# Webhook

A **webhook** delivers an event to your endpoint when an async job finishes, so you do not
have to poll. Use them for anything that routinely takes more than 30 seconds — above all
`deep_review`.

## Events

| Event | Fires when |
|---|---|
| `search.completed` / `search.failed` | a Search reaches a terminal state |
| `extraction.completed` / `extraction.failed` | an Extraction finishes |
| `topic_search.completed` / `topic_search.failed` | a TopicSearch finishes |
| `document.parsed` / `document.failed` | a Document finishes parsing |

## Event shape

```json
{
  "object": "event",
  "id": "evt_6sd1xz9jre",
  "type": "search.completed",
  "created_at": "2026-08-10T11:55:02Z",
  "data": {
    "object": "search",
    "id": "srch_9dm2pq4x1a",
    "status": "succeeded",
    "depth": "standard",
    "paper_count": 20,
    "credits_cost": 5,
    "created_at": "2026-08-10T11:54:48Z",
    "completed_at": "2026-08-10T11:55:02Z"
  }
}
```

`data` is the full resource, so a handler usually needs no follow-up `GET`.

## Delivery semantics

- **At-least-once.** Deduplicate by `event.id`; handlers must be idempotent.
- **Retries:** 5 attempts at 1 m, 5 m, 30 m, 2 h, 12 h, on any non-`2xx` or timeout.
- **Ordering is not guaranteed.** Two events for the same resource can arrive out of order; trust the resource's `status`, not arrival order.
- **Disabling:** an endpoint failing every delivery for 7 consecutive days is disabled and the org owner is emailed.

## Verify every delivery

Signature verification is mandatory, not optional — an unverified endpoint accepts forged completions.
The recipe is on webhook-endpoints.

## Related

webhook-endpoints · job · streaming-deep-review
