Webhooks
AOA outgoing webhooks: the platform tells your system about payments, refunds and cancelled events. How to register a URL and what it must meet.
A webhook means we send a request to you the moment something happens: a ticket is paid for, money is refunded, an event is cancelled. You don’t have to keep polling us.
Event cancellations matter most
Polling the order status covers the payment, but not what happens later. An event can be cancelled a week after the purchase, and nobody polls the status of a ticket bought long ago. Without a webhook your system simply won’t find out.You need an API key with the webhooks:write scope. Register the URL to send requests to and list the events:
curl -X POST https://aoa.com.ua/api/v1/webhooks \
-H "Authorization: Bearer aoa_live_…" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/hooks/aoa",
"events": ["order.paid", "event.cancelled"]
}'{
"data": {
"id": "8f3c1a92-…",
"url": "https://example.com/hooks/aoa",
"events": ["order.paid", "event.cancelled"],
"secret": "whsec_9Kq2mR7vXp4nT8wL5yB1zC4d",
"createdAt": "2026-07-30T12:00:00.000Z"
}
}The secret is shown once
Thesecret field is only returned in the response to creation. After that we store it encrypted and can’t show it again. Save it right away: you use it to verify the signature of every request.One key can have up to 10 URLs, which is handy when test and production environments listen on different hosts.
https and port 443 or 8443.localhost, 10.x, 192.168.x, 169.254.x) are rejected. The check runs both at registration and before every delivery: if the domain later starts resolving to an internal address, we stop sending to it.POST /hooks/aoa HTTP/1.1
Content-Type: application/json
AOA-Signature: t=1800000000,v1=5f2a…
AOA-Delivery-Id: 3d9f7c21-…
AOA-Event-Type: order.paid
{
"id": "3d9f7c21-…",
"type": "order.paid",
"createdAt": "2026-07-30T12:00:00.000Z",
"data": {
"paymentId": "d3f1a2b4-…",
"eventId": "a1b2c3",
"status": "SUCCESS",
"amountMinor": 90000,
"currency": "UAH",
"attendeeId": "clx9attendee01"
}
}| Header | Purpose |
|---|---|
AOA-Signature | The body signature. Always verify it, see Verifying signatures |
AOA-Delivery-Id | Delivery identifier. It stays the same on retries, so deduplicate by it |
AOA-Event-Type | Event type. It repeats the type field in the body and is handy for routing |
AOA-Delivery-Id.We retry the delivery with growing pauses: after a minute, 5 minutes, 30 minutes, 2 hours and 6 hours. That’s about nine hours in total, enough to ride out a night-time deploy or an outage.
If a URL doesn’t respond for a very long time, we switch it off automatically so we don’t keep a queue of dead requests. The same happens at once, with no retries, if the URL starts resolving to an internal network; the reason will show in the lastError field of the last delivery.
You can see the state in GET/api/v1/webhooks, in the disabledAt field. To switch it back on:
curl -X PATCH https://aoa.com.ua/api/v1/webhooks/{id} \
-H "Authorization: Bearer aoa_live_…" \
-H "Content-Type: application/json" \
-d '{"isActive": true}'You don’t have to write a handler: AOA webhooks work with Make, Zapier and n8n directly. Ready-made recipes are in Make, Zapier, n8n.