Skip to main content
Read this before you write any agent code, because the default is more restrictive than most integrations expect. On a store with no extra configuration, an agent credential can read everything in its scopes, create payments, and cancel them. It cannot refund a payment, change which tokens the store accepts, issue a session mandate, or pay out. Those four write paths return 403 and keep returning 403 until a human configures a control. There is no request you can send, and no header you can add, that changes this from the agent side. The denials are the system working as designed. Treat them as a configuration state to report, not an error to retry.

What happens by default

SouthPay resolves an authorization provider per store. No provider is configured by default, so every store gets a permissive stub that approves every verification it is asked for. Each endpoint then checks whether the approval came from a real provider, and refuses if it did not. Payment creation is the deliberate exception. Charging a customer creates a receivable rather than an outflow, so it needs no mandate. Check which provider you are on with GET /api/v2/agentic/account (the get_account MCP tool). authorization.provider identifies the authorization provider in force and authorization.mandates is a boolean:
Response 200
"mandates": false means you are on the defaults described above.

Unblocking payouts with spend limits

Spend limits are per-credential, per-asset payout caps. They are the only control a merchant can configure without SouthPay staff involvement, and they are what makes agent payouts possible at all. A spend limit does two things:
  1. It unlocks the asset. With the default provider, a payout in an asset that has no spend limit is refused with payout_controls_required before any balance check happens.
  2. It caps the payout. Every payout is checked against a per-transaction cap and against a daily counter that resets at midnight UTC. Breaching either returns 403 with per_tx_cap_exceeded or daily_cap_exceeded.
Limits are set on the credential in the dashboard, under Agents. Both caps are optional individually. A limit row with only a daily cap still unlocks the asset. An agent reads its own headroom with GET /api/v2/agentic/payout_limits (or get_payout_limits over MCP), which returns per_tx_cap_atomic, daily_cap_atomic, daily_spent_atomic, daily_remaining_atomic and controls_configured per asset, plus the utc_day the counter belongs to. controls_configured: false on an asset is a reliable predictor that a payout in it will be denied. Size the payout from this endpoint rather than discovering the cap through a 403.

Unblocking refunds, token changes and mandates

Refunds, token toggles and mandate issuance need a real authorization provider. Spend limits do not help here; the check is specifically “is this store’s provider something other than the default”. A provider is configured per store. There is no API for this. It is not exposed on any merchant endpoint and it is not a dashboard toggle. SouthPay support enables it for your store. Until then, the three actions stay at 403 mandate_required regardless of credential scopes.
If you are building an agent for merchants generally, assume the provider is absent. Discover it at runtime from GET /agentic/account and gate your own tool exposure on authorization.mandates, rather than offering the agent a refund capability that will always fail.

With a provider enabled

Once a provider is configured, the model changes in both directions. The three blocked actions become available, and payment creation stops being unconditional. It is verified per call like everything else, and can now be denied with authorization_denied. The agent presents a mandate on gated requests in the X-Mandate header, base64-encoded JSON:
SouthPay forwards the presentation and the action’s parameters (action type, amount, currency, asset, destination) to the provider, which returns allow or deny. The decision and receipt are stored with the resulting payment, payout or mandate. Two details worth planning for:
  • The header is capped at 32768 bytes, and a value that is missing, oversized or not valid base64 JSON is treated as no mandate at all. On a gated action that produces a denial rather than a parse error, so a malformed header and an absent one look identical from the outside.
  • Spend limits still apply. A payout must pass provider verification and stay inside any configured per-transaction and daily caps.

Error codes

Every agentic endpoint uses the structured envelope, with code populated:
Response 403
Retrying an identical gated request produces an identical denial and burns rate-limit budget. Read error.code, explain it, and stop.

Audit trail

Each gated decision is recorded. Payments, payouts and mandates persist the provider’s decision and receipt on the record itself. Every agent action (created, denied, cap exceeded) is emitted as telemetry keyed by credential id. Merchants see the resulting payments, payouts and settlements per credential in the dashboard under Agents.
Last modified on August 21, 2026