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.
Delivery envelope
Every delivery has the same outer shape.data holds the resource-specific payload documented below.
| Header | Description |
|---|---|
X-Webhook-ID | The envelope id — use for deduplication. |
X-Webhook-Event | The event type, e.g. payout.completed. |
X-Webhook-Timestamp | Unix seconds at signing time. Used for verification. |
X-Webhook-Signature | v1={hex-hmac-sha256}. See Webhook Signing. |
User-Agent | AntonPayments-Webhook/1.0 |
Event catalog
Payout events
10 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.
Test events
Fired by the test-delivery endpoint.
Payout events
| Event type | Fires when |
|---|---|
payout.created | A payout is successfully created via POST /v1/payouts. |
payout.approved | A pending payout is approved (maker-checker flow). |
payout.processing | The payout has been submitted to the underlying rail provider. |
payout.sent | The rail has confirmed funds are on the way to the beneficiary. |
payout.completed | The rail confirms funds have been delivered. |
payout.failed | Rail submission or execution failed terminally. |
payout.cancelled | The payout was cancelled before execution. |
payout.returned | The rail reported the funds were returned after sending. |
payout.screening_failed | Compliance screening blocked the payout. |
payout.velocity_blocked | A risk/velocity rule blocked the payout at create time. |
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 and payout.velocity_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.
payout.screening_failed
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
| Event type | Fires when |
|---|---|
beneficiary.created | A beneficiary is created via POST /v1/beneficiaries. |
beneficiary.updated | A beneficiary is edited, archived, restored, or has its PII updated. |
beneficiary.deleted | A beneficiary is deleted. Payload contains only the id. |
beneficiary.blocked | A beneficiary is blocked (e.g. by compliance). |
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
| Event type | Fires when |
|---|---|
instrument.created | An instrument is attached to a beneficiary via POST /v1/beneficiaries/{id}/instruments. |
instrument.updated | An instrument is edited. |
instrument.deleted | An instrument is deleted. Payload contains only the id. |
instrument.created
instrument.updated
Same shape as instrument.created with the new values reflected.
instrument.deleted
Batch events
| Event type | Fires when |
|---|---|
batch.uploaded | A CSV or XLSX batch file is accepted by POST /v1/batches. Fires before validation begins. |
batch.completed | A batch finished processing with at least one successful row (includes partial success). |
batch.failed | A batch failed terminally — no rows could be processed, or every row failed. |
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
| Event type | Fires when |
|---|---|
fx.quote.created | An FX quote is locked (binding commitment). Indicative quotes do not fire an event. |
fx.exchange.created | An FX exchange is executed and is pending settlement. |
fx.exchange.completed | The exchange has settled. |
fx.exchange.failed | The exchange failed to settle, or was stuck in pending beyond the retry budget. |
fx.quote.created
fx.exchange.created, fx.exchange.completed, fx.exchange.failed
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.
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 — either in the merchant dashboard or via the Balance Alerts API. 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.
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 signingsecret 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.GET /v1/webhooks/events, GET /v1/webhooks/events/{id}, and GET /v1/webhooks/events/{id}/deliveries. See Webhook Signing for verification.