StackShift Mail
Events, webhooks, and timelines
LiveList mail events, inspect per-message timelines, subscribe webhooks, rotate secrets, retry deliveries, and verify webhook signatures.
Goal
Build reliable downstream automation from StackShift Mail events without trusting unsigned payloads.
Current status
Live
This area is documented as current, user-reliable behavior.
Workflow
- 1List events or inspect a message timeline when debugging.
- 2Create a webhook endpoint with a URL and explicit eventTypes.
- 3Store the returned secret immediately. It is returned on create and rotate.
- 4Verify StackShift webhook signatures with timestamp tolerance before processing.
- 5Use delivery detail and retry APIs for failed webhook deliveries.
Event types
- Message events: mail.message.queued, mail.message.sending, mail.message.sent, mail.message.deferred, mail.message.failed, mail.message.bounced, mail.message.suppressed.
- Suppression events: mail.suppression.created and mail.suppression.deleted.
- OTP events: mail.otp.created, mail.otp.sent, mail.otp.verified, mail.otp.failed_attempt, mail.otp.failed, mail.otp.expired, and mail.otp.canceled.
- Template events: mail.template.created, mail.template.updated, mail.template.deleted, mail.template.version.created, and mail.template.test_sent.
- Domain events: mail.domain.created, mail.domain.verified, mail.domain.failed, and mail.domain.deleted.
- Webhook events: mail.webhook.created, mail.webhook.updated, mail.webhook.disabled, mail.webhook.delivery.succeeded, and mail.webhook.delivery.failed.
Create a webhook
Example
tsconst webhook = await stackshift.mail.webhooks.create({
url: 'https://example.com/webhooks/stackshift-mail',
description: 'Production mail lifecycle events',
eventTypes: [
'mail.message.sent',
'mail.message.bounced',
'mail.otp.verified',
],
})
// Store webhook.secret now. It is only returned on create or rotate.
console.log(webhook.id, webhook.secret)Verify a signature
Example
tsimport { verifyWebhookSignature } from '@stackshift-cloud/sdk'
const valid = verifyWebhookSignature({
rawBody,
signatureHeader: request.headers.get('StackShift-Signature'),
timestampHeader: request.headers.get('StackShift-Timestamp'),
secret: process.env.STACKSHIFT_MAIL_WEBHOOK_SECRET!,
toleranceSeconds: 300,
})
if (!valid) throw new Error('Invalid StackShift Mail webhook signature')Operational APIs
- GET /mail/events filters by type, resourceType, resourceId, messageId, from, to, limit, and cursor.
- GET /mail/messages/{id}/timeline returns timeline items with type, label, createdAt, and optional metadata.
- GET /mail/webhooks/{webhookId}/deliveries filters webhook deliveries by status, limit, and cursor.
- GET /mail/webhook-deliveries/{deliveryId} includes delivery attempts.
- POST /mail/webhook-deliveries/{deliveryId}/retry requests a retry for a delivery.
Expected result
Your application processes mail lifecycle events once, verifies signatures, and can recover failed webhook deliveries.
Common failures
- Webhook handler does not preserve the raw request body before JSON parsing.
- Signature verification uses the wrong secret after rotation.
- Handler is not idempotent and double-processes retried events.
- Endpoint repeatedly returns non-2xx responses and deliveries move from failed toward abandoned.