Skip to main content

Webhooks

Use Motorical delivery webhooks to push real-time email events to your server — deliveries, bounces, complaints, and more.

Managing Webhooks

All webhook endpoints require the webhooks.manage scope.

List Webhooks

curl -H "Authorization: Bearer $TOKEN" \
"$BASE_URL/motor-blocks/$BLOCK_ID/webhooks"

Response: Array of webhook endpoints with id, url, events, enabled, failure_count, last_delivery_at, and created_at.

Create a Webhook

curl -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com/webhook","events":["message.delivered","message.bounced"]}' \
"$BASE_URL/motor-blocks/$BLOCK_ID/webhooks"

If events is omitted, the webhook subscribes to all six events listed under Available Events. Pass an explicit events array for a subset — in particular, omit message.processed and message.deferred unless your application handles intermediate states.

The 201 response returns the signing secret once — it is never retrievable again:

{
"success": true,
"data": {
"id": "9c2f0d81-4b6e-4d2a-9f11-3a7e5c0b8d42",
"url": "https://example.com/webhook",
"events": ["message.delivered", "message.bounced"],
"enabled": true,
"created_at": "2026-08-25T12:00:00.000Z",
"secret": "…48 hex chars…",
"secretMasked": "ab12…"
},
"message": "Webhook created. The full \"secret\" is shown once — store it now for signature verification (X-Motorical-Signature)."
}

Store data.secret immediately. It is the key for the HMAC-SHA256 verification below; losing it means deleting and recreating the webhook.

Update a Webhook

curl -X PUT -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com/new-url","enabled":true}' \
"$BASE_URL/motor-blocks/$BLOCK_ID/webhooks/$WEBHOOK_ID"

Updatable fields: url, events (array), enabled (boolean).

Delete a Webhook

curl -X DELETE -H "Authorization: Bearer $TOKEN" \
"$BASE_URL/motor-blocks/$BLOCK_ID/webhooks/$WEBHOOK_ID"

Test a Webhook

Send a test delivery to verify your endpoint is reachable:

curl -X POST -H "Authorization: Bearer $TOKEN" \
"$BASE_URL/motor-blocks/$BLOCK_ID/webhooks/$WEBHOOK_ID/test"

Returns 202 Accepted with a queued test delivery.

Delivery History

View recent webhook deliveries with status and latency:

curl -H "Authorization: Bearer $TOKEN" \
"$BASE_URL/motor-blocks/$BLOCK_ID/webhooks/$WEBHOOK_ID/deliveries?limit=50"

Parameters:

ParameterDescription
limitMax deliveries to return (1–200, default 50)

Response: Array of deliveries with eventType, status, attempts, error, latencyMs, createdAt, and deliveredAt.

Signature Verification

Every webhook POST is signed with X-Motorical-Signature — an HMAC-SHA256 of the JSON body using your secret. Always verify this signature before processing the payload.

const crypto = require('crypto');

function verifyWebhookSignature(body, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(JSON.stringify(body))
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}

Available Events

EventDescription
message.processedAccepted by the gateway and handed to delivery — an intermediate event, not a final outcome
message.deferredDelivery temporarily delayed; a retry is scheduled
message.deliveredAccepted by the recipient's server
message.bouncedBounced (hard or soft)
message.failedPermanent delivery failure
message.complainedRecipient marked the email as spam

Monitoring Webhook Health

Check delivery statistics for a webhook endpoint:

curl -H "Authorization: Bearer $TOKEN" \
"$BASE_URL/motor-blocks/$BLOCK_ID/webhooks/$WEBHOOK_ID/stats?hours=24"

Response includes: delivered count, failed count, queued count, failure rate, and average latency.

Best Practices

  • Respond quickly — return 200 OK within 5 seconds
  • Process asynchronously — queue webhook payloads for background processing
  • Verify signatures — always validate X-Motorical-Signature
  • Handle retries — Motorical retries failed deliveries with exponential backoff
  • Use HTTPS — webhook URLs must use TLS