Skip to main content
For setup without code, use Settings → Webhooks. This page describes the receiving contract and programmatic management.

Event payload

Mermail sends JSON using POST. This example shows an email received event; identifiers are illustrative.
from, to, cc, and bcc are arrays of formatted address strings when present. Delivery outcomes can include recipient, outcome, and bounce_type. Use recipient to identify the affected recipient of a multi-recipient message. Available text or html may be included. Attachment metadata can include id, filename, mimetype, size, content_id, and disposition. Attachment bytes and private storage URLs are excluded.

Omitted content

Bodies are omitted when content safety checks require it, when stored content is unavailable, or when the event would exceed 1 MiB. Check data.content_omitted_reason, such as content_safety, body_unavailable, or payload_limit. Metadata may also be bounded; data.metadata_truncated: true indicates this happened. Do not assume a missing body is empty. When permitted, fetch the message or attachment through the authenticated Email API. Handle email content as untrusted input, including HTML, links, attachments, and instructions embedded in messages. Synthetic tests include test: true at the top level and data.synthetic: true. Their sample content does not represent a real mailbox message.

Verify each delivery

Each delivery has three signature headers: Use a Standard Webhooks-compatible verifier with the signing value returned when you create the endpoint or rotate it. Keep this value in your receiver’s secure configuration. Do not put it in frontend code or log it. If you implement verification yourself:
  1. Preserve the raw request body bytes before parsing JSON.
  2. Validate the timestamp against a short tolerance, normally five minutes, allowing for clock skew.
  3. Remove the whsec_ prefix from your configured signing value and base64-decode the remaining key.
  4. Compute HMAC-SHA256 over webhook-id + "." + webhook-timestamp + "." + raw_body using those exact bytes.
  5. Base64-encode the result and compare it to the v1 signature using a constant-time comparison.
  6. Parse the verified payload, check its expected workspace and event type, and deduplicate by event_id before processing it.
A retry has the same event ID and payload but a fresh timestamp and signature. Keep deduplication records for at least the seven-day payload retention window. An optional Authorization header is sent in addition to the signature. Return a 2xx response promptly after durably accepting the event. Process slower work asynchronously. If you already accepted an event, acknowledge its duplicate without running the action again. See limits and retries.

Manage webhooks with the API

Use a workspace-scoped API key via x-api-key, with workspace admin authority. All management paths start with:
Create an endpoint with a public URL, a nonempty eventTypes array, and an explicit mailbox selection:
Set allInboxes: false and supply mailboxIds to select individual mailboxes. Prefer their public IDs. The optional authorization field configures your destination’s Authorization header. Create, test, and retry require an Idempotency-Key header: 1–128 characters using letters, digits, ., _, :, or -. Reuse the same key only for the identical request after an uncertain response. A conflicting reuse returns 409. A successful create replay returns the existing endpoint without returning its one-time signingSecret again. Endpoint responses expose urlHost, not the full destination URL or Authorization value. Create and rotation return signingSecret once. In a PATCH, omit url to keep it, use authorization: null to clear the header, or set status to active or paused. Supplying eventTypes replaces the full subscription list. Delivery history accepts limit from 1 to 100, default 25. Pass the returned nextCursor as cursor for the next page. A test or retry returns deliveryId; read history to see whether delivery succeeded.

Manage webhooks with MCP

Use the default full-catalog MCP connection with workspace admin authority. The restricted agent-inbox profile does not expose webhook management. Read tools are list_webhooks, get_webhook, and list_webhook_deliveries. Write tools are create_webhook, update_webhook, delete_webhook, test_webhook, retry_webhook_delivery, and rotate_webhook_secret. Write tools require the existing prepare_destructive_action confirmation bound to their exact arguments. An agent should obtain your approval before configuring external email delivery. Create, test, and retry also require idempotencyKey. Existing credential eligibility and management request limits apply.