States and notifications
An ACH transfer has eight states. Only its creation publishes a transfer event; the later moves are read from the file events and from the transfer itself.
The states
status | Meaning | Moves to |
|---|---|---|
pending | Accepted. A credit has its hold. The entry waits for a file. | batched, or cancelled for an international transfer |
held_for_review | Sanctions screening was not clear, or the fraud rules held a credit. No file takes the entry. | pending, rejected, or cancelled for an international transfer |
rejected | Refused at review. The hold is released. | Final |
cancelled | Withdrawn before it joined a file. Only an international transfer can be cancelled. The hold is released. | Final |
batched | In a file that is being sent. trace_number and file_id are set. | sent |
sent | The operator acknowledged the file. | settled |
settled | Posted to the ledger. journal_id is set and a credit's hold is released. | returned |
returned | The RDFI returned the entry and the posting was reversed. return_code, return_reason and reversal_journal_id are set. | Final |
If the operator does not acknowledge a file, its entries stay batched and the file is sent again. A return reported for an entry that is not yet settled answers payments.transfer_not_settled.
Review
A transfer held by screening is decided at POST /transfers/ach/{id}/review with a decision of approve or reject, by a staff or service token that carries payments:write. Approval puts it back to pending for the next file. On a credit the fraud rules run first, and they can keep it held. Rejection releases the hold. A transfer in any other state answers payments.not_reviewable. An Idempotency-Key is optional here, and a repeat under the same key returns the recorded decision.
A credit the fraud rules hold has a fraud review, found with GET /fraud-reviews?payment_id=. While that review is open the route above answers payments.fraud_review_open. Only the fraud review's decision, release or reject, moves the transfer.
Events
| Event type | Published when |
|---|---|
payments.ach_transfer.created | A transfer is accepted. data is the transfer, with status pending or held_for_review. |
payments.fraud_review.held, .released, .rejected | The fraud rules hold a payment, and staff decide it. data.payment_kind is ach and data.payment_id is the transfer. |
payments.ach_file.sent | The operator acknowledged a file. Its entries are now sent. data is the file: id, direction, status, effective_date, entry_count, the totals and rail_ref. |
payments.ach_file.settled | The settlement of a file was posted. Its entries are now settled. |
payments.ach_file.received | A file from the operator was processed. |
payments.ach_receipt.posted, .returned, .accepted, .held, .blocked | A received entry got its outcome, at receipt or after a review or a later return. |
payments.ach_change.received, .applied, .refused, .sent | A notification of change changed status. See Changes and prenotes. |
ledger.journal.posted | Any journal posts, including a settlement and the reversal of a return. |
No event is published when a transfer becomes batched, sent, settled, returned, rejected or cancelled, or when a review approves it.
What to listen for
- Subscribe a webhook endpoint to
payments.ach_transfer.created,payments.ach_file.*andpayments.fraud_review.*. A subscription is an exact type, a prefix that ends in.*, or*for everything. - File events carry no list of entries. When one arrives with
directionoutbound, read the transfers you are waiting on and matchfile_idto the file'sid. Return files and refused notifications of change publishpayments.ach_file.senttoo, withdirectionoutbound_return. - Returns have no event. Read the transfer, or list
GET /transferswithtype=achandstatus=returned. That list also holds received entries the bank returned. - For money arriving, subscribe to
payments.ach_receipt.*.
Delivery, signatures and retries are covered in Events and webhooks.