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

# How Dmand AI Webhooks Deliver Enrichment Results

> Receive Dmand AI enrichment results by webhook. Learn how to set a webhook object, choose real-time or batch delivery, and handle the payload envelope.

The Dmand AI API is fully asynchronous. When you submit an enrichment, the API immediately returns a `batch_id` and a `requests` array. Results are delivered later by webhook or retrieved by polling. Webhooks are the recommended way to receive results because they do not count against your rate limit.

## Why webhooks

Webhooks push results to your server as soon as they are ready. You do not need to poll or keep a connection open. They are faster than polling and do not consume your rate limit.

## How it works

1. Include a `webhook` object in your [single](/api-reference/email/submit) or [bulk](/api-reference/email/submit-bulk) submit request.
2. Dmand processes the NPI and resolves or verifies the email.
3. Dmand POSTs the result to your callback URL in the same envelope format used by polling.

## Webhook modes

Choose how you want to receive notifications with the `webhook.mode` field.

* **`real-time`** (default): One webhook per NPI as it resolves. Use this when you want to act on each result immediately.
* **`batch`**: One webhook when the entire batch completes. Use this when you only need the final summary.

## Submit with a webhook

```json theme={null}
{
  "npi": "1003158791",
  "webhook": {
    "url": "https://your-server.com/webhook",
    "mode": "real-time"
  },
  "custom_data": {
    "internal_id": "contact_42"
  }
}
```

## Webhook payload

The payload uses the same envelope as polling and batch poll responses. The `webhook` object describes the delivery configuration, and `data` contains the per-NPI results.

```json theme={null}
{
  "batch": {
    "id": "b_123",
    "status": "completed",
    "total": 1,
    "completed_count": 1,
    "created_at": "2026-09-28T10:00:00Z",
    "updated_at": "2026-09-28T10:00:04Z"
  },
  "webhook": {
    "url": "https://your-server.com/webhook",
    "mode": "real-time",
    "status": "delivered"
  },
  "custom_data": {
    "internal_id": "contact_42"
  },
  "usage": {
    "credits_used": 1,
    "balance": 999
  },
  "data": [
    {
      "request_id": "r_456",
      "npi": "1003158791",
      "status": "completed",
      "replayed": false,
      "email_type": "professional",
      "email": "jane.doe@examplehealth.org",
      "email_last_validated": "2026-09-20T00:00:00Z",
      "email_status": "valid"
    }
  ]
}
```

If no `webhook` was provided, the `webhook` field is `null`.

## Echoing custom data with custom\_data

Include `custom_data` in the submit body to attach any JSON object. It is echoed verbatim in every poll response and webhook payload. Use it to pass internal identifiers, correlation IDs, or tags so you can match results to your own records.

## Responding to webhooks and retry behavior

Your endpoint must return an HTTP 2xx response as quickly as possible. Perform heavy processing asynchronously so you do not block the response. If your endpoint returns a non-2xx response, Dmand retries delivery with backoff.

Make your handler idempotent and deduplicate by `request_id` to avoid processing the same result more than once.

## Testing webhooks

Use [webhook.site](https://webhook.site) to get a temporary URL and inspect real payloads without setting up your own server.

## Polling fallback

If you cannot receive webhooks, you can poll `GET /api/v1/email/{request_id}` or `GET /api/v1/batch/{batch_id}`. Polling consumes your rate limit and delivers results more slowly. If you must poll, space requests at reasonable intervals. Do not rely solely on webhooks; poll as a fallback if a webhook does not arrive.
