Webhooks overview

Webhooks let Aeses notify your server when something happens — a deposit confirms, a withdrawal broadcasts, an event needs your attention. Instead of polling, your endpoint receives a POST with a JSON payload describing the event.

How it works

  1. You expose an HTTPS endpoint on your server that accepts POST requests.
  2. You provide that URL when creating a deposit or withdrawal — or set an account-level default in Dashboard → Developers → Webhooks.
  3. When the resource changes state, Aeses signs the payload and POSTs it to your endpoint.
  4. Your endpoint verifies the signature, updates your own database, and returns 200 OK.
  5. If your endpoint fails to respond with 2xx within 10 seconds, Aeses retries on a backoff schedule.

Payload shape

Every deposit and withdrawal webhook event has the same envelope:

Event envelope
{
"id": "evt_k3j9x0a1b2c3",
"event": "deposit.completed",
"created_at": 1731600125,
"data": {
  "object": "deposit",
  "id": "dep_3f2a9c1e7b8d4a6f9e0c1b2a3d4e5f60",
  "status": "completed",
  "...": "..."
}
}
  • id — unique event ID.
  • event — the event name. See the event catalog. Also sent in the X-Webhook-Event header.
  • created_at — Unix timestamp (seconds) when the event was generated.
  • data — a full snapshot of the resource (deposit or withdrawal) at the time of the event, with the same fields returned by the API.

Every request also carries X-Webhook-Id (the delivery ID, stable across retries of the same delivery), X-Webhook-Timestamp and X-Webhook-Signature headers.

Acknowledging events

Return a 2xx status code as soon as you have durably enqueued the event for processing. Do not block the response on slow downstream work — your worker pool can process the payload asynchronously.

If you respond with 4xx (other than 408) Aeses will not retry, because the response indicates a permanent failure (e.g. malformed event, signature mismatch). For 5xx, 408, and timeouts, Aeses retries on the schedule described in Retries.

Best practices

  • Verify the signature first. Never trust an unverified payload — see Signatures.
  • Idempotency on receive. Aeses may deliver the same event more than once. Use event.id as a dedup key.
  • Out-of-order delivery. Events for the same resource may arrive out of order. Always reconcile against the resource's status field, not the order of arrival.
  • Test from the dashboard. Use Developers → Webhooks → Send test event to fire a payload at your endpoint without involving the blockchain.
  • Use ngrok in development. A public HTTPS URL is required even in test mode.

Webhook endpoints vs. inline URLs

You can set a webhook URL in two places:

  • Account-level endpoints — configured in the dashboard. Receive every event of every type. Best for production.
  • Per-resource webhook_url — passed when creating a deposit/withdrawal. Receives events for that resource only. Useful when different products inside your organization need disjoint streams.

When both are set, both receive the event.