Skip to main content
The agentic API is a separate surface for autonomous agents acting on a store’s behalf. It lives under /api/v2/agentic, accepts only spa_ agent credentials, and returns records the calling credential created. An agent never sees another agent’s payments or payouts. For how credentials are issued and how authorization providers work, see agent credentials and authorization. This page is the endpoint reference. Paths are relative to https://api.southpay.io/api/v2.

Authentication

Only credentials matching spa_live_ or spa_test_ are accepted. API keys and OAuth tokens are rejected on every path here, and agent credentials are rejected everywhere else. Every response on this surface uses the structured envelope {"error": {"message": …, "code": …}}. That is unlike the rest of the API, where the flat {"error": "<string>"} form is the common case.

Scopes

Eight agent scopes exist: payments:read, payments:write, payouts:read, payouts:write, assets:read, assets:write, x402:read, x402:write.

Rate limit

600 requests per minute per credential in live mode (120 in test), shared across all agentic paths except market data. Over the limit you get 429 {"error": {"message": "Too many requests", "code": "rate_limited"}} with a Retry-After header in seconds. See Rate limits for every throttled path.

What the default authorization provider blocks

Read this before you write any agent that moves money. The authorization provider is configured per store, and only SouthPay staff can set it. With no provider, which is the default for every store, payments work and most other writes are hard-blocked at 403.
Mandates are not optional hardening. Four write paths cannot be used at all without a configured authorization provider, and there is no API to configure one. If your agent needs refunds, token control or x402 settlement, talk to support before you build against them. Payouts are the one exception: an agent spend limit set in the dashboard unblocks them without a provider.

Read agent context

GET /agentic/account. No scope required. Call this first: it tells you which store you are on, which mode, what you are allowed to do, and whether mandates are available.
string
required
"live" or "test", derived from the credential prefix. There is no separate sandbox host.
object
required

Create a payment

POST /agentic/payments. Scope payments:write. Idempotency-Key optional. The same payment_intent envelope as the public endpoint, but a smaller field set and stricter amount validation. title, description, image_url and line_items are not accepted here.
string
required
Fiat major units. Must be finite, positive, at most 2 decimal places, and at most 100000000.00.
string
required
One of USD, EUR, GBP, HKD, SGD, JPY, DKK, CHF, SEK, NOK.
string
string
string
integer
default:"3600"
How long the payment stays payable, in seconds. Minimum 300, maximum 86400. Omit it for the 60 minute default.
object
At most 50 keys. Every value must be a string.
exchange_rate_snapshot is a plain decimal string, not an object. There is no {rate, source} shape on a payment address.
The intent expires 60 minutes after creation, or after expires_in seconds when you send it. Send the customer to hosted_url and pay the exact crypto_amount_atomic to address.

Retrieve a payment

GET /agentic/payments/{id}. Scope payments:read. Returns the detail view, identical in shape to the public retrieve endpoint: financials, transaction, overpayment, merchant, payment_events, timeline and the rest. An id the credential did not create returns 404.

List payments

GET /agentic/payments. Scope payments:read. Only this credential’s payments, newest first.
string
Exact match on the 16-character reference. Upcased before matching.
integer
default:"1"
integer
default:"10"
Between 1 and 100.
Response 200
Agentic payments use the meta envelope. Agentic payouts and x402 settlements use pagination, and refunds and mandates return data with no page information at all.

Cancel a payment

POST /agentic/payments/{id}/cancel. Scope payments:write. No body. Only a pending intent can be canceled. The intent moves to status: "expired" with state_reason: "canceled_by_agent", and 200 returns the full detail view.
Response 200
Cancellation emits payment_intent.canceled, but that event is not in the subscribable catalogue, so no webhook endpoint can receive it. To observe agent cancellations, poll for status: "expired" with state_reason: "canceled_by_agent".

Refund a payment

POST /agentic/payments/{payment_intent_id}/refunds. Scope payments:write. Idempotency-Key required.
string
Decimal major units of the asset. Omit for a full refund.
string
Required when the payment received more than one asset.
There is no destination_address here. An agent cannot redirect a refund. Funds go back to the paying address. Returns 201 with {"data": [ … ]}, an array of refund objects, one per asset. GET on the same path lists existing refunds in the same wrapper, unpaginated. Unlike the merchant refund endpoint, this one returns machine-readable codes:

Create a payout

POST /agentic/payouts. Scope payouts:write. Idempotency-Key required. Crypto only, to a raw address. Agents cannot use saved payout destinations and cannot off-ramp to fiat. Parameters are top-level.
string
required
Active asset in the credential’s mode.
string
required
Atomic units. Must be positive.
string
required
Where the funds go. Must be valid for the asset’s chain.
The response is the same payout object merchants see. Idempotency keys are namespaced per credential, so two agents can use the same key without colliding. Check headroom before you call, with payout limits.

Retrieve and list payouts

GET /agentic/payouts/{id}. Scope payouts:read. Bare payout object. Unknown id returns 404 not_found. GET /agentic/payouts. Scope payouts:read. Accepts page (default 1) and per_page (default 25, max 100).
Response 200

Read payout limits

GET /agentic/payout_limits. Scope assets:read. Spend caps and remaining headroom for the current UTC day. Call this before a payout rather than discovering a cap through a 403.
string
Limit the response to one asset.
Response 200
boolean
required
False when neither cap is set. With the default authorization provider, false here means POST /agentic/payouts will return 403 payout_controls_required for this asset.
string | null
Null when there is no daily cap, meaning unlimited rather than zero.
Counters reset at 00:00 UTC. utc_day tells you which day the figures belong to.

Read balances

GET /agentic/balances. Scope assets:read.
string
Filter the balances array. settlement_balance is always computed across all assets regardless.
Response 200
This differs from the merchant balances endpoint: there is no stablecoin_summary, and an asset_id filter is available. amount_cents is null when a rate could not be resolved.

Read exchange rates

GET /agentic/exchange_rates. Scope assets:read. SouthPay’s own rates, the ones applied when pricing a payment. For public market data, use market data instead.
string
Fiat currency to quote against. Defaults to the store’s settlement currency.
string
Quote a single asset instead of all accepted assets.
Response 200
rate is a string. Assets whose rate cannot be resolved are omitted from the array rather than returned with a null rate, so a shorter list than you expected is a lookup failure, not an empty balance.

Manage accepted tokens

GET /agentic/tokens. Scope assets:read.
Response 200
accepted is what customers can currently pay with. available is everything else active in this mode. The two arrays never overlap, and active mirrors which array the entry is in. PATCH /agentic/tokens/{asset_id}. Scope assets:write.
boolean
required
True to accept the asset, false to stop accepting it.
Response 200

Mandates

A mandate is a signed spending envelope an agent draws down against, used by x402 settlements. Concepts are covered in the authorization guide. POST /agentic/mandates. Scope x402:write. Parameters are top-level.
string
required
Asset the cap is denominated in.
string
required
Total the mandate may spend, in atomic units. Must be positive.
string
required
Your reference for this mandate. Settlements name it to draw against the envelope.
string
Ceiling for any single settlement.
string
default:"x402"
What the mandate authorizes.
integer
default:"3600"
Lifetime from creation.
Response 201
status is active, revoked, expired or exhausted. remaining_atomic is the figure to check before settling. GET /agentic/mandates. Scope x402:read. Returns {"data": [ … ]}, capped at 100 and not paginated: there are no page parameters and no total. GET /agentic/mandates/{id}. Scope x402:read. Bare mandate object. Unknown id returns 404 not_found.

x402 settlements

POST /agentic/x402/settlements. Scope x402:write. Idempotency-Key required. Parameters are top-level.
string
required
string
required
Atomic units. Zero is accepted. The check rejects negatives only.
string
required
The mandate to draw against. Must be active, unexpired and have headroom.
string
Replay guard. Generated for you if omitted.
string
Recipient identifier from the x402 challenge.
string
Payer identifier.
object
The raw requirements object from the x402 challenge, stored alongside the settlement.
Response 201
Settlements are ledger-only by default. On-chain dispatch is off unless SouthPay staff enable it for your store. A confirmed settlement without dispatch enabled means the internal ledger moved, not that a transaction was broadcast. tx_ref stays null.
status is pending, submitted, confirmed or failed. GET /agentic/x402/settlements. Scope x402:read. Accepts page and per_page (default 25, max 100), and returns the pagination envelope. GET /agentic/x402/settlements/{id}. Scope x402:read. Unknown id returns 404 not_found.

Market data

GET /agentic/market_data. Unauthenticated. No credential, no scope. Public reference prices from CoinGecko. It touches no SouthPay funds and reads no store data, which is why it needs no credential.
string
required
Ticker or CoinGecko id, for example btc or bitcoin.
string
default:"usd"
Currency to quote in.
Response 200
Rate limited to 30 requests per minute per IP, separately from the 120-per-credential agentic limit.
These are public market prices, not the rates SouthPay applies. For the rate used to price a payment intent, use exchange rates.

Payment statuses

Agentic payments use the same six statuses as merchant payments: pending, processing, completed, expired, failed, refunded. There is no overpaid status. An overpayment is status: "completed" with state_reason: "completed_overpaid", and the excess is in the overpayment object on the detail view. state_reason has ten values, including canceled_by_agent, which only this API produces. See payment lifecycle.
Last modified on August 31, 2026