Inbound email webhook

Use Inbound email webhook to receive inbound.email.received and delivery events with X-Email-Webhook-Secret, event_id, email.id and delivery.message_id.

Developers and messaging admins

Feature availability

Product, package, provider and deployment boundaries for this page.

Available from
Current documentation
Providers
apiwebhookemailresend
Deployment modes
cloud

Before accepting email webhooks

Use this page when an email provider sends inbound customer replies or outbound delivery events into WebRiskOps. The webhook stores inbound messages idempotently and records delivery status events without requiring a shared mailbox workflow.

  • Use placeholder values only; never paste real API keys, webhook secrets, tokens or customer data into documentation examples.
  • Use email event IDs and provider message IDs for duplicate detection.
  • Do not include full mailbox content, secrets or real customer addresses in public examples.

Receive an inbound email webhook

Follow the path `Authentication and headers → POST /api/email/webhook → Inbound routing or delivery event → Automated message workflow`.

  1. Open Authentication and headers and confirm the provider will send `X-Email-Webhook-Secret: ${WEBRISKOPS_EMAIL_WEBHOOK_SECRET}`. Result: the provider request can authenticate without putting the shared secret in the payload.
  2. Configure the email provider to send `POST /api/email/webhook` with `Content-Type: application/json`. Result: route name `email.webhooks.store` receives only normalized JSON webhook events.
  3. For inbound customer replies, set `type` to `inbound.email.received`, include stable `event_id` and optional `occurred_at`. Result: WebRiskOps can detect duplicate provider events.
  4. Include `email.id`, `email.from`, `email.to`, optional `email.subject` and required `email.text`. Result: the inbound message can be stored and routed through automated messaging rules.
  5. Use fictional test values such as `customer@example.test` and `support@example.test` while validating the provider mapping. Result: public examples and tickets do not expose real mailbox content.
  6. For delivery status callbacks, set `type` to `email.sent`, `email.failed`, `email.bounced` or `email.suppressed`, then include `delivery.message_id` and optional `delivery.reason`. Result: the matching outbound message status can be updated.
  7. Add `Idempotency-Key` when the email provider supports retry keys, and keep `event_id` stable for the same provider event. Result: repeated inbound and delivery webhooks are accepted without creating duplicate records.
  8. Review the `202 Accepted` response before enabling production retries. Result: the provider can retry only when the endpoint is unavailable or returns a non-accepted response.
  9. If `UNAUTHORIZED` or a 503 configuration response appears, fix the shared secret configuration before retrying. Result: invalid or unconfigured secrets do not expose submitted values.
  10. If `INVALID_PAYLOAD` or validation errors appear, fix the missing type, event_id, email or delivery fields, then continue to Errors, idempotency, retries and rate limits. Result: malformed provider events are corrected without manual message handling.

Configure email and delivery payloads

Email webhook payloads should stay small and normalized.

  • `type` must be `inbound.email.received`, `email.sent`, `email.failed`, `email.bounced` or `email.suppressed`.
  • `event_id` is the provider event identifier and should not change across retries.
  • `occurred_at` may carry the provider event timestamp.
  • `email.id`, `email.from`, `email.to` and `email.text` are required for inbound email events.
  • `email.subject` is optional and should be shortened by the provider if needed before delivery.
  • `delivery.message_id` is required for delivery events so WebRiskOps can match an outbound message.
  • `delivery.reason` should contain a short provider reason such as `recipient_suppressed`.

Ready email webhook states

Continue only when the provider event can be routed safely.

  • Shared secret ready means `X-Email-Webhook-Secret` matches the configured email webhook secret.
  • Inbound payload ready means type is inbound.email.received and the email object includes id, from, to and text.
  • Delivery payload ready means type is one of the delivery status events and delivery.message_id is present.
  • Duplicate guard ready means event_id and provider message IDs remain stable across retries.
  • Routing ready means inbound email can enter RouteInboundMessage without a shared mailbox or human triage step.

Blocked email webhook states

Blocked email webhooks should explain exactly what to fix.

  • `UNAUTHORIZED` means `X-Email-Webhook-Secret` is missing, invalid or the webhook secret is not configured.
  • `INVALID_PAYLOAD` means required type, event_id, email or delivery fields are missing or malformed.
  • `WEBHOOK_EVENT_DUPLICATE` means the provider resent an already stored event; keep the same event_id and do not create another message.
  • Invalid from or to addresses fail validation before inbound routing runs.
  • Full mailbox threads, attachments, tokens or real customer examples should be removed from public examples before retrying.

Continue after email webhook

After `202 Accepted`, continue to the automated message workflow for inbound replies or outbound delivery diagnostics for delivery events. Use Authentication and headers for shared-secret failures, Request and response examples for copyable placeholder requests, and Errors, idempotency, retries and rate limits when provider retries or validation errors need interpretation.

Related documentation

Was this page helpful?

Feedback goes into the product documentation review queue.