MVP API (v0.1) — The collections surface covers ACH debit collections. Additional collection rails will be added in future releases.

What Are Collections?

Collections are initiated inbound pull payments. They debit an external account (via a counterparty’s payment method) and credit an OpenFX account. This is the inverse of a standard payment, where you push funds out to a counterparty.
External Account (counterparty)
  |
  |  <-- Collection pulls funds
  |
  v
Your OpenFX Account (credited)
Collections are a first-class resource in the OpenFX API with their own lifecycle, endpoints, and ID prefix (col_). They are distinct from outbound payments.

Currently Supported Rails

Collections currently support ACH debit only. Additional pull-payment rails will be added in future versions.
RailEndpointSEC CodesSettlement
achPOST /collections/achWEB, PPD, CCD1-2 business days (standard), same day

Collection Lifecycle

Every collection progresses through a defined set of statuses:
StatusDescription
pendingCollection created, not yet submitted to the rail.
submittedSubmitted to the payment rail for processing.
processingThe rail is processing the debit.
completedFunds received and credited to the destination account.
returnedThe debit was returned by the external bank (e.g., insufficient funds, unauthorized).
failedCollection failed before completing.
ACH return window: ACH debit collections can be returned for up to 60 calendar days after settlement. Even after a collection reaches completed status, a return may arrive. Always subscribe to the collection.returned webhook event and design your reconciliation logic to handle late returns.

Two Approaches to Creating Collections

Like payments, OpenFX provides both a unified and a rail-specific endpoint for collections.

Unified endpoint

POST /collections accepts any supported collection rail. You specify the rail field in the request body.

Rail-specific endpoint

POST /collections/ach provides direct access to ACH debit with rail-native parameters (SEC code, same-day vs standard). The rail field is implicit in the URL.
Use the rail-specific endpoint when you always collect via a single rail and want the tightest request schema with rail-native fields. Use the unified endpoint if you plan to support multiple collection rails as they become available.

Creating a Collection

curl -X POST https://sandbox.api.openfx.com/v1/collections \
  -H "Authorization: Bearer $API_KEY" \
  -H "X-Signature: $SIGNATURE" \
  -H "X-Timestamp: $TIMESTAMP" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "destinationAccountId": "acc_01953e1a5f4b7002",
    "counterpartyId": "cpt_01953e1a5f4b7004",
    "paymentMethodId": "pm_01953e1a5f4b7300",
    "rail": "ach",
    "amount": {
      "currency": "USD", "value": "250000"
    },
    "reference": "INV-2026-0042",
    "purpose": "Invoice payment"
  }'
The response returns the full collection resource:
{
  "id": "col_01953e1a5f4b7e00",
  "customerId": "cus_01953e1a5f4b7000",
  "destinationAccountId": "acc_01953e1a5f4b7002",
  "counterpartyId": "cpt_01953e1a5f4b7004",
  "paymentMethodId": "pm_01953e1a5f4b7300",
  "rail": "ach",
  "amount": {
    "currency": "USD",
    "exponent": 2,
    "value": "250000",
    "displayValue": "2500.00"
  },
  "direction": "inbound",
  "status": "pending",
  "reference": "INV-2026-0042",
  "purpose": "Invoice payment",
  "metadata": {},
  "createdAt": "2026-02-25T10:00:00Z",
  "updatedAt": "2026-02-25T10:00:00Z"
}

Listing Collections

curl -X GET "https://sandbox.api.openfx.com/v1/collections?status=completed&limit=20" \
  -H "Authorization: Bearer $API_KEY" \
  -H "X-Signature: $SIGNATURE" \
  -H "X-Timestamp: $TIMESTAMP"

Key Collection Fields

FieldTypeDescription
idstringCollection ID with col_ prefix (e.g., col_01953e1a5f4b7e00)
destinationAccountIdstringThe OpenFX account where collected funds are credited
counterpartyIdstringThe external party whose account is being debited
paymentMethodIdstringThe counterparty’s payment method (must support debit)
railenumCurrently only ach
amountMoneyThe amount to collect ({ "currency": "USD", "value": "250000" })
directionenumAlways inbound for collections
statusenumCurrent lifecycle status
totalCreditAmountMoneyNet amount credited after fees
feesFeeBreakdownFee details if applicable
referencestringYour payment reference for reconciliation
achReturnCodestringACH return reason code (present when status is returned)

API Reference