Swap webhooks

Real-time events for verification, routes, and settlement

View as Markdown

Verification and settlement complete in the background. Subscribe to webhooks to be notified the moment state changes, instead of polling.

Manage your webhook endpoints (URL, subscribed events, signing secret) in the Partner Platform → Developer → Webhook endpoints.

Payload structure

Every event is delivered as an HTTP POST with this envelope:

1{
2 "id": "unique_event_id",
3 "type": "payment_route.transaction.created",
4 "payload": {
5 // event-specific fields (see below)
6 },
7 "createdAt": "2026-08-13T12:00:00Z"
8}

Verifying signatures

Each request includes an X-Signature header — an HMAC-SHA256 hex digest of the raw request body, keyed by your endpoint’s signing secret. Recompute it and compare using a constant-time function. See the general Webhook guide for full code samples (Node.js, PHP, Go, Java).

Retries

If your endpoint doesn’t return a 2xx, we retry with exponential backoff, up to 5 attempts (10s, 30s, 1m, 2m, 5m).

Events

EventWhen it fires
company.onboarding_status_changedA company’s onboarding status changes
company.kyc_link.issuedA company’s verification link becomes available
company.kyc_status_changedIdentity verification moves on
payment_route.createdA payment route is opened
payment_route.transaction.createdMoney lands on a payment route

company.kyc_link.issued

Fires once the company is provisioned for swap. Carries the same swap block as GET /v1/kyc-link, so you can store both links without a follow-up call.

1{
2 "companyId": "01KZ2WJKWVFPCVAB6MY106QRZV",
3 "kycUrl": "https://public-api.alphax.com/kyc/9f2c1d84e7b6a5309c8f",
4 "kycStatus": "not_started",
5 "tosUrl": "https://public-api.alphax.com/kyc/9f2c1d84e7b6a5309c8f/terms",
6 "tosAccepted": false
7}

company.kyc_status_changed

1{
2 "companyId": "01KZ2WJKWVFPCVAB6MY106QRZV",
3 "kycStatus": "approved"
4}

kycStatus is one of not_started, incomplete, awaiting_questionnaire, awaiting_ubo, under_review, approved, rejected, paused or offboarded — see the Verification page for what each means and which need your customer to act.

payment_route.created

paymentRoute is the same object GET /v1/payment-routes/{id} returns.

1{
2 "companyId": "01KZ2WJKWVFPCVAB6MY106QRZV",
3 "paymentRoute": {
4 "id": "01KZ2RT4Q8N7YB3D5F6G7H8J9K",
5 "type": "offramp",
6 "status": "active",
7 "currency": "USD",
8 "feePercent": 0.9,
9 "depositAddress": "TTRRSXZza9kJuv1fSUeehfkJsZntqUQSqp",
10 "source": {
11 "type": "crypto",
12 "currency": "USDT",
13 "paymentRail": "tron",
14 "address": "TTRRSXZza9kJuv1fSUeehfkJsZntqUQSqp"
15 },
16 "destination": {
17 "type": "bank",
18 "currency": "USD",
19 "paymentRail": "ach",
20 "bankName": "Example Bank",
21 "bankAccountNumber": "1234567890",
22 "bankRoutingNumber": "021000021",
23 "bankBeneficiaryName": "Acme Ltd"
24 },
25 "createdAt": "2026-08-13T09:41:22.000000Z"
26 }
27}

This also fires for routes opened in the AlphaX app rather than through the API, so your records stay in step either way.

payment_route.transaction.created

The body is companyId plus the exact object the transaction endpoints return — so you can hand it to the same code whether you polled for it or were pushed it.

1{
2 "companyId": "01KZ2WJKWVFPCVAB6MY106QRZV",
3 "type": "PaymentRoute",
4 "transaction": {
5 "id": "01KZ2TXN4Q8N7YB3D5F6G7H8J9",
6 "direction": "Credit",
7 "amount": "99.10",
8 "currency": "USD",
9 "description": "[payment route] 100.00 USDT",
10 "counterpartyName": "TFrom...",
11 "createdAt": "2026-08-13T10:02:11.000000Z"
12 },
13 "data": {
14 "routeId": "01KZ2RT4Q8N7YB3D5F6G7H8J9K",
15 "routeType": "offramp",
16 "incomingAmount": "100.00",
17 "convertedAmount": "99.10",
18 "totalFees": "0.90",
19 "sourceTxHash": "0x...",
20 "destinationTxHash": "0x...",
21 "source": { "paymentRail": "tron", "currency": "USDT", "fromAddress": "TFrom..." },
22 "destination": { "paymentRail": "ach", "currency": "USD", "bankName": "Example Bank" }
23 }
24}

For an on-ramp, data carries the payer’s details instead:

1{
2 "routeId": "01KZ2RT4Q8N7YB3D5F6G7H8J9K",
3 "routeType": "onramp",
4 "senderName": "ACME LLC",
5 "senderBankRoutingNumber": "021000021",
6 "incomingAmount": "500.00",
7 "convertedAmount": "497.50",
8 "destinationTxHash": "0x..."
9}

A note on emails

If you onboarded a company, AlphaX does not email its people — no deposit notifications, no receipts. You own that relationship, and these webhooks are how you learn what to tell them.