Webhooks
Register HTTPS endpoints that receive signed POST callbacks when events happen in your account.
Verifying signatures
Every delivery carries an X-Byomailer-Signature header of the form sha256=<hex>, plus X-Byomailer-Timestamp (Unix seconds), X-Byomailer-Event, and X-Byomailer-Delivery (a unique id). Compute the expected signature as HMAC-SHA256(timestamp + "." + rawBody, secret) using your endpoint's signing secret, and compare it with a timing-safe comparison. Reject deliveries whose timestamp is outside a ±5 minute window to prevent replay.
Signature verification
// Node.js example
const crypto = require('crypto');
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(timestamp + '.' + rawBody)
.digest('hex');
const ok = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signatureHeader));/api/v1/webhook-endpointsList all webhook endpoints for the authenticated client. Admin-only. Cursor-paginated. The signing secret is never returned by this endpoint.
Response Fields
idintegerEndpoint ID.
uuidstringEndpoint UUID.
urlstringDestination HTTPS URL.
eventsarraySubscribed event types.
activebooleanWhether the endpoint receives deliveries.
disabled_reasonstring|nullmanual or auto_failures when inactive.
consecutive_failuresintegerFailed deliveries since the last success.
Request
curl -X GET \
"https://byomailer.com/api/v1/webhook-endpoints" \
-H "Authorization: Bearer {your-api-token}" \
-H "Accept: application/json"Response
{
"data": [
{
"id": 1,
"uuid": "wh-uuid-1",
"url": "https://example.com/webhooks/byomailer",
"description": "CRM sync",
"events": [
"contact.subscribed",
"newsletter.sent"
],
"active": true,
"disabled_reason": null,
"consecutive_failures": 0,
"last_triggered_at": "2026-01-15T10:30:00+00:00"
}
],
"meta": {
"path": "https://byomailer.com/api/v1/webhook-endpoints",
"per_page": 25,
"next_cursor": null,
"prev_cursor": null
}
}/api/v1/webhook-endpointsCreate a webhook endpoint. The plaintext signing secret is returned ONCE in this response — store it to verify the X-Byomailer-Signature header. URL must be a public HTTPS endpoint. Supported events: contact.subscribed, contact.unsubscribed, contact.resubscribed, newsletter.sent, sequence_step.sent, sequence.completed.
Request
curl -X POST \
"https://byomailer.com/api/v1/webhook-endpoints" \
-H "Authorization: Bearer {your-api-token}" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/webhooks/byomailer",
"events": [
"contact.subscribed",
"newsletter.sent"
],
"description": "CRM sync"
}'Response
{
"data": {
"id": 1,
"uuid": "wh-uuid-1",
"url": "https://example.com/webhooks/byomailer",
"events": [
"contact.subscribed",
"newsletter.sent"
],
"active": true,
"secret": "whsec_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
}/api/v1/webhook-endpoints/{id}Update an endpoint. Only active and description are mutable — URL and events are immutable, recreate the endpoint to change them.
Request
curl -X PATCH \
"https://byomailer.com/api/v1/webhook-endpoints/{id}" \
-H "Authorization: Bearer {your-api-token}" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"active": false,
"description": "Paused for maintenance"
}'Response
{
"data": {
"id": 1,
"active": false
}
}/api/v1/webhook-endpoints/{id}Delete an endpoint and stop all deliveries to it.
Request
curl -X DELETE \
"https://byomailer.com/api/v1/webhook-endpoints/{id}" \
-H "Authorization: Bearer {your-api-token}" \
-H "Accept: application/json"Response
No content/api/v1/webhook-endpoints/{id}/deliveriesCursor-paginated delivery log for an endpoint.
Request
curl -X GET \
"https://byomailer.com/api/v1/webhook-endpoints/{id}/deliveries" \
-H "Authorization: Bearer {your-api-token}" \
-H "Accept: application/json"Response
{
"data": [
{
"id": 10,
"uuid": "del-uuid-10",
"event_type": "contact.subscribed",
"status": "success",
"attempts": 1,
"response_status": 200,
"delivered_at": "2026-01-15T10:30:01+00:00"
}
],
"meta": {
"per_page": 25,
"next_cursor": null,
"prev_cursor": null
}
}/api/v1/webhook-endpoints/{id}/testQueue a sample test delivery to the endpoint. Rate-limited per client.
Request
curl -X POST \
"https://byomailer.com/api/v1/webhook-endpoints/{id}/test" \
-H "Authorization: Bearer {your-api-token}" \
-H "Accept: application/json"Response
{
"data": {
"id": 11,
"event_type": "webhook.test",
"status": "pending"
}
}/api/v1/webhook-endpoints/{id}/secretRotate the signing secret. The new plaintext secret is returned ONCE; existing receivers fail signature verification until updated.
Request
curl -X POST \
"https://byomailer.com/api/v1/webhook-endpoints/{id}/secret" \
-H "Authorization: Bearer {your-api-token}" \
-H "Accept: application/json"Response
{
"data": {
"id": 1,
"secret": "whsec_yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"
}
}