Overview

ACH (Automated Clearing House) is the workhorse of US domestic payments. It handles billions of transactions annually for payroll, vendor payments, recurring billing, and general-purpose transfers. OpenFX supports both standard ACH (1-3 business day settlement) and same-day ACH (settlement within hours on the same business day). ACH payments are created through the POST /payments/ach endpoint with a us_bank payment method on the counterparty.
ACH is a batch-processed network. Payments are grouped and submitted in batches to the Federal Reserve, which is why settlement takes hours or days rather than seconds. Same-day ACH has specific cutoff windows that vary by institution.

ACH types

The achType field controls settlement speed:
TypeSettlementCutoffMax amountUse case
standard1-3 business days21:00 UTCNo per-transaction limitPayroll, vendor payments, recurring transfers
same_daySame business day (hours)Earlier cutoff windows$1,000,000 per transactionUrgent payments, time-sensitive disbursements
If you do not specify achType, the default is standard. Use same_day only when you need faster settlement — it typically incurs a higher fee.

SEC codes

The SEC (Standard Entry Class) code identifies the type of ACH transaction and determines the authorization requirements. The secCode field accepts:
CodeNameDescriptionTypical use
WEBInternet-InitiatedAuthorized via the internetOnline payments, e-commerce, consumer transfers
PPDPrearranged Payment and DepositConsumer transactions with a standing authorizationDirect deposit, recurring consumer payments
CCDCorporate Credit or DebitBusiness-to-business transactionsCorporate vendor payments, intercompany transfers
CTXCorporate Trade ExchangeBusiness payments with addenda recordsTrade payments with invoice data, EDI-linked payments
Choosing the wrong SEC code can result in NACHA violations. Use CCD or CTX for business-to-business payments and WEB or PPD for consumer payments. If unsure, CCD is the safest choice for corporate payments.
The SEC code determines the authorization model for the ACH transaction. Business-to-business payments should use CCD (single payment) or CTX (payment with addenda/invoice data). Consumer-facing payments should use WEB (internet-authorized) or PPD (pre-authorized recurring). Mismatched SEC codes can result in NACHA rule violations and return code R17 (file record edit criteria).

Prerequisites

Before creating an ACH payment, you need:
  1. An active customer (KYB approved) with a funded USD account (demand_deposit type)
  2. A counterparty with a us_bank payment method containing:
    • routingNumber — 9-digit ABA routing number
    • accountNumber — Bank account number
    • bankAccountTypechecking or savings

Creating an ACH payment

curl -X POST https://sandbox.api.openfx.com/v1/payments/ach \
  -H "Authorization: Bearer $API_KEY" \
  -H "X-Signature: $SIGNATURE" \
  -H "X-Timestamp: $TIMESTAMP" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "sourceAccountId": "acc_01953e1a5f4b7002",
    "counterpartyId": "cpt_01953e1a5f4b7004",
    "paymentMethodId": "pm_01953e1a5f4b7300",
    "amount": {
      "currency": "USD", "value": "250000"
    },
    "achType": "standard",
    "secCode": "CCD",
    "reference": "Invoice #INV-2026-0087",
    "metadata": {
      "invoiceId": "INV-2026-0087",
      "department": "accounts_payable"
    }
  }'
The response returns a Payment resource with status: created. The payment will progress through processing and eventually reach completed or returned.

Same-day ACH

To send a same-day ACH payment, set achType to same_day:
curl -X POST https://sandbox.api.openfx.com/v1/payments/ach \
  -H "Authorization: Bearer $API_KEY" \
  -H "X-Signature: $SIGNATURE" \
  -H "X-Timestamp: $TIMESTAMP" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "sourceAccountId": "acc_01953e1a5f4b7002",
    "paymentMethodId": "pm_01953e1a5f4b7300",
    "amount": {
      "currency": "USD", "value": "1500000"
    },
    "achType": "same_day",
    "secCode": "CCD",
    "reference": "Urgent vendor payment"
  }'
Same-day ACH has a per-transaction limit of $1,000,000 set by NACHA. Payments exceeding this amount must use standard ACH or a different rail like Fedwire.

ACH returns

ACH payments can be returned by the receiving bank for various reasons. When a return occurs, the payment transitions to returned status and the returnCode field on the Payment provides the NACHA return reason.

Common return codes

CodeReasonDescriptionAction
R01Insufficient fundsNot enough funds in the receiver’s accountRetry later or contact the counterparty
R02Account closedThe receiver’s account is closedUpdate the payment method with a new account
R03No account / unable to locateRouting/account number does not match a valid accountVerify counterparty payment method details
R04Invalid account numberAccount number structure is invalidCorrect the account number on the payment method
R10Customer advises unauthorizedThe receiver disputes the transactionReview authorization and respond to dispute
R29Corporate customer advises not authorizedCorporate counterparty disputes the transactionReview authorization agreement
ACH returns can arrive up to 2 business days after settlement for standard returns and up to 60 calendar days for unauthorized transaction disputes (R10, R29). Always monitor the payment.returned webhook event for timely notification.

Handling returns

When a payment is returned, you receive a payment.returned webhook and the payment status changes to returned. You can then decide how to respond:
# Get the returned payment to see the return code
curl -X GET https://sandbox.api.openfx.com/v1/payments/ach/pmt_01953e1a5f4b7005 \
  -H "Authorization: Bearer $API_KEY" \
  -H "X-Signature: $SIGNATURE" \
  -H "X-Timestamp: $TIMESTAMP"

Payment lifecycle

created -> processing -> completed
                      -> returned
                      -> failed
StatusDescription
createdPayment accepted and queued for processing
processingPayment submitted to the ACH network
completedFunds successfully delivered
returnedPayment returned by the receiving bank (see return codes above)
failedPayment could not be processed (e.g., insufficient funds in source account)

Provider mapping reference

Under the hood, POST /payments/ach maps to the banking provider’s ACH origination endpoint. The Platform API normalizes provider-specific field names and status values into the OpenFX schema. Field mapping:
OpenFX FieldProvider FieldNotes
sourceAccountIddeposit_account_idThe funded account to debit
paymentMethodIdcounterparty_us_bank_account_idThe counterparty’s bank account
amount (decimal string)amount.value (string cents) + amount.currency="USD"Amount conversion from OpenFX to provider format
secCodesec_codeSEC code passed through directly
referencecompany_discretionary_dataFree-text reference for the counterparty
Status mapping:
Provider StatusOpenFX Status
PENDINGprocessing
SETTLEDcompleted
FAILEDfailed
RETURNEDreturned
The Idempotency-Key header is mapped to the provider’s idempotency header automatically. You do not need to handle provider-specific header formats.

API reference