Skip to main content
Webhooks are HTTP POSTs Anton sends to a URL you control when something happens in your account — a payout moves through its lifecycle, a beneficiary is created, an FX exchange settles. Subscribe by calling POST /v1/webhooks with the URL and list of event types you want to receive. Deliveries are at-least-once. You may occasionally receive the same event twice — deduplicate on the envelope id. Events for the same resource are dispatched in the order they occur, but network retries mean they can arrive out of order at your endpoint. Failed deliveries retry with exponential backoff (30 seconds, 2 minutes, 8 minutes, 32 minutes, then hourly up to 5 attempts total) before being abandoned. Every delivery is HMAC-signed — see Webhook Signing for verification. Respond with any 2xx status within 30 seconds to acknowledge receipt. Webhook subscriptions are available on every account tier, including AI-compliance-only accounts — events for surfaces an account cannot reach (for example payout events on a compliance-only account) simply never fire.

Delivery envelope

Every delivery has the same outer shape. data holds the resource-specific payload documented below.
Each delivery also carries these HTTP headers:

Event catalog

Payout events

11 events covering the full payout lifecycle.

Beneficiary events

Beneficiary create, update, delete, and block.

Instrument events

Payment instrument create, update, delete.

Batch events

Batch upload, completion, and failure.

FX events

Quote locks and exchange execution.

Funding events

Incoming funds credited to your balance.

Compliance events

Screening hits that require manual review.

Verification events

KYC/KYB verification lifecycle, from link delivery to decision.

Test events

Fired by the test-delivery endpoint.

Payout events

The payload for payout lifecycle events is the payout object. The exact shape depends on the event — payout.created includes the initial fields; payout.sent, payout.completed, and payout.failed include rail identifiers and timestamps as they become available. payout.screening_failed, payout.velocity_blocked, and payout.engine_blocked use a compact shape with just id, status, and reason.
When a real-time risk score is available on the payout (available via the Anton risk engine), the lifecycle event payloads include a risk object summarising the score and contributing factors.

payout.created

payout.processing, payout.sent, payout.completed, payout.failed, payout.returned

These share the same lifecycle payload shape. rail_provider, rail_reference, completed_at, and failed_at are populated when the rail reports them.
The payout.failed payload carries the payout resource, not the failure detail. To branch on why a payout failed, fetch GET /v1/payouts/{id}/events — the terminal event’s metadata carries a stable failure_code (provider_rejected, vault_unavailable, insufficient_funds, …), a failure_category, and a sanitized reason. See Errors → Stable failure codes on payout events.

payout.screening_failed

payout.velocity_blocked

payout.engine_blocked

Fires alongside payout.velocity_blocked when a payout is blocked and the Anton engine layer was the primary decider. payout.velocity_blocked is a legacy catch-all — it fires on every block regardless of which layer made the decision — while payout.engine_blocked carries the layer-precise signal for engine-driven blocks only. Both events are emitted during a transition window (target cutover: 2026-Q3); subscribe to payout.engine_blocked for engine-specific handling and treat payout.velocity_blocked as a back-compat catch-all until you are ready to drop it. The payload matches payout.velocity_blocked.

payout.approved

Fires when a payout transitions to approved — either because compliance screening cleared it or an ops reviewer approved the manual review case it was queued in. Arrives before payout.processing for the same payout.

payout.cancelled

Fires when a payout is cancelled before being submitted to the rail. The payload includes the previous_status at the time of cancellation and the released_amount that was returned to the merchant’s available balance.

Beneficiary events

The payload’s data field contains the beneficiary resource. Sensitive fields (BT token references, fingerprints, deletion timestamps) are never included.

beneficiary.created

beneficiary.updated, beneficiary.blocked

Same shape as beneficiary.created with the event type and resource state reflecting the new values.

beneficiary.deleted

Instrument events

instrument.created

Credential tokens and fingerprints are never included — raw instrument credentials live only in the Basis Theory vault.

instrument.updated

Same shape as instrument.created with the new values reflected.

instrument.deleted

Batch events

batch.uploaded

batch.completed

Fires when processing finishes with status of completed (all rows succeeded) or partial (some succeeded, some failed). Branch on the payload status field to distinguish full from partial success.

batch.failed

Fires when a batch finishes with status = failed — either the file could not be processed at all (download/parse failure, empty file) or every row failed during processing. The payload includes an errors array describing the row-level failures when available.

FX events

fx.quote.created

fx.exchange.created, fx.exchange.completed, fx.exchange.failed

A fx.exchange.failed event fired by the status-polling worker (for exchanges that get stuck in pending) uses a compact payload:

Funding events

funding.credit

Fires when incoming funds are received on a merchant account and credited to the internal balance. The payload carries the masked sender name only — Anton never forwards raw counterparty PII to webhook subscribers.

Compliance events

screening.hit

Fires when compliance screening returns a possible match that requires manual review. The payload intentionally omits the matched sanctions-list entry content — Anton treats that information as compliance-sensitive and does not surface match details to merchants to avoid tipping-off risk. Subscribers should treat this event as a signal that a review case is open for the payout; the payout itself transitions to manual_review.

Verification events

Emitted by the Verifications module as a subject moves through a hosted KYC/KYB flow. All six events share one compact payload — the verification attempt ID, its subject, and the status after the transition. Payloads never carry the hosted link, the subject’s name, or document content; fetch GET /v1/verification-subjects/{id} for the full state.

verification.approved

verification.started, verification.declined, verification.review, and verification.expired share this exact payload shape with their respective status values. Same shape. The event type is the delivery receipt; status carries the attempt’s current status after the operation — sent on first delivery, but e.g. awaiting_owners when re-delivering an owner’s link on a business verification (which also adds owner_id), or in_progress when re-delivering to a subject who already opened the flow. Key your delivery-receipt handling on the event type, not on status:
verification.link_sent fires only when Anton actually delivered the email. Manual-delivery flows (delivery: "manual") and environments without an email path never emit it — the attempt stays created and you deliver the returned hosted_link yourself.

Balance events

balance.low

Fires when a merchant’s available balance drops below a configured low-balance threshold. Thresholds are configured per (merchant, currency) pair — one threshold per pair — in the merchant dashboard. The event uses latching semantics to prevent spam while the balance oscillates around the threshold:
  • Fires once when the available balance transitions from at-or-above the threshold to below it.
  • Does not fire again while the balance remains below the threshold.
  • Re-arms automatically when the balance recovers to at-or-above the threshold. No recovery event is emitted.
  • The next dip below the threshold fires again.
Delivery is best-effort and runs asynchronously from the balance mutation. A webhook failure never blocks the underlying payout, funding credit, or FX exchange.

Test events

test

Fired by POST /v1/webhooks/{id}/test to help you verify your endpoint is reachable and your signature verification works. The payload is a synthetic example with hard-coded identifiers — do not persist or act on it.

Subscribing to events

Create a subscription with the list of event types you want to receive. The signing secret is returned once, at creation time — store it securely.
The url must use https:// and must be publicly reachable from the internet. Anton rejects plaintext http:// endpoints, loopback addresses, RFC1918 private ranges, .local / .internal hostnames, and cloud metadata endpoints — these are refused with webhook_url_not_https or webhook_url_private_address. Plaintext http:// is only accepted against a local development API. See Errors → Webhook subscriptions.
Inspect past deliveries with GET /v1/webhooks/events, GET /v1/webhooks/events/{id}, and GET /v1/webhooks/events/{id}/deliveries. See Webhook Signing for verification.