Documentation

Events, webhooks, and timelines

List mail events, inspect per-message timelines, subscribe webhooks, rotate secrets, retry deliveries, and verify webhook signatures.

Search Docs

StackShift Mail

Events, webhooks, and timelines

Live

List 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

  1. 1List events or inspect a message timeline when debugging.
  2. 2Create a webhook endpoint with a URL and explicit eventTypes.
  3. 3Store the returned secret immediately. It is returned on create and rotate.
  4. 4Verify StackShift webhook signatures with timestamp tolerance before processing.
  5. 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

ts
const 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

ts
import { 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.