Webhooks
Create and manage Webhooks
Retrieve a list of webhooks
GET /webhooks
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
limit | integer | no | Maximum number of webhooks to return. |
after | string | no | Pagination cursor to fetch results after this webhook ID. Cannot be used with 'before'. |
before | string | no | Pagination cursor to fetch results before this webhook ID. Cannot be used with 'after'. |
Example
curl -X GET "$SESAMESEND_URL/webhooks" \
-H "Authorization: Bearer $OPENSEND_API_KEY"Responses
| Status | Description |
|---|---|
200 | OK |
{
"object": "list",
"has_more": false,
"data": [
{
"id": "479e3145-dd38-476b-932c-529ceb705947",
"endpoint": "https://webhook.example.com/handler",
"events": [
"email.sent"
],
"status": "enabled",
"created_at": "2023-10-06 23:47:56.678+00"
}
]
}Create a new webhook
POST /webhooks
Body
| Field | Type | Required | Description |
|---|---|---|---|
endpoint | string | yes | The URL where webhook events will be sent. |
events | string[] | yes | Array of event types to subscribe to. |
Example
curl -X POST "$SESAMESEND_URL/webhooks" \
-H "Authorization: Bearer $OPENSEND_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"endpoint": "https://webhook.example.com/handler",
"events": [
"email.sent",
"email.delivered",
"email.bounced",
"email.suppressed"
]
}'Responses
| Status | Description |
|---|---|
201 | Created |
{
"object": "webhook",
"id": "479e3145-dd38-476b-932c-529ceb705947",
"signing_secret": "whsec_..."
}Retrieve a single webhook
GET /webhooks/{webhook_id}
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
webhook_id | string | yes | The Webhook ID. |
Example
curl -X GET "$SESAMESEND_URL/webhooks/<webhook_id>" \
-H "Authorization: Bearer $OPENSEND_API_KEY"Responses
| Status | Description |
|---|---|
200 | OK |
{
"object": "webhook",
"id": "479e3145-dd38-476b-932c-529ceb705947",
"endpoint": "https://webhook.example.com/handler",
"events": [
"email.sent",
"email.delivered"
],
"status": "enabled",
"created_at": "2023-10-06 23:47:56.678+00",
"signing_secret": "whsec_..."
}Update an existing webhook
PATCH /webhooks/{webhook_id}
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
webhook_id | string | yes | The Webhook ID. |
Body
| Field | Type | Required | Description |
|---|---|---|---|
endpoint | string | no | The URL where webhook events will be sent. |
events | string[] | no | Array of event types to subscribe to. |
status | "enabled" | "disabled" | no | The status of the webhook. |
Example
curl -X PATCH "$SESAMESEND_URL/webhooks/<webhook_id>" \
-H "Authorization: Bearer $OPENSEND_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"endpoint": "https://webhook.example.com/new-handler",
"events": [
"email.sent",
"email.delivered"
],
"status": "enabled"
}'Responses
| Status | Description |
|---|---|
200 | OK |
{
"object": "webhook",
"id": "479e3145-dd38-476b-932c-529ceb705947"
}Remove an existing webhook
DELETE /webhooks/{webhook_id}
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
webhook_id | string | yes | The Webhook ID. |
Example
curl -X DELETE "$SESAMESEND_URL/webhooks/<webhook_id>" \
-H "Authorization: Bearer $OPENSEND_API_KEY"Responses
| Status | Description |
|---|---|
200 | OK |
{
"object": "webhook",
"id": "479e3145-dd38-476b-932c-529ceb705947",
"deleted": true
}Rotate a webhook signing secret
POST /webhooks/{webhook_id}/signing-secret/rotate
Generates a new signing secret for the webhook and returns it. Payloads delivered after the rotation are signed with the new secret. The previous secret keeps verifying payloads for 24 hours, so both secrets are accepted during that window. A webhook that does not exist or was removed returns a 404 not_found.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
webhook_id | string | yes | The Webhook ID. |
Example
curl -X POST "$SESAMESEND_URL/webhooks/<webhook_id>/signing-secret/rotate" \
-H "Authorization: Bearer $OPENSEND_API_KEY"Responses
| Status | Description |
|---|---|
200 | OK |
{
"object": "webhook",
"id": "479e3145-dd38-476b-932c-529ceb705947",
"signing_secret": "whsec_..."
}Retrieve a list of webhook events
GET /webhooks/{webhook_id}/events
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
webhook_id | string | yes | The Webhook ID. |
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
limit | integer | no | Number of items to return. |
after | string | no | Return items after this cursor. |
Example
curl -X GET "$SESAMESEND_URL/webhooks/<webhook_id>/events" \
-H "Authorization: Bearer $OPENSEND_API_KEY"Responses
| Status | Description |
|---|---|
200 | OK |
{
"object": "list",
"has_more": false,
"data": [
{
"id": "msg_1srOrx2ZWZBpBUvZwXKQmoEYga2",
"type": "email.sent",
"created_at": "2026-08-22T15:28:00.000Z",
"status": "success"
}
]
}Retrieve a single webhook event
GET /webhooks/{webhook_id}/events/{event_id}
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
webhook_id | string | yes | The Webhook ID. |
event_id | string | yes | The Webhook Event ID. |
Example
curl -X GET "$SESAMESEND_URL/webhooks/<webhook_id>/events/<event_id>" \
-H "Authorization: Bearer $OPENSEND_API_KEY"Responses
| Status | Description |
|---|---|
200 | OK |
{
"object": "webhook_event",
"id": "msg_1srOrx2ZWZBpBUvZwXKQmoEYga2",
"type": "email.sent",
"created_at": "2026-08-22T15:28:00.000Z",
"status": "attempting",
"next_attempt_at": "2026-08-22T15:33:00.000Z",
"payload": {
"type": "email.sent",
"created_at": "2026-08-22T15:28:00.000Z",
"data": {
"email_id": "571f1f42-1c2d-4b1f-8f8e-8b3b5b3b5b3b",
"from": "onboarding@resend.dev",
"to": [
"delivered@resend.dev"
],
"subject": "Welcome",
"created_at": "2026-08-22T15:27:59.000Z"
}
}
}Replay a webhook event
POST /webhooks/{webhook_id}/events/{event_id}/replay
Queues one more delivery of the event to the webhook. The event must be retrievable through the get event endpoint and the webhook must be enabled; a disabled webhook returns a 422 validation_error. A manual replay does not schedule automatic retries.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
webhook_id | string | yes | The Webhook ID. |
event_id | string | yes | The Webhook Event ID. |
Example
curl -X POST "$SESAMESEND_URL/webhooks/<webhook_id>/events/<event_id>/replay" \
-H "Authorization: Bearer $OPENSEND_API_KEY"Responses
| Status | Description |
|---|---|
200 | OK |
{
"object": "webhook_event",
"id": "msg_1srOrx2ZWZBpBUvZwXKQmoEYga2"
}Retrieve a list of webhook event attempts
GET /webhooks/{webhook_id}/events/{event_id}/attempts
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
webhook_id | string | yes | The Webhook ID. |
event_id | string | yes | The Webhook Event ID. |
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
limit | integer | no | Number of items to return. |
after | string | no | Return items after this cursor. |
Example
curl -X GET "$SESAMESEND_URL/webhooks/<webhook_id>/events/<event_id>/attempts" \
-H "Authorization: Bearer $OPENSEND_API_KEY"Responses
| Status | Description |
|---|---|
200 | OK |
{
"object": "list",
"has_more": false,
"data": [
{
"id": "atmpt_1srOrx2ZWZBpBUvZwXKQmoEYga2",
"http_status_code": 200,
"response": "{\"ok\":true}",
"sent_at": "2026-08-22T15:33:12.000Z"
}
]
}