Branch on the response
In both
202 cases the transaction is persisted and its funds are locked. It executes on its own once approved or once the time lock expires.
Track held transactions to the end
A held transaction can stay non-terminal for hours. Track it the same way as any other transaction, through webhooks first and polling as a fallback:- Subscribe to
transaction.signed,transaction.completed,transaction.failed, andtransaction.cancelled. A held transaction that is approved, or whose time lock expires, emitstransaction.signedand then follows the normal path. - Subscribe to
policy.violation, sent when ablockrule blocks a transaction, andpolicy.alert, sent when analertrule matches. - Poll Get transaction for anything still non-terminal after your expected window, and stop at a terminal status:
completed,failed,cancelled, orrejected.
rejected means an approver turned the transfer down. It is terminal. Return the funds to the customer’s balance in your ledger and tell them.
Webhooks covers signature verification, and Best practices covers reconciling missed events.
Tell customers the truth
Map each status to something a customer can act on. Don’t show a held transfer as “sent”.
Don’t expose rule names or thresholds to customers. They describe your controls, and showing them helps someone find the amount just below a limit.
Reconcile ledger balances
Treat the funds of a held transaction as reserved. Debit the customer’s available balance when Create transaction returns201 or 202. Release the reservation only on failed, cancelled, or rejected. This prevents a customer from spending the same balance twice while an approval is pending.