Skip to content

Webhooks

Signed HTTP calls to your server when emails are delivered, bounce, get replies and more.

View as Markdown

List webhook endpoints

GET/projects/{project_id}/webhook-endpoints

Every endpoint of the project, in one page.

Parameters

NameInTypeNotes
project_idpathstringRequired
Request
curl "https://sendocado.com/api/v1/projects/$PROJECT_ID/webhook-endpoints" \
  -H "Authorization: Bearer $SENDOCADO_API_KEY"
Response 200
{
  "webhook_endpoints": [
    {
      "id": "bofbcixgy29db8p5qa3e68f7e4qeqpno",
      "project_id": "ujzde8gxd6ncf10epf91dhodzdoc9is0",
      "url": "https://acme.example/webhooks/sendocado",
      "event_types": ["reply.received", "email.bounced"],
      "is_enabled": true,
      "created_at": 1789395200000
    }
  ],
  "next_cursor": null
}

Errors

StatusTypeExample message
401unauthorizedSend a valid API key as "Authorization: Bearer sc_…", or sign in.
404project_not_foundProject not found.
429rate_limitedToo many requests. Try again in 12 seconds.

Add a webhook endpoint

POST/projects/{project_id}/webhook-endpoints

An https URL on the public internet and the event types it gets. The response carries the signing secret; you can read it again later.

Parameters

NameInTypeNotes
project_idpathstringRequired

Body

Send JSON with every field; use null for a value you do not set.

FieldTypeNotes
urlstringRequired
event_types("email.sent" | "email.delivered" | "email.delivery_delayed" | "email.bounced" | "email.complained" | "email.failed" | "email.opened" | "email.clicked" | "reply.received" | "contact.unsubscribed")[]Required
Request
curl -X POST "https://sendocado.com/api/v1/projects/$PROJECT_ID/webhook-endpoints" \
  -H "Authorization: Bearer $SENDOCADO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "url": "https://acme.example/webhooks/sendocado",
  "event_types": ["reply.received", "email.bounced"]
}'
Response 201
{
  "id": "bofbcixgy29db8p5qa3e68f7e4qeqpno",
  "project_id": "ujzde8gxd6ncf10epf91dhodzdoc9is0",
  "url": "https://acme.example/webhooks/sendocado",
  "event_types": ["reply.received", "email.bounced"],
  "is_enabled": true,
  "created_at": 1789395200000,
  "secret": "whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw"
}

Errors

StatusTypeExample message
400invalid_dataSend a JSON request body.
401unauthorizedSend a valid API key as "Authorization: Bearer sc_…", or sign in.
404project_not_foundProject not found.
409conflictThis campaign has enrollments, so it cannot be deleted. Pause it instead.
429rate_limitedToo many requests. Try again in 12 seconds.

Get a webhook endpoint

GET/webhook-endpoints/{webhook_endpoint_id}

is_enabled turns false when every attempt for many events in a row failed; turn it back on with an update.

Parameters

NameInTypeNotes
webhook_endpoint_idpathstringRequired
Request
curl "https://sendocado.com/api/v1/webhook-endpoints/$WEBHOOK_ENDPOINT_ID" \
  -H "Authorization: Bearer $SENDOCADO_API_KEY"
Response 200
{
  "id": "bofbcixgy29db8p5qa3e68f7e4qeqpno",
  "project_id": "ujzde8gxd6ncf10epf91dhodzdoc9is0",
  "url": "https://acme.example/webhooks/sendocado",
  "event_types": ["reply.received", "email.bounced"],
  "is_enabled": true,
  "created_at": 1789395200000
}

Errors

StatusTypeExample message
401unauthorizedSend a valid API key as "Authorization: Bearer sc_…", or sign in.
404webhook_endpoint_not_foundWebhook endpoint not found.
429rate_limitedToo many requests. Try again in 12 seconds.

Update a webhook endpoint

PUT/webhook-endpoints/{webhook_endpoint_id}

Send every field. is_enabled true turns back on an endpoint that was turned off.

Parameters

NameInTypeNotes
webhook_endpoint_idpathstringRequired

Body

Send JSON with every field; use null for a value you do not set.

FieldTypeNotes
urlstringRequired
event_types("email.sent" | "email.delivered" | "email.delivery_delayed" | "email.bounced" | "email.complained" | "email.failed" | "email.opened" | "email.clicked" | "reply.received" | "contact.unsubscribed")[]Required
is_enabledbooleanRequired
Request
curl -X PUT "https://sendocado.com/api/v1/webhook-endpoints/$WEBHOOK_ENDPOINT_ID" \
  -H "Authorization: Bearer $SENDOCADO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "url": "https://acme.example/webhooks/sendocado",
  "event_types": ["reply.received", "email.bounced"],
  "is_enabled": true
}'
Response 200
{
  "id": "bofbcixgy29db8p5qa3e68f7e4qeqpno",
  "project_id": "ujzde8gxd6ncf10epf91dhodzdoc9is0",
  "url": "https://acme.example/webhooks/sendocado",
  "event_types": ["reply.received", "email.bounced"],
  "is_enabled": true,
  "created_at": 1789395200000
}

Errors

StatusTypeExample message
400invalid_dataSend a JSON request body.
401unauthorizedSend a valid API key as "Authorization: Bearer sc_…", or sign in.
404webhook_endpoint_not_foundWebhook endpoint not found.
429rate_limitedToo many requests. Try again in 12 seconds.

Delete a webhook endpoint

DELETE/webhook-endpoints/{webhook_endpoint_id}

No more events are delivered to it.

Parameters

NameInTypeNotes
webhook_endpoint_idpathstringRequired
Request
curl -X DELETE "https://sendocado.com/api/v1/webhook-endpoints/$WEBHOOK_ENDPOINT_ID" \
  -H "Authorization: Bearer $SENDOCADO_API_KEY"

Answers 204 with no body.

Errors

StatusTypeExample message
401unauthorizedSend a valid API key as "Authorization: Bearer sc_…", or sign in.
404webhook_endpoint_not_foundWebhook endpoint not found.
429rate_limitedToo many requests. Try again in 12 seconds.

Get the signing secret

GET/webhook-endpoints/{webhook_endpoint_id}/secret

The secret that signs every delivery to this endpoint.

Parameters

NameInTypeNotes
webhook_endpoint_idpathstringRequired
Request
curl "https://sendocado.com/api/v1/webhook-endpoints/$WEBHOOK_ENDPOINT_ID/secret" \
  -H "Authorization: Bearer $SENDOCADO_API_KEY"
Response 200
{
  "secret": "whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw"
}

Errors

StatusTypeExample message
401unauthorizedSend a valid API key as "Authorization: Bearer sc_…", or sign in.
404webhook_endpoint_not_foundWebhook endpoint not found.
429rate_limitedToo many requests. Try again in 12 seconds.

Rotate the signing secret

POST/webhook-endpoints/{webhook_endpoint_id}/secret-rotations

The new secret signs every attempt from now on, retries of earlier events included, so switch your receiver to it at once.

Parameters

NameInTypeNotes
webhook_endpoint_idpathstringRequired
Request
curl -X POST "https://sendocado.com/api/v1/webhook-endpoints/$WEBHOOK_ENDPOINT_ID/secret-rotations" \
  -H "Authorization: Bearer $SENDOCADO_API_KEY"
Response 201
{
  "secret": "whsec_3yX0aP8qLm2Vn7Bc4Rt9Wd6Kf1Hj5Gs0"
}

Errors

StatusTypeExample message
401unauthorizedSend a valid API key as "Authorization: Bearer sc_…", or sign in.
404webhook_endpoint_not_foundWebhook endpoint not found.
429rate_limitedToo many requests. Try again in 12 seconds.

List delivery attempts

GET/webhook-endpoints/{webhook_endpoint_id}/deliveries

Newest attempt first, with your server’s status code or the error. Kept for 30 days.

Parameters

NameInTypeNotes
webhook_endpoint_idpathstringRequired
cursorquerystring | nullOptional
limitqueryintegerOptional, default 50
Request
curl "https://sendocado.com/api/v1/webhook-endpoints/$WEBHOOK_ENDPOINT_ID/deliveries" \
  -H "Authorization: Bearer $SENDOCADO_API_KEY"
Response 200
{
  "webhook_deliveries": [
    {
      "id": "f4bs3e62rynnefj7qxi6rhxo55zbka52",
      "webhook_endpoint_id": "bofbcixgy29db8p5qa3e68f7e4qeqpno",
      "webhook_event_id": "35ye4scmejvqtia4d5rgn5s7s333h9mt",
      "event_type": "reply.received",
      "attempt": 1,
      "status_code": 200,
      "error": null,
      "duration_ms": 142,
      "created_at": 1790010800000
    }
  ],
  "next_cursor": null
}

Errors

StatusTypeExample message
400invalid_datalimit: Too big: expected number to be <=200
401unauthorizedSend a valid API key as "Authorization: Bearer sc_…", or sign in.
404webhook_endpoint_not_foundWebhook endpoint not found.
429rate_limitedToo many requests. Try again in 12 seconds.

Deliver an event again

POST/webhook-endpoints/{webhook_endpoint_id}/deliveries

One more try, now (202); it shows in the delivery list like any other.

Parameters

NameInTypeNotes
webhook_endpoint_idpathstringRequired

Body

Send JSON with every field; use null for a value you do not set.

FieldTypeNotes
webhook_event_idstringRequired
Request
curl -X POST "https://sendocado.com/api/v1/webhook-endpoints/$WEBHOOK_ENDPOINT_ID/deliveries" \
  -H "Authorization: Bearer $SENDOCADO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "webhook_event_id": "35ye4scmejvqtia4d5rgn5s7s333h9mt"
}'
Response 202
{
  "webhook_event_id": "35ye4scmejvqtia4d5rgn5s7s333h9mt"
}

Errors

StatusTypeExample message
400invalid_dataSend a JSON request body.
401unauthorizedSend a valid API key as "Authorization: Bearer sc_…", or sign in.
404webhook_endpoint_not_foundWebhook endpoint not found.
422invalid_referenceNo template with that id in this project.
429rate_limitedToo many requests. Try again in 12 seconds.