Skip to main content
Durable operations such as imports, launches, replies and warmup changes finish in a worker. A webhook endpoint receives a signed event when one of them reaches an outcome, so you do not have to poll get_api_operation. Webhooks need the webhooks:read and webhooks:manage scopes, an owner or admin identity and a host with webhooks enabled. A disabled host answers 503 webhooks_unavailable.

Register an endpoint

Call create_api_webhook_endpoint with an https:// URL and the event types you want. The URL must resolve only to public internet addresses; Emailx checks it when you save it and again before every delivery, and never follows redirects. Saving does not contact the URL. The response contains secret once. Store it in your secret manager: Emailx never returns it again. If you lose it, rotate the secret. Events carry the operation ID, kind, status, error code and resource, never the operation result. Read details with get_api_operation.

Verify each delivery

Every delivery is a POST with a JSON body and three headers:
  • webhook-id: the event ID. It stays the same on retries and redeliveries.
  • webhook-timestamp: Unix seconds when this attempt was signed.
  • webhook-signature: one or more v1,<base64> values separated by spaces.
The signature is HMAC-SHA256 over {webhook-id}.{webhook-timestamp}.{raw body}, keyed with the base64 bytes after whsec_. Reject a timestamp more than five minutes from your clock, and accept the request if any v1 value matches.
Answer with any 2xx within 10 seconds and do the work afterwards. Deliveries can arrive more than once, so store webhook-id and ignore repeats.

Retries and recovery

A failed attempt (non-2xx, timeout or unsafe destination) is retried after 1 minute, 5 minutes, 30 minutes, 2 hours, 8 hours and 24 hours. After seven attempts the delivery is abandoned. After 50 failed attempts in a row the endpoint switches itself off with disabled_reason: too_many_failures; switch it on again with update_api_webhook_endpoint.
  • Send a test event to check a new endpoint.
  • List deliveries by status to find failures, and read one for its payload and last result.
  • Redeliver a finished delivery once your receiver is fixed. It keeps the same webhook-id.
  • Rotate the secret if it leaks. The old secret keeps signing for 24 hours alongside the new one, so update your receiver within that window.
From the CLI, the same actions live under emailx webhooks. MCP tools are create_webhook_endpoint, send_webhook_test, list_webhook_deliveries and redeliver_webhook, among others.