x402 is a pattern for machine-to-machine payments: a service answers 402 Payment Required, the agent pays, the service delivers. Charging per call makes per-action human approval impractical, so SouthPay uses session mandates. A human authorizes a capped envelope once, and the agent draws against it call by call under local, deterministic enforcement.
Both resources are REST-only, under the x402:read and x402:write scopes. Neither is exposed as an MCP tool.
Two things are off by default
Read this before building against x402. On a store with no configuration, the flow does not run at all, and even with it running the money does not leave the chain-side.
Mandate issuance requires an authorization provider. POST /agentic/mandates returns 403 mandate_required unless a provider is configured for the store. There is no API to configure one and no dashboard toggle. SouthPay support sets it per store. Because a settlement needs a usable mandate, POST /agentic/x402/settlements is blocked by the same wall. On a default store, every x402 write returns 403.
On-chain dispatch is off by default. Settlements are a ledger accrual, not a transfer. SouthPay broadcasts a settlement on-chain only when all of the following hold:
- on-chain dispatch is enabled for the store, which is off unless SouthPay staff turn it on;
- the settlement is in live mode, since test-mode settlements are never dispatched;
amount_atomic is non-zero;
pay_to is set, since a settlement without one is failed with reason missing_pay_to.
With dispatch off, a settlement stays submitted indefinitely and tx_ref stays null. The spend is real on SouthPay’s internal ledger, reducing the store balance and the mandate envelope, but no on-chain transfer exists. Do not treat submitted as settlement finality, and do not release goods against it.
Polling a submitted settlement for confirmed on a store without on-chain dispatch is an infinite loop. Confirm dispatch is enabled with your SouthPay contact before you build a state machine that waits on it.
How the flow runs
Issuance is verified once through the store’s authorization provider. Every subsequent draw is enforced locally against the envelope’s caps and the store balance, with no per-call round trip to the provider.
Issue a session mandate
mandate_ref is unique per credential and issuance is idempotent on it: posting the same mandate_ref again returns the existing mandate rather than creating a second one or raising a conflict.
Failures: 403 mandate_required with no provider, 403 authorization_denied when a provider evaluates and refuses, 404 asset_not_found, 422 invalid_cap for a non-positive total, 422 mandate_ref_required.
A mandate is usable while status is active, it has not expired, and remaining_atomic is positive.
GET /agentic/mandates lists the credential’s mandates, capped at the 100 most recent. GET /agentic/mandates/:id fetches one.
Settle a charge
Each paid call becomes one settlement drawing on the mandate.
Idempotency-Key is required; without it the request is refused with 422 idempotency_key_required. Retrying with the same key returns the original settlement, with the normal 201.
nonce defaults to a random 32-character hex value. payer and requirements, the service’s own 402 payment requirements stored for audit, are optional.
amount_atomic must not be negative, and zero is accepted. A zero-amount settlement records the call against the mandate without drawing on the envelope, and is never dispatched on-chain.
Under a row lock on the mandate, each settlement:
- confirms the mandate is usable, otherwise
403 mandate_required;
- enforces the per-call cap and the remaining envelope, otherwise
403 spend_cap_exceeded;
- confirms the store balance covers the amount, otherwise
422 insufficient_balance;
- records the debit on the double-entry ledger and increments
spent_atomic, flipping the mandate to exhausted if that consumes the envelope.
GET /agentic/x402/settlements lists settlements with a pagination envelope (page, per_page default 25 max 100, total, total_pages). GET /agentic/x402/settlements/:id fetches one.
Settlement status
confirmed and failed are terminal. Without on-chain dispatch a settlement finishes its life as submitted, which is the state most integrations will see today.
If dispatch is enabled for your store, tx_ref carries the provider transaction reference once broadcast. Dispatch is keyed deterministically per settlement, so a retry cannot double-send. Last modified on August 21, 2026