Payment lifecycle and statuses

An outbound payment is asynchronous. POST /v1/outbound-payments returns 201 with the payment's id straight away, and the payment then moves through compliance screening and the payment rail on its own. Poll GET /v1/outbound-payments/{id} until it reaches a terminal status.

Statuses

StatusTerminalWhat it meansWhat to do
ScheduledNoThe payment has a future valueDate and has not entered the lifecycle yet.Wait for the value date, or cancel it.
AwaitingFundsNoThe debiting account did not have enough available balance when the balance check ran.Fund the account; the payment resumes on its own.
ProcessingNoScreening has passed and the payment is with the payment rail.Keep polling.
SentYesThe bank executed the payment. The account is debited at this point.Reconcile against GET /v1/transactions.
RejectedYesThe payment could not be completed, for example because the receiving bank rejected it. No funds have been moved.Fix the cause, and create a new payment with a new idempotencyKey.
ReturnedYesThe payment completed and was subsequently returned by the beneficiary bank.Reconcile against GET /v1/transactions.
CancelledYesYou cancelled the payment before it was sent for processing.Nothing further.

The same values are accepted by the status filter on GET /v1/outbound-payments, which is the efficient way to sweep everything still in flight.

The path a payment takes

  1. Created. A payment created over the Client API goes straight into compliance approval. The manual approval stages of the portal are skipped, so an API payment is never held in Draft.
  2. Value-date gate. A payment with a future valueDate parks as Scheduled and only continues on that date. The gate runs asynchronously; a future-dated payment may read Processing for a few seconds before Scheduled.
  3. Balance check. The available balance on the debiting account is checked against the ledger. If it is short, the payment stops at AwaitingFunds and resumes once the balance is there.
  4. Compliance screening. A rejection ends the payment at Rejected; an acceptance lets it continue.
  5. Initiation and execution. The payment moves to Processing while it is with the payment rail, then to Sent when the bank executes it. The debit hits the ledger on Sent, not before.

Polling

You can receive status changes by webhook or by polling. Webhook endpoints are registered by your account manager; GET /v1/events returns the same events for 90 days and is the recovery path if your endpoint was down. When polling the payment itself, back off between attempts and stop when it reaches a terminal status or parks at Scheduled or AwaitingFunds. Both of those wait on something outside the API (a date, or a credit landing) rather than on us. The detail read also returns an events array holding the events raised for that payment, in the same shape as a row from GET /v1/events.

Internal payments

POST /v1/internal-payments moves funds between two of the same client's accounts in a single currency. There is no approval stage and no payment rail, so the transfer completes immediately when the debiting account has sufficient available balance and there is no lifecycle to poll. Idempotency works exactly as it does for outbound payments, except that the 409 body carries existingInternalPaymentId.

Inbound payments

Inbound payments are created by money arriving from outside, not by you. Read them with GET /v1/inbound-payments and GET /v1/inbound-payments/{id}. In the sandbox, POST /v1/simulations/inbound-payments drives the same command chain a real upstream credit would, which is how you fund an account before testing an outbound flow.

Testing every outcome

The sandbox reaches all of these statuses deterministically: a reference that starts with a documented trigger token produces that outcome, and any other reference takes the happy path. See Sandbox Outcome Triggers for the trigger vocabulary.

Remember that a payment id is only useful if you kept it. If a create response was lost, do not create the payment again: retry the identical request with the same idempotencyKey and you will get 200 with the original id back. See Idempotency.

Cancelling

POST /v1/outbound-payments/{id}/cancel cancels a payment that has not yet been sent for processing and returns 204. reason is required and must be one of incorrect_amount, incorrect_payee or payment_not_required.

  • A payment already with the payment processor or the bank cannot be cancelled: 422.
  • A payment that is already cancelled: 409.
  • A payment belonging to another client: 404.