Accept an ACH Payment

Charge a customer's bank account via ACH in a single API call

Accepting an ACH payment debits a customer's bank account and credits your merchant account over the ACH network. It's the bank-account counterpart to a card Sale: the customer pays you for goods or services, on a lower-cost rail. You submit it on the same payment API — set tenderType to ACH, pass the bank account, and set the entry class that matches your authorization. For the full field list, jump to the Request reference.

Moving funds already inside your program (funding a Passport Account, disbursing, or a treasury-level pull) is a different job — see Treasury → Collections.

Common use cases

  • Take a bank-account payment at online checkout instead of a card
  • Collect an invoice or bill payment directly from a customer's bank account
  • Accept recurring bank-account payments for subscriptions or installments

Make your first payment

The fastest way to see it work: charge a bank account with the minimal fields below. The full set of options is in the Request reference.

POST /checkout/v3/payment
Content-Type: application/json
x-api-key: YOUR_API_KEY

{
  "merchantId": 1000157980,
  "amount": 120.00,
  "tenderType": "ACH",
  "paymentType": "Sale",
  "entryClass": "PPD",
  "bankAccount": {
    "name": "Alex Johnson",
    "routingNumber": "021000021",
    "accountNumber": "1234567890",
    "type": "Checking"
  },
  "source": "API"
}

You'll get back a 201 Created. Because ACH isn't approved instantly by an issuer, the payment starts as status: PendingACH and settles over the following business days. Store the returned id (use it to retrieve or void the payment before it settles) and paymentToken (use it for follow-up refunds after settlement).

🚧

PENDING-PUBLISH

The example response below mirrors the create-payment schema (tenderType, amount, status, type, id, paymentToken). Confirm the exact ACH response echo — masked bankAccount, and any ACH-specific fields (e.g. achIndicator, achAuthorizationEmail) — against a live sandbox ACH call before publish.

{
  "created": "2026-08-20T07:11:30.9Z",
  "id": 4100000000869901,
  "paymentToken": "PYVrf077uthlfkIiAMXMEE0BJECoXkrf",
  "merchantId": 1000157980,
  "tenderType": "ACH",
  "amount": "120.00",
  "entryClass": "PPD",
  "bankAccount": {
    "name": "Alex Johnson",
    "type": "Checking"
  },
  "status": "PendingACH",
  "type": "Sale"
}

The endpoint is documented in the API reference at POST /checkout/v3/payment.

📘

Use replayId for safe retries

Accept Payments uses the replayId field in the request body for safe retries; there's no separate header. Send a unique replayId per payment, and if a request with the same value arrives again, we return the original response instead of debiting the account twice. See Idempotent Requests.

📘

Get authorization before you debit

An ACH debit pulls money from a customer's account, so NACHA requires their authorization. Set entryClass to reflect how you obtained it (PPD, WEB, TEL, CCD, CTX), keep the proof, and be ready to produce it on request.


Scenarios

Every ACH payment follows the same payment lifecycle, starting at PendingACH. The only thing that changes per scenario is how you supply the bank account, so pick the one that matches the problem you're solving.

sequenceDiagram
    participant You as Your Application
    participant PCE as PCE
    participant Bank as Customer's Bank

    You->>PCE: POST /checkout/v3/payment (tenderType: ACH)
    PCE->>PCE: Validate request + authorization
    PCE-->>You: 201 Created (status: PendingACH)
    PCE->>Bank: Submit ACH debit to network
    Note over PCE: Settlement window (business days)
    PCE-->>You: Webhook (settled or returned)

Before you begin (all scenarios)

  • Your merchant account is active and enabled for ACH acceptance.
  • You hold the customer's authorization to debit their account.

Scenario 1: Charge a bank account entered at checkout

(raw bank details passed inline)

Use this when a customer enters their bank details to pay you and you don't save them. Pass the routing number, account number, holder name, and account type directly in bankAccount, and set entryClass to match your authorization.

You'll also need: the customer's routing number, account number, account type, and authorization.

Request

POST /checkout/v3/payment
Content-Type: application/json
x-api-key: YOUR_API_KEY

{
  "merchantId": 1000157980,
  "amount": 250.00,
  "tenderType": "ACH",
  "paymentType": "Sale",
  "entryClass": "WEB",
  "bankAccount": {
    "name": "Alex Johnson",
    "routingNumber": "021000021",
    "accountNumber": "1234567890",
    "type": "Checking"
  },
  "customerName": "Alex Johnson",
  "customerCode": "01455",
  "source": "API"
}

Scenario 2: Collect a business (B2B) payment

(corporate account, CCD entry class)

Use this to collect from a business customer's corporate account — for example, an invoice paid by another company. Set entryClass to CCD (or CTX if you're sending structured remittance addenda).

You'll also need: the business's authorization to debit their corporate account.

Request

POST /checkout/v3/payment
Content-Type: application/json
x-api-key: YOUR_API_KEY

{
  "merchantId": 1000157980,
  "amount": 4200.00,
  "tenderType": "ACH",
  "paymentType": "Sale",
  "entryClass": "CCD",
  "bankAccount": {
    "name": "Northwind Supplies LLC",
    "routingNumber": "021000021",
    "accountNumber": "9987654321",
    "type": "Checking"
  },
  "customerCode": "INV-4471",
  "source": "API"
}

Track the payment

An ACH payment starts at PendingACH and doesn't confirm on submit, so follow it rather than assuming success. Retrieve it with GET /checkout/v3/payment/{id}, or subscribe to webhooks.

🚧

PENDING-PUBLISH

Confirm the ACH webhook event names for settlement and return (the card flow uses PaymentSuccess / PaymentFail; ACH return handling may use different events) against Webhook Event Types before publish.

The statuses, the flow to settlement, and the webhook events all live in Payment Lifecycle and Webhook Event Types.


Request reference

The complete set of fields for the create-payment request when tenderType is ACH. Scenarios above use subsets of these.

Core parameters

ParameterRequiredDescription
merchantIdYour PCE merchant identifier that receives the payment.
amountAmount to charge, in the account currency (USD by default).
paymentTypeSet to Sale.
tenderTypeSet to ACH.
bankAccountThe bank account to debit. Required when tenderType is ACH. See Bank account fields.
entryClassACH entry class (SEC code): PPD, WEB, TEL, CCD, or CTX. Required when tenderType is ACH.
replayIdRecommendedYour unique retry key. Retrying with the same value returns the original response instead of debiting again. See Idempotent Requests.
customerNameOptionalCustomer's full name.
customerCodeOptionalYour reference for the customer, included in settlement.
sourceOptionalOrigin of the payment. Possible values: API, QuickPay, Recurring, Link2Pay, Terminal.

Bank account fields

Required when tenderType is ACH.

ParameterRequiredDescription
bankAccount.routingNumber9-digit bank routing number.
bankAccount.accountNumberBank account number.
bankAccount.nameFull name of the bank account holder.
bankAccount.typeChecking or Savings.

Validation

The prerequisites above are the validations, and PCE enforces them when you submit. A submission is checked synchronously; if a check fails, the request returns an error and no payment is created. Submission checks:

  • Required fields are present and correctly formatted (routing number, account number, account type, entry class).
  • Your merchant account is enabled for ACH acceptance.
  • Authorization for the debit is present.

Conditions that can only be judged once the debit is in flight — insufficient funds, a closed account, or a bank return — surface after submission as the payment moves out of PendingACH. See Payment Lifecycle.


Statuses

An ACH payment returns PendingACH on submit and resolves over the following business days as the debit settles or is returned. Accept Payments uses the shared Payment Lifecycle for every status and how a payment progresses to settlement.

🚧

PENDING-PUBLISH

Document the ACH settled/returned terminal states and typical timing on Payment Lifecycle (confirm against the MXM status model and ACH return codes) before publish.


Go live

The shared pre-production checklist (production credentials, webhook subscription, idempotency, and sandbox testing) is in Getting Started. Specific to ACH, also confirm:

  • ACH acceptance is enabled for your merchantId.
  • You hold a valid authorization for every debit and set the matching entryClass.
  • You handle the PendingACH → settled/returned flow rather than treating the payment as final on submit.
  • You generate a unique replayId per payment for safe retries.

Best practices

General practices (set a unique replayId, subscribe to webhooks, test in sandbox) are in Getting Started. Specific to ACH:

PracticeDescription
Set the correct entry classMatch entryClass to how you obtained authorization (PPD/WEB/TEL consumer, CCD/CTX business).
Retain authorizationKeep proof of the customer's authorization; you may need to produce it on request.
Verify bank detailsCheck the routing and account numbers before submitting to reduce returns.
Wait for settlementDon't fulfil high-value orders until the ACH payment clears PendingACH.

Next steps

See also



Did this page help you?
.readme-logo { display: none !important; }