# Webhooks

Receive real-time events for card authorizations, settlements, and refunds.

Card webhooks notify your server about card transaction activity as it happens. Register endpoints from your dashboard under **Developers → Cards**.

## Endpoint scope

Each webhook endpoint is **product-scoped**. An endpoint registered under Developers → Cards receives **only** card events — it never receives banking or checkout events. Each endpoint has its own verification token, and you can register more than one.

## Event types

| Event | When |
|-------|------|
| `card.transaction.approved` | A card authorization is approved. |
| `card.transaction.denied` | A card authorization is declined. |
| `card.transaction.pending` | An authorized spend is pending/in-flight. |
| `card.transaction.completed` | A spend settles; `data.amount` is the final posted amount. |
| `card.transaction.reversed` | A prior authorization is reversed (hold released). |
| `card.transaction.refunded` | A refund is credited back to the card. |

## Payload

Every delivery wraps the transaction in a common envelope. `data` is the same shape returned by [`GET /v1/activity?type=cards`](/docs/cards-balance-activity).

```json
{
  "id": "evt_01HXR9...",
  "type": "card.transaction.approved",
  "createdAt": "2026-04-08T12:00:00.000Z",
  "livemode": true,
  "data": {
    "id": "ctxn_123",
    "cardId": "126b6996-9c99-4732-9a58-3d8721e30bc8",
    "cardLast4": "4242",
    "occurredAt": "2026-04-08T12:00:00.000Z",
    "settledAt": null,
    "description": "Northstar Media",
    "merchant": {
      "name": "Northstar Media",
      "city": "Sao Paulo",
      "country": "BR",
      "category": "Advertising",
      "enrichedName": "Northstar Media",
      "enrichedCategory": "Advertising"
    },
    "amount": "-42.50",
    "currency": "USD",
    "direction": "debit",
    "category": "purchase",
    "status": "pending",
    "declinedReason": null,
    "disputeStatus": null
  }
}
```

## Verifying deliveries

Every request includes these headers:

- `X-Dolafy-Token` — your per-endpoint verification token, shown once when the endpoint is created.
- `Dolafy-Event-Id` — unique event id (also the body `id`).
- `Dolafy-Event-Type` — the event type.
- `Dolafy-Delivery-Id` — unique delivery id; retries of the same delivery reuse it.

Compare `X-Dolafy-Token` to the token you stored at creation and reject the request if it does not match. There is no HMAC signature — because the token is sent on every request, your endpoint must use HTTPS, keep the token secret, and avoid logging request headers. Rotate the token by recreating the endpoint.

## Delivery semantics

- Respond with a `2xx` quickly, then process the event asynchronously.
- Delivery is **best-effort and single-attempt** for card events. There is no durable retry queue or replay endpoint.
- **Make your handlers idempotent** by `Dolafy-Event-Id` (or `Dolafy-Delivery-Id`), and reconcile anything you may have missed with [`GET /v1/activity?type=cards`](/docs/cards-balance-activity).
- Manual test deliveries sent from the dashboard include top-level `"test": true`. Never fulfil or move money from a test event.
