Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.encoreos.io/llms.txt

Use this file to discover all available pages before exploring further.

Version: 1.0.0
Created: 2026-02-23
Updated: 2026-02-24
Status: πŸ—οΈ Scaffolded (Phase 1 β€” gateway integration pending sandbox credentials)
Owner: FA (Finance & Accounting)

Overview

This document defines the integration contract between Encore Health OS’s FA module and Ramp for corporate card and spend management. Ramp provides spend management, corporate cards, ERP/accounting sync (vendors, transaction coding, payables), and an open developer API. This integration enables syncing card transactions into Encore Health OS for coding, approval workflows, and reconciliation.

Quick Reference

I need to…PatternLocation
Connect Ramp to Encore Health OSOAuth callback or API key registrationEdge function ramp-connect; table fa_ramp_connections
Sync card transactionsIdempotent sync by Ramp transaction IDEdge function ramp-sync; table fa_card_transactions
Disconnect RampRevoke tokens, set status disconnectedEdge function ramp-disconnect
Verify webhook eventsSignature verification per Ramp docsEdge function ramp-webhook; store RAMP_WEBHOOK_SECRET

Decision Trees / Pattern Library

  • OAuth vs API key: Use OAuth when the Connect UX involves user authorization in the browser (recommended per Ramp guide). Use API key for server-only or headless sync when OAuth is not required.
  • Pagination: Ramp list endpoints use limit/page or cursor; loop until all pages are fetched for the org’s date range. See v1/pagination.
  • Deduplication: Use fa_card_transactions.ramp_transaction_id as unique key; unique index on that column. On conflict, skip or update per product requirement (spec recommends skip for idempotency).

Common Mistakes

PitfallMitigation
Skipping webhook signature verificationAlways verify signature using RAMP_WEBHOOK_SECRET per v1/api/webhooks; reject unsigned or invalid payloads.
Token refresh not handledProactively refresh before token_expires_at or reactively on 401; set reauth_required when refresh fails.
Duplicate transactions importedEnforce unique index on fa_card_transactions.ramp_transaction_id; use upsert/skip on conflict.
RLS misconfigurationUse SECURITY DEFINER helpers; ensure UPDATE policies include WITH CHECK on organization_id.

Pre-Flight Checklist

  • Env vars set: RAMP_CLIENT_ID, RAMP_CLIENT_SECRET, RAMP_API_KEY (if used), RAMP_WEBHOOK_SECRET, RAMP_ENVIRONMENT.
  • DB index on fa_card_transactions.ramp_transaction_id for deduplication.
  • Test sandbox connection (request access via Ramp partnerships intake) before production.

Integration Pattern

Type: External API Integration via Edge Functions
Direction: Outbound (Encore Health OS β†’ Ramp) + Inbound (Webhooks if supported by Ramp)
Authentication: OAuth (recommended for Connect UX) and/or API key; see Ramp docs.ramp.com/developer-api/v1/guides/oauth

Authentication Requirements

Environment Matrix

EnvironmentAccessNotes
SandboxRequest via Ramp partnerships intakeTest data; develop without production credentials
ProductionAPI key from Ramp onboarding formActive Ramp account required

Credentials

CredentialPurposeStorage
RAMP_CLIENT_IDOAuth app identificationSupabase Secret
RAMP_CLIENT_SECRETOAuth app secretSupabase Secret
RAMP_API_KEYServer-to-server API access (if used)Supabase Secret
RAMP_WEBHOOK_SECRETWebhook signature verification (if Ramp provides webhooks)Supabase Secret
RAMP_ENVIRONMENTsandbox | productionEnvironment variable (non-sensitive config)
Exact auth mechanism (OAuth scopes, API key headers) MUST be confirmed from live Ramp API documentation at docs.ramp.com/developer-api.

API Endpoints

Ramp API (Outbound)

Reference: docs.ramp.com/developer-api
AreaPurposeDoc URL
OAuthAuthorization and token exchangev1/guides/oauth
TransactionsList/sync card transactions; filters: date range, merchant, statusv1/api/transactions
PaginationCursor-based: page_size (2-100) + start (last entity ID)v1/pagination
Card ProgramsList card programs (optional Phase 1)v1/api/card-programs
WebhooksPush events (e.g. transaction.created); verify signature per docsv1/api/webhooks
ReimbursementsOut of scope Phase 1v1/api/reimbursements
Implementation must use the live API reference for exact paths, methods, request/response schemas, pagination parameters, and webhook payload/shape.

Edge Functions (Inbound/Internal)

FunctionMethodPurpose
ramp-connectPOSTComplete OAuth callback or register API key; create/update org connection
ramp-syncPOSTSync card transactions for the organization’s Ramp connection
ramp-disconnectPOSTRevoke tokens, set connection status to disconnected
ramp-webhookPOSTHandle Ramp webhook events; verify signature per v1/api/webhooks

Transactions Sync (Pagination and Deduplication)

  • Pagination: Cursor-based: page_size (2-100, default 20) + start (ID of last entity). Loop until no more results. See v1/pagination. Confirmed 2026-02-24.
  • Deduplication: Use Ramp transaction ID as unique key; unique index on fa_card_transactions.ramp_transaction_id. On conflict (same ramp_transaction_id), either skip or update existing row per product requirement (spec recommends skip for idempotency).
  • Incremental sync: If Ramp supports filtering by updated_at or similar, use it to reduce payload; otherwise full date-range fetch with deduplication is acceptable for Phase 1.

Data Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Encore Health OS    β”‚                 β”‚   Ramp API      β”‚
β”‚   Frontend      β”‚                 β”‚   (docs.ramp.com)β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚                                    β”‚
         β”‚ 1. Connect Ramp (OAuth or config) β”‚
         β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Ί β”‚
         β”‚                                    β”‚
         β”‚ 2. Tokens / success                β”‚
         │◄────────────────────────────────────
         β”‚                                    β”‚
         β”‚ 3. POST /ramp-connect              β”‚
         β”‚    (to Edge Function)              β”‚
         β–Ό                                    β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                           β”‚
β”‚   ramp-connect   β”‚ 4. Store connection       β”‚
β”‚   Edge Function β”‚     in fa_ramp_connections β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜                           β”‚
         β”‚                                    β”‚
         β”‚ 5. Sync requested                  β”‚
         β–Ό                                    β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” 6. GET/POST transactions β”‚
β”‚   ramp-sync      β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Ί β”‚
β”‚   Edge Function  β”‚                          β”‚
β”‚                  β”‚ 7. Transaction data      β”‚
β”‚                  │◄──────────────────────────
β”‚                  β”‚                          β”‚
β”‚                  β”‚ 8. Store in fa_card_transactions
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β”‚ 9. (Optional) Webhook from Ramp
         │◄───────────────────────────────────
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   ramp-webhook  β”‚ 10. Verify signature, trigger sync or update status
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Webhook Events

Ramp supports webhooks (see v1/api/webhooks). Implementation must confirm the following from live docs:
  • Signature verification: Implement per Ramp’s webhook docs (e.g. HMAC, webhook secret header, or JWT); store RAMP_WEBHOOK_SECRET in Supabase secrets.
  • Replay protection: Use timestamp window if Ramp provides one (e.g. reject if t outside Β±3 min).
  • Event types: e.g. transaction.created, connection/revoked – document exact event names and payload fields when implementing; map to actions below.
  • Actions: Update connection status, trigger incremental sync, or mark transactions; never log full tokens or card numbers.
  • Retries: Ramp retries webhook delivery up to 10 times for 429/5xx responses. Endpoint must respond within 10 seconds. Implement idempotency using event id to handle duplicate deliveries. Confirmed 2026-02-24.

Database Schema

New Tables

fa_ramp_connections
  • id UUID PK
  • organization_id UUID FK, UNIQUE (one connection per org)
  • Ramp entity/account identifier(s)
  • Token columns (encrypted at rest) or reference to secrets
  • connection_status TEXT – connected | disconnected | error | reauth_required
  • last_synced_at TIMESTAMPTZ
  • created_at, updated_at
  • RLS via SECURITY DEFINER helper on organization_id
fa_card_transactions
  • id UUID PK
  • organization_id UUID FK
  • ramp_connection_id UUID FK
  • ramp_transaction_id TEXT UNIQUE (deduplication)
  • Amount, currency, date, merchant, status, etc. (match Ramp API response)
  • GL/vendor coding columns (nullable)
  • created_at, updated_at
  • RLS on organization_id
  • Unique index on ramp_transaction_id

Modified Tables

fa_module_settings
  • ramp_integration_enabled BOOLEAN DEFAULT false

Security Considerations

Token Storage

  • App-level credentials (RAMP_CLIENT_ID, RAMP_CLIENT_SECRET, RAMP_WEBHOOK_SECRET) are stored in Supabase Secrets.
  • Per-organization OAuth tokens (access_token, refresh_token) are stored in encrypted DB columns scoped by organization_id (not in shared Supabase Secrets).
  • Tokens are never exposed to frontend.
  • Edge functions access per-org tokens via service-role queries filtered by organization_id.

Multi-Tenancy

  • All Edge Function queries include organization_id filter
  • RLS policies on fa_ramp_connections and fa_card_transactions enforce organization isolation
  • Audit logging for connect, sync, disconnect, and webhook events

PHI/PII

  • Card transaction metadata (merchant, amount) is not PHI
  • Do not send or log PHI to Ramp; do not log full card numbers or tokens

Error Handling

Ramp API Errors

HTTP StatusMeaningAction
401Unauthorized / token invalidSet status to reauth_required or disconnect
403Forbidden / access revokedSet status to disconnected
429Rate limitedExponential backoff, retry
5xxRamp server errorLog, retry with backoff

Retry Strategy

  • Exponential backoff for 429 and 5xx uses 1s, 2s, 4s, 8s, 16s; any Retry-After header takes precedence.
  • Do not retry 4xx (except 429) indefinitely.
  • Rate limit: 200 requests per 10-second rolling window (confirmed from Ramp docs 2026-02-24). Apply the same backoff sequence above on 429 responses.
  • Align with FA-20 Plaid pattern: same backoff array and break on non–rate-limit errors.

Logging

Allowlisted Fields

  • organization_id
  • ramp_connection_id (not tokens)
  • transactions_synced, transactions_skipped
  • sync_duration_ms
  • Webhook event type (not payload secrets)

Prohibited

  • access_token, refresh_token, API keys
  • Full card numbers or sensitive merchant PII

Testing Strategy

  • Unit: Ramp client and transaction mapping (mocked responses); webhook signature verification with test secret.
  • Integration: Connect and sync against Ramp sandbox (request access via Ramp Partnerships Intake); test pagination, date-range filter, and deduplication.
  • E2E: Connect β†’ Sync β†’ View transactions (when UI exists).
  • RLS: Verify tenant isolation on fa_ramp_connections and fa_card_transactions.

Implementation Confirmation Checklist

Before marking integration complete, confirm with live Ramp docs and sandbox:
  • OAuth: scopes, token refresh, and redirect/callback URL requirements.
  • Transactions: exact path, query params (date range, status, limit, page/cursor), response schema; map all required fields to fa_card_transactions.
  • Webhooks: event types, payload shape, signature algorithm and header; implement verification and idempotent handling.
  • Rate limit: 200 requests per 10-second rolling window (confirmed 2026-02-24); honor Retry-After header.
  • Sandbox: request and obtain sandbox credentials; document test entity/card data if provided.

Rollback Strategy

  • Feature flag ramp_integration_enabled disables UI and sync
  • Disabling flag hides Ramp options; existing data remains; no destructive migration required
  • Optional: soft-delete or status column on fa_ramp_connections for reversible disconnect

References