Skip to main content
Editability note: this guide was drafted against the OpenAPI spec. If the product/engineering team hasn’t validated it against a recent end-to-end trace, flag anything that reads off and edit the relevant section — each H2 below is self-contained.
A payout is a single payment from your merchant balance to a beneficiary’s payment instrument. This guide walks through everything you need to know to send one in production: the data model, the fields that matter, the state machine, and how your integration should respond to each state. For a 5-minute sandbox walkthrough, start with the Quickstart. This guide assumes you’ve already done that and need to build the real thing.

The data model

Three entities come together on every payout:
  • Beneficiary — who you’re paying. Identity only; PII is tokenized on creation.
  • Instrument — where the money goes. Bank account, wallet, or card, attached to a beneficiary. Credentials are tokenized.
  • Payout — the single payment. Links a beneficiary and one of their instruments to an amount, currency, and rail.
Create them in that order. Beneficiaries can have many instruments; one payout uses exactly one instrument.

Economics: source vs dest amounts

Every payout has two amounts:
  • source_amount — what’s debited from your merchant balance in your source currency.
  • dest_amount — what the beneficiary receives in their destination currency.
For same-currency payouts these are equal. For cross-currency payouts, Anton computes the other side using the current corridor pricing. The fixed_side field tells Anton which amount is authoritative:
  • fixed_dest (default) — beneficiary receives exactly dest_amount; Anton computes source_amount including FX and fees.
  • fixed_source — merchant pays exactly source_amount; Anton computes how much the beneficiary receives after FX and fees.
fee_bearer controls who absorbs the fee:
  • merchant (default) — fee is added on top of source_amount.
  • beneficiary — fee is deducted from dest_amount, so the beneficiary receives less than the stated amount.

Corridors, methods, and rails

A corridor is a (currency, country, method, network) combination Anton can deliver through. Before attempting a payout, verify the corridor is enabled on your account:
The method field on POST /v1/payouts selects the delivery method. For fiat:
  • faster_payment — UK Faster Payments
  • sepa — SEPA Credit Transfer (EUR)
  • ach — US ACH
  • swift — SWIFT international wire
  • wire — generic domestic wire
  • bank_transfer — generic bank transfer (rail picks based on corridor)
  • mobile_money — M-Pesa, MTN, etc.
For crypto/stablecoin, see Crypto & Stablecoin Payouts. rail_type (fiat, crypto, or stablecoin) is a hint Anton may override based on corridor availability.

Purpose and reference

Two required fields that serve different audiences:
  • purpose — a compliance-facing payment-purpose code. Examples: contractor_payment, supplier_payment, salary, refund, services, goods. Used for reporting and some rails require it.
  • reference — your own free-form string, up to 100 chars. Appears on the beneficiary’s statement where the rail supports it. Use your invoice or order number so both sides can reconcile.

Send end-user session context

If a person triggered this payout in your product — a customer hitting “pay”, an operator releasing an invoice — send the session object. Every field is optional and none of them can fail your payout, but they are the difference between Anton scoring a payout it can see and one it is guessing at.

Why it materially improves the risk assessment

Without session context, the only address Anton sees is your server’s — which tells it where your infrastructure runs, not where your user is. That is the single biggest blind spot in scoring a payout. With it, Anton can reason about:
  • Where the payer actually is — country and network of ip, checked against the payout’s destination corridor.
  • Whether the story is consistenttimezone against the country the IP resolves to. A Toronto browser paying from a Singapore address is worth a second look; the same browser from a Toronto address is not.
  • What kind of network it is — residential broadband, a datacenter, a Tor exit, an iCloud Private Relay egress. These carry very different weight, and Anton treats legitimate consumer privacy tooling differently from anonymity infrastructure.
  • Whether it fits your own pattern — once you send session data consistently, a payout that arrives without it stands out against your own baseline, which is a useful signal in its own right.
The practical effect is fewer false positives on your legitimate traffic. A payout Anton can place in a coherent, ordinary-looking session is one it does not need to hold for review on thinner evidence.
Send the IP your edge observed for the end user — not your server’s address and not a value the browser supplied. If you sit behind a load balancer or CDN, take the client entry from X-Forwarded-For counting from the right, at the hop your own infrastructure appends. A caller-supplied leftmost entry is attacker-controlled.

Data-quality feedback, never rejection

Only a syntactically invalid ip is an error (422). Everything else is accepted and reported back on the payout as session_quality, so you can fix your integration without anything failing in production:
non_public_ip almost always means a misconfigured proxy handed us your own load balancer’s private address instead of the user’s.

session.ip supersedes end_user_ip

The older top-level end_user_ip field still works. When both are present, session.ip wins, unconditionally. New integrations should send session and leave end_user_ip alone.

What you are confirming by sending it

By sending session data you confirm you collected it lawfully from your end user under your own privacy notice, and that you are authorized to share it with Anton for fraud prevention and AML transaction monitoring. Anton keeps it as transaction evidence on a 7-year horizon aligned to the payout record, and never uses it to build a profile of your users outside that purpose.

Idempotency

POST /v1/payouts requires an Idempotency-Key header. Derive it from your own business data so retries after a network failure converge on the same payout:
If you retry with the same key, Anton returns the original response and sets X-Idempotent-Replayed: true. Different bodies with the same key return 409 idempotency_conflict. See Idempotency for details.

The state machine

Payouts move through a 13-state machine. The full detail is in How Anton Evaluates Payouts; the short version:

Subscribe to webhooks — don’t poll

Every state transition fires a payout.* event. Subscribe once via POST /v1/webhooks and handle the events you care about:
  • payout.completed — funds delivered
  • payout.failed, payout.returned — terminal failure paths
  • payout.screening_failed, payout.velocity_blocked, payout.engine_blocked — compliance/risk blocks (payout.engine_blocked fires alongside payout.velocity_blocked when the Anton engine drove the block)
  • payout.cancelled — operator or API cancellation
Polling GET /v1/payouts/{id} works in development but wastes rate-limit budget at scale and misses transitions.

Cancelling a payout

You can cancel a payout that has not yet been submitted to a rail — from created, pending_screening, pending_approval, pending_engine_review, or manual_review:
Once a payout reaches processing, the rail has it — cancellation is no longer possible via the API. Contact support if you need to halt an in-flight payout. On successful cancellation, the debited funds (source amount, fee, and any FX buffer) are released back to your balance.

What can go wrong

Your merchant balance in the source currency can’t cover source_amount + fee + buffer. Top up the balance or reduce the payout.
The requested (source_currency, dest_currency, country, method) isn’t active on your account. Call GET /v1/corridors to see active ones, or contact support to enable a new corridor.
The ID doesn’t exist or belongs to a different merchant. Double-check the ID, including prefix (ben_..., ins_...).
The instrument is archived, disabled, or its method/currency doesn’t match the payout. Instruments are scoped to a single country + method at creation.
Honor Retry-After and back off. See Rate Limits.

Next steps

Manage beneficiaries

Dedup, update PII, archive, restore.

Handle webhooks

Subscription, signing, delivery semantics.

Crypto & stablecoin

Network selection, finality, memo/tag fields.

FX & exchange

Lockable quotes and cross-currency payouts.