Skip to main content
See the public error catalog for the complete error contract.

What this protection does

Some bank corridors protect a destination after a recent bank rejection. When the same normalized destination was rejected recently, CBPay stops the next create before it creates a payout, debits the balance, or consumes the idempotency key. The protection is scoped to the account and the normalized combination of bank_code, account_number, and tax_id. Changing capitalization or formatting does not bypass it.

Safe sequence

  1. If the first response is ambiguous, replay the exact request with the same idempotency_key. This returns the original resource with idempotency_hit: true; it never creates a second payout.
  2. If the response is destination_recently_rejected, the original key was not consumed. Review the bank rejection and decide whether the destination should be retried.
  3. A deliberate retry uses a new idempotency key and options.destination_retry_ack set to the most recent rejected payout ID.
  4. Reusing the old key with changed options returns 409 idempotency_conflict; it never changes the original operation.
  5. A destination with no recent rejection, or a payout on another corridor, follows its normal validation and dispatch path.
The acknowledgement is an explicit operator decision, not an automatic second attempt.

Deliberate retry request

The acknowledgement must identify the most recent rejected case for the same account and normalized destination. Do not copy a case ID from another account or destination. For the complete error catalog, see Errors.

Response examples

Recent rejection

The message includes the UTC rejection date, the prior case ID, and the prior code. The public response is provider-agnostic.

Changed options with the old key

States and actions

FAQ

No. The guard runs before payout insertion and before the debit. It also does not consume the submitted idempotency key.
Yes, if you are replaying the exact original request. A deliberate retry after reviewing the rejection must use a new key and the acknowledgement option.
Request options are part of the idempotency payload. Reusing a key with changed options is a different request, so CBPay rejects it instead of silently changing the original operation.
No. The protection is applied only where the corridor enables it. Other rails and destinations without a recent matching rejection follow their existing validation and dispatch flow.
Last modified on October 6, 2026