Webhooks

Create webhook

Register a webhook. Returns 201 with the webhook and its signing secret. This is the only time the full secret is shown, so store it now.

POSThttps://api.sndr.sh/v1/webhooks
Create webhook
curl -X POST 'https://api.sndr.sh/v1/webhooks' \
  -H "Authorization: Bearer $SNDR_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
    "url":    "https://your-app.com/webhooks/sndr",
    "events": ["email.delivered", "email.bounced", "email.failed"]
  }'
201Created
{
  "id":              "wh_2a7d4e9c-6b1",
  "organization_id": "org_8d41c7a2-3f6",
  "url":             "https://your-app.com/webhooks/sndr",
  "events":          ["email.delivered", "email.bounced", "email.failed"],
  "secret_prefix":   "whsec_Xk9pQ2",
  "active":          true,
  "created_at":      "2026-06-01T12:00:00Z",
  "secret":          "Xk9pQ2vLr8TzW4mN1bYcE7hJ0aSdFgUi"
}

Authorization

Authorizationstringheaderrequired

Bearer followed by your API key. Needs the send scope.

Body

application/json
urlstringrequired

Public HTTPS URL. Hosts that resolve to private, loopback or link-local addresses are rejected.

eventsstring[]required

Events to receive, at least one of: email.delivered, email.bounced, email.failed, email.unsubscribed (email.queued and email.complained are accepted but not sent).

Errors

401unauthenticatedMissing or invalid API key.
400invalid_requestBody is not valid JSON, url is missing or not a URL, or an event name is not supported.
402plan_limit_reachedThe plan’s webhook limit is reached.
403insufficient_scopeThe API key is missing the send scope.
422validation_failedurl is not https, cannot be resolved, or points at a private address.