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

# Webhooks

> Webhook delivery, HMAC signature verification, idempotency, retries, and event handling guidance for DZap integrations.

# Webhooks

DZap webhook deliveries notify production integrations about asynchronous execution updates, transaction status changes, partner fee events, and operational events. Treat every webhook as untrusted until the signature, timestamp, event ID, and payload shape are verified.

## Delivery headers

Webhook deliveries should include:

```text theme={null}
DZap-Event-Id: evt_01J...
DZap-Timestamp: 1717117200
DZap-Signature: v1=<hex_hmac_sha256>
Content-Type: application/json
```

The signature is an HMAC-SHA-256 over:

```text theme={null}
<DZap-Timestamp>.<raw request body>
```

Use the raw request body bytes, not a parsed and re-serialized JSON object.

## Verification example

```ts theme={null}
import crypto from 'node:crypto';

export function verifyDZapWebhook({
  body,
  timestamp,
  signature,
  secret,
}: {
  body: Buffer;
  timestamp: string;
  signature: string;
  secret: string;
}) {
  const [version, received] = signature.split('=');
  if (version !== 'v1' || !received) return false;

  const payload = Buffer.concat([
    Buffer.from(timestamp),
    Buffer.from('.'),
    body,
  ]);

  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(received, 'hex'),
    Buffer.from(expected, 'hex')
  );
}
```

Reject requests when the timestamp is older than five minutes, the signature is missing, or the event ID has already been processed.

## Idempotency

Store `DZap-Event-Id` before applying side effects. If the same event is delivered again, return `200 OK` after confirming it was already handled. This keeps retries safe.

## Retries

DZap retries failed webhook deliveries with backoff. Your endpoint should return:

* `2xx` after successful processing or idempotent duplicate handling.
* `4xx` when the payload is permanently invalid.
* `5xx` when your system is temporarily unavailable and DZap should retry.

## Event shape

```json theme={null}
{
  "id": "evt_01J...",
  "type": "intent.status.updated",
  "createdAt": "2026-05-30T00:00:00Z",
  "data": {
    "intentId": "int_01J...",
    "status": "executed",
    "txHash": "0x..."
  }
}
```

## Agent guidance

Agents should not create public webhook endpoints without user approval. When reviewing an integration, check that the webhook handler verifies `DZap-Signature`, stores `DZap-Event-Id`, uses the raw body for HMAC verification, and returns `2xx` for duplicate deliveries.
