Approvals
Tracking a payment through approval
Last updated 14 September 2026
When a payment you created needs sign-off, it does not fail and it does not send. It waits. This guide is about seeing where it is.
When approval applies
Finance configures approval policies in the web app under Team, Approval Policies. Each policy has an amount range, a set of approvers and a scope, and the scope includes a setting for whether the policy covers API-created payments. If it does, your POST /payments creates an approval request rather than a payment in flight.
Agree the policies with finance before you integrate. A payout service that assumes instant sending will look broken the first time a policy catches a payment.
Finding the approval
Three endpoints:
GET /account/{xaid}/approvals: approvals for one account, paged, up to 50 per page. Use this.GET /approvals: all approvals the credentials can see.GET /approval/{ref}: one approval by its reference.
An approval record carries ref, xtid, parent_xaid, status, the transaction it relates to and a meta object. Match on xtid from the payment response.
async function findApproval(xaid, xtid, token) {
const approvals = await listAll(`/account/${xaid}/approvals`, token, 50);
return approvals.find(a => a.xtid === xtid) ?? null;
}Polling
An approval can take minutes or days depending on who has to sign. Poll gently:
- Immediately after creating the payment, check once. If there is no approval record, the payment did not need one.
- Then check every few minutes for the first hour, every 15 minutes after that.
- Stop when the
statusis no longer pending, or when thextidappears inGET /account/{xaid}/transactions, which means it was approved and sent.
Show the status to whoever is waiting. "Awaiting approval by finance" is a much better message than a spinner.
Declined and expired
If the approval is declined, or expires under the policy's expiry window, the payment is not sent. Your job should surface that to a person and must not resubmit automatically; a declined payment was declined for a reason.
Webhooks instead of polling
Subscribe to TransactionConfirmed on the account and you are told when the payment settles, without polling. Use the approval endpoints for the "waiting" state and the webhook for the "done" state. See Subscribing to webhooks.
Approving from the API
The Customer API exposes approvals for reading. Approving and declining happens in the web app or Xace Mobile, where the approver's identity and MFA are checked. See [How to approve transactions created by multi-users](https://support.xace.io/en/articles/8711903-how-to-approve-transactions-created-by-multiusers).