> ## Documentation Index
> Fetch the complete documentation index at: https://docs.anunnakielite.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks

> Signed, retried, idempotency-friendly event delivery.

Currents sends signed HTTP POST requests to your configured `webhook_url` whenever a compliance-relevant event occurs. Webhooks are the canonical channel for asynchronous updates — sanctions reviews, KYC vendor decisions, deposit-limit activations, AML case escalations, and so on.

## Configuring your endpoint

Provide a single HTTPS URL during sandbox onboarding. We POST every event for your tenant to that URL.

## Signature verification

Every request carries three headers:

| Header                 | Purpose                                                                          |
| ---------------------- | -------------------------------------------------------------------------------- |
| `X-Anunnaki-Signature` | Hex HMAC-SHA256 of the raw request body, keyed with your webhook signing secret. |
| `X-Anunnaki-Event`     | The event type, e.g. `kyc.approved`.                                             |
| `X-Anunnaki-Event-Id`  | Stable UUID for this event. Use it for idempotent processing.                    |

Verify the signature using a constant-time comparison against the **raw body bytes** (do not re-serialize a parsed JSON object — whitespace will diverge).

```javascript theme={null}
import crypto from "crypto";

function verifyAnunnakiSignature(rawBody, header, signingSecret) {
  const expected = crypto
    .createHmac("sha256", signingSecret)
    .update(rawBody)
    .digest("hex");
  const a = Buffer.from(header, "hex");
  const b = Buffer.from(expected, "hex");
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}
```

Reject any request whose signature does not verify with **401 Unauthorized**.

## Retry policy

Failed deliveries — anything other than a `2xx` response within 5 seconds — are retried with the following backoff:

| Attempt   | Delay before retry                                                           |
| --------- | ---------------------------------------------------------------------------- |
| 1         | immediate                                                                    |
| 2         | 10 s                                                                         |
| 3         | 60 s                                                                         |
| 4         | 5 min                                                                        |
| 5         | 30 min                                                                       |
| (abandon) | 2 hr — then the delivery is marked `abandoned` and written to the audit log. |

There are **at most 5 attempts**. To survive transient outages, return 2xx as quickly as possible and process asynchronously.

## Idempotent processing

Use `X-Anunnaki-Event-Id` as your idempotency key. We will re-deliver the same event ID under retry; store processed event IDs and short-circuit duplicates.

## Event naming

Events follow `<api>.<event>` — e.g. `exclusion.created`, `limit.breach_attempt`, `kyc.approved`, `sanctions.hit`, `geo.country_restricted`, `aml.escalated`. Each API reference page lists its event catalogue.

## Envelope shape

```json theme={null}
{
  "event_id": "5f9b0e3a-1b8b-4d8c-9f6c-2b5a1b0a3e44",
  "event_type": "kyc.approved",
  "tenant_id": "e9694cc9-16d6-4956-9fce-f387f85881d0",
  "occurred_at": "2026-05-25T07:00:00Z",
  "data": {
    "...": "event-specific payload"
  }
}
```

Raw bodies are stable — keep them around for the duration of your retry window in case you need to re-verify a signature.
