The Routable connector polls a Routable workspace and surfaces settings accounts, companies (counterparties), payables, and receivables. It also initiates outbound payables in response to Formance CreateTransfer and CreatePayout workflows.
Prerequisites#
You need a Routable account and an API key. Decide upfront which team member will own payables initiated through Formance — Routable requires an acting_team_member on every payable. Set it per-connector via config, or per-request via metadata; see Initiating payouts and transfers.
Make sure to create an API key dedicated to Formance. Doing so will improve your auditability and security and will allow you to revoke access to Formance at any time if needed.
Installation#
curl -X POST $FORMANCE_API_URL/api/payments/v3/connectors/install/routable \
-H "Content-Type: application/json" \
-d @config.jsonConfiguration fields#
| Field | Required | Default | Purpose |
|---|---|---|---|
apiKey | yes | — | Routable bearer token. Sent as Authorization: Bearer <apiKey> on every request. |
endpoint | no | https://api.routable.com | API root. Use https://api.sandbox.routable.com for the Routable sandbox. |
actingTeamMember | no | "" | Default Routable team member ID for payable creation. Optional at the connector level — callers can override per-request via the com.routable.spec/acting_team_member metadata key. If neither is set, payable creation fails with a clear validation error before any HTTP call. |
pollingPeriod | no | 30m | Sync cadence (minimum 20m). |
The connector validates the API key at install with a GET /v1/settings/accounts?page=1&page_size=1 probe — bad keys fail install rather than the first FETCH_ACCOUNTS cycle.
Capabilities#
FETCH_ACCOUNTS— settings accounts viaGET /v1/settings/accounts.FETCH_BALANCES— settings-accountavailable_amountviaGET /v1/settings/accounts/{id}.FETCH_EXTERNAL_ACCOUNTS— companies (counterparties) viaGET /v1/companies.FETCH_PAYMENTS— payables and receivables viaGET /v1/payablesandGET /v1/receivables.CREATE_TRANSFERandCREATE_PAYOUT— bothPOST /v1/payables(transfers are payables with theTRANSFERtype).
Webhooks, bank-account creation, and reversals are not implemented.
Routable caps API throughput at roughly 1.5 payouts per second. The connector declares this via PluginWithPayoutThrottle, so the platform throttles CreatePayout / CreateTransfer through a dedicated Temporal task queue. See Operations → Connector reliability.
Account model#
Every Connectivity internal account is one Routable settings account from GET /v1/settings/accounts. The reference is the settings-account ID; defaultAsset is the account currency. EXTERNAL accounts come from /v1/companies (the payee surface), refreshed on a 24-hour cadence to respect upstream rate limits. See Accounts for the cross-connector model.
Asset model#
Routable returns ISO currency codes (USD, EUR, KWD). Formatted to UMN via currency.FormatAsset — USD/2, EUR/2, KWD/3. Unsupported currencies are skipped (logged) without dropping the rest of the page. Amounts arrive as decimal strings and convert to integer minor units with half-up rounding.
Status mapping#
Routable payable statuses → Connectivity Payment statuses:
Routable status | Payment status |
|---|---|
draft, ready_to_send, pending, scheduled, initiated, processing, in_transit, awaiting_delivery | PENDING |
completed, paid, externally_paid, delivered | SUCCEEDED |
failed, returned, nsf | FAILED |
stopped, canceled, cancelled, voided | CANCELLED |
expired | EXPIRED |
| anything else (or empty) | UNKNOWN |
Comparison is case-insensitive. Payment scheme is mapped from delivery_method: ach_* → ACH, everything else → OTHER.
Metadata keys#
Under com.routable.spec/. Full list in the connector's MAPPINGS.md; highlights:
Account metadata (internal accounts)#
object, type, is_valid, currency_code, plus type_details.account_type, type_details.bank_name, type_details.account_number, type_details.routing_number.
External-account metadata (companies)#
object, type, status, country_code, is_vendor, is_customer, is_archived, external_id, business_name, display_name, plus the structured registered_address.* keys.
Payment metadata#
For payables (PAYOUT) and receivables (PAYIN): type, delivery_method, status, external_id, memo, reference. Two correlation aliases also land on every Formance-initiated Payment:
com.routable.spec/payment_initiation_reference— the originating PaymentInitiation reference (absent on payables created in Routable's UI).com.routable.spec/payable_id— the Routable payable UUID (mirrorsPayment.Reference).
See Correlating an initiation with the synced payment.
Initiating payouts and transfers#
CreateTransfer and CreatePayout translate the Formance PSPPaymentInitiation into a POST /v1/payables. Most fields come from the structured initiation; a few Routable knobs are exposed via metadata:
| Metadata key | Required | Default | Maps to | Purpose |
|---|---|---|---|---|
com.routable.spec/type | no | ach | type | Payable rail (ach, wire, check, international, external, vendor_choice). |
com.routable.spec/delivery_method | no | ach_standard | delivery_method | Specific delivery option (ach_standard, ach_same_day, wire, check, …). Must be compatible with type. |
com.routable.spec/acting_team_member | conditional | connector config | acting_team_member | Routable team member ID initiating the payable. Required at request time — from either the connector config or this key. |
com.routable.spec/external_id | no | "" | external_id | Caller-supplied external reference (idempotent lookup key on Routable's side). |
com.routable.spec/line_item_description | no | PSPPaymentInitiation.Description, then "Payment <reference>" | line_items[0].description | Description on the auto-generated single-line item. Routable v1 requires a non-empty value. |
The Formance PaymentInitiation.Reference is sent as the Idempotency-Key header — Routable returns the original payable on retries with the same key, which Formance's create-then-poll workflow relies on.
Async response handling#
POST /v1/payables answers in two shapes:
| Routable response | Behaviour |
|---|---|
202 Accepted (async) | PollPayoutStatus / PollTransferStatus scheduled against GET /v1/payables/{id}; the first successful poll links the PaymentInitiation to a Payment and ends the loop. |
201 Created with a terminal status (completed, failed, cancelled, expired) | Payment returned immediately. |
201 Created with a non-terminal status | Polling round scheduled; first poll returns the Payment. |
Once linked, further transitions (PENDING → PROCESSING → SUCCEEDED) flow through the periodic FETCH_PAYMENTS schedule.
Correlating an initiation with the synced payment#
Initiating a payable through Formance produces two rows:
- A
PaymentInitiationkeyed by the reference you supplied (e.g.payout-acmecorp-20260506-172725). - A
PSPPaymentkeyed by Routable's payable UUID.
They're linked at the engine level. To resolve one from the other:
Pagination and recovery#
List endpoints are 1-indexed page + page_size (cap 100). The connector checkpoints pagination opaquely between cycles, so a mid-cycle worker crash resumes deterministically — no row double-billed or dropped.
The payments fetcher walks payables, then receivables, then advances its cycle watermark. The watermark stays immutable for the full duration of a cycle to avoid the page-2-tighter-than-page-1 race that would drop rows whose status_changed_at lands between page boundaries.
Routable's status_changed_at.gte filter is inclusive, so cycle-boundary rows re-emit each cycle. The engine dedupes by PSPPayment.Reference — wasted bandwidth, never a correctness issue.
Known gaps#
- Webhooks — Routable exposes a webhook product upstream; the connector uses polling. Subscription shape in upstream
MAPPINGS.md §6.4. - Bank-account creation — companies and delivery methods are pulled, not created. Manage new companies in Routable's UI.
- Reversals —
ReverseTransferandReversePayoutare not wired. - Throughput cap — Routable caps API throughput at ~1.5 payouts/s. The platform throttles outbound workflows via a dedicated task queue; bursts queue under load rather than fail.