Skip to main content
Register an endpoint once, and every job event is POSTed to it.
The answer holds the endpoint’s signing secret (whsec_...), shown only now. topics may also include mailbox.disconnected, job.corrected (a reviewer corrected a finished job, or reverted a correction) and email.received. An empty list receives every topic except the opt-in job.corrected and email.received, which an endpoint receives only when it lists them. The CRM integrations can take job.corrected too.

The event

The payload never carries the merchant’s transactions. Fetch result_path with your API key for the full result. intake is the job’s intake: who sent the packet, by which email, for which of your end users, with which files. It is in every job event, job.failed included, so a job that failed before anything was read still names its broker and its email.

email.received

An endpoint that lists email.received gets one event for every inbound email, the moment it is taken: jobs, merges, ignored and refused emails alike, so a CRM can track each one. A redelivery of the same message sends no second event.
It carries the email’s envelope and outcome, never its body or attachments: fetch email_path for the record and /raw for the message. job_id is the job it started or the thread’s job (null when there is none); the job’s own event comes when the job finishes. See Emails and threads.

Verify the signature

Verify against the raw request body, before parsing it.

Delivery

  • Answer 2xx within 10 seconds. Anything else (another status, a timeout, a refused connection) is retried on this schedule, then the delivery is dead: Each time is the earliest: deliveries are picked up every few seconds, and five failures in a row pause the endpoint for 5 minutes (its deliveries wait without spending an attempt), so the last attempt can come later.
  • Every job ends in an event. The event is written in the same transaction as the job’s final status, so it cannot be lost, and pending deliveries survive restarts.
  • Targets must be https and resolve to public addresses. Redirects are not followed.

Missed events

Your endpoint may be down longer than the retries last, or reject events by mistake. To see it, GET /v1/webhooks/{id}/deliveries lists each delivery with its status (pending, delivered, dead, cancelled), its attempts and your endpoint’s last answer. To recover:
  • Re-send one delivery: POST /v1/webhooks/{id}/deliveries/{delivery_id}/resend, for a dead, delivered or cancelled one (409 while it is still pending).
  • Re-send every dead delivery since a time: POST /v1/webhooks/{id}/deliveries/resend?since=<ISO 8601>, for instance from when an outage began. Each event whose delivery died (its last attempt) at or after since is sent once, unless it has been delivered or is pending since.
A re-sent event is the same event, byte for byte: the same body, id and X-Parser-Event-Id, signed afresh. It is a new delivery with the full retry schedule; the earlier one stays in the history. Deduplicate on the event id and a re-send is always safe. Polling covers whatever no webhook brought: GET /v1/jobs?finished_since= lists every job that finished since a time, oldest finish first, each once across its pages. See the sync recipe.

Manage endpoints