Webhooks

Receive signed HTTP callbacks for email lifecycle events.

Base URL: https://api.supersendtx.com

Manage endpoints in the dashboard (Webhooks) or via the API / SDK / CLI below.


Authentication

Authorization: Bearer stx_…

Dashboard session cookies also work for browser requests to /api/webhooks.


Supported events

Event When fired
email.received An inbound email arrived on a receive-enabled domain; retrieve full content from /received-emails/{id}
email.sent SuperSend TX accepted the message for delivery
email.delivered The message was delivered to the recipient mailbox provider
email.delivery_delayed Delivery was delayed or temporarily held
email.bounced Hard/soft bounce; recipient is auto-suppressed
email.complained Recipient marked the message as spam/complaint
email.opened Open pixel loaded when open tracking is on
email.clicked Tracked link clicked when click tracking is on
email.failed Delivery failed
email.suppressed Send blocked because a recipient is on the suppression list
email.scheduled Email accepted with scheduled_at
automation.started An active automation matched an incoming event and a run was created
automation.step_completed One automation step completed successfully
automation.completed A run finished all steps (or ended early on a false condition)
automation.failed A run failed (send failure, timeout, validation, etc.)

Open/click tracking are domain settings (open_tracking / click_tracking) configured per domain.


Create endpoint

POST /webhooks

{
  "url": "https://yourapp.com/webhooks/supersendtx",
  "events": ["email.delivered", "email.bounced"]
}

events is optional — defaults to all supported events.

200 — Created

{
  "webhook": {
    "id": "clx…",
    "url": "https://yourapp.com/webhooks/supersendtx",
    "events": ["email.delivered", "email.bounced"],
    "enabled": true,
    "created_at": "2026-07-25T12:00:00.000Z",
    "updated_at": "2026-07-25T12:00:00.000Z"
  },
  "secret": "whsec_…"
}

Copy secret immediately — it is only returned once. Use it to verify incoming webhook signatures.


List endpoints

GET /webhooks

Cursor pagination: limit, cursor{ webhooks, has_more, next_cursor }.


Retrieve endpoint

GET /webhooks/{id}

{
  "webhook": {
    "id": "clx…",
    "url": "https://yourapp.com/webhooks/supersendtx",
    "events": ["email.delivered", "email.bounced"],
    "enabled": true,
    "created_at": "2026-07-25T12:00:00.000Z",
    "updated_at": "2026-07-25T12:00:00.000Z"
  }
}

Update endpoint

PATCH /webhooks/{id}

{
  "url": "https://yourapp.com/new-path",
  "events": ["email.bounced"],
  "enabled": false
}

All fields are optional.


Delete endpoint

DELETE /webhooks/{id}

{ "ok": true }

Test sink

POST /emails/test (full-scope API key)

{ "event": "email.bounced", "email_id": "msg_…", "deliver": true }

Builds a webhook payload (optionally for an existing email) and, when deliver is not false, enqueues delivery to your subscribed endpoints. Useful in CI.


Incoming webhook payload

SuperSend TX POSTs JSON to your endpoint URL when a subscribed event occurs.

Email event example

{
  "type": "email.received",
  "created_at": "2026-07-25T12:05:00.000Z",
  "data": {
    "email_id": "inb_abc123…",
    "to": ["sales@inbound.example.com"],
    "from": "Sender <sender@example.com>",
    "subject": "Hello",
    "status": "received",
    "rcpt_to": "sales@inbound.example.com",
    "cc": [],
    "message_id": "<abc@example.com>",
    "in_reply_to": null,
    "references": [],
    "spam_status": "NotSpam",
    "attachment_count": 1,
    "attachments": [
      {
        "filename": "invoice.pdf",
        "content_type": "application/pdf",
        "size": 48291
      }
    ],
    "received_at": "2026-07-25T12:04:59.000Z"
  }
}

For inbound events, attachment metadata is included but attachment bytes are not — fetch /received-emails/{id} for full bodies and base64 attachment data.

For bounces, type is email.bounced, status is bounced, and bounce_reason may contain a provider reason string.

Automation event example

{
  "type": "automation.step_completed",
  "created_at": "2026-07-26T12:05:00.000Z",
  "data": {
    "automation_id": "a1b2c3",
    "automation_name": "Welcome flow",
    "run_id": "r1s2t3",
    "status": "running",
    "event_name": "user.created",
    "step_index": 0,
    "step_type": "send_email",
    "error": null
  }
}

Signature verification

Each delivery includes:

SuperSendTX-Signature: t=1721908800,v1=abc123…

SDK helper (preferred)

import { SuperSendTX, verifyWebhookSignature } from 'supersendtx'

const ok = verifyWebhookSignature(secret, rawBody, request.headers.get('supersendtx-signature'))
// or:
const client = new SuperSendTX(process.env.SUPERSENDTX_API_KEY!)
client.webhooks.verify(secret, rawBody, header)

Verify by:

  1. Read the raw request body as a string (before JSON parsing).
  2. Parse t (Unix timestamp) and v1 (hex HMAC) from the header.
  3. Reject if t is more than 5 minutes from your server clock.
  4. Compute HMAC-SHA256(secret, "${t}.${rawBody}") and compare to v1 (constant-time).

Return 2xx quickly from your handler. Failed deliveries are retried by Bull at 0s, 5s, 30s, 2m, 2m (persisted in Redis via the supersendtx:webhook-delivery queue). Run the worker:webhooks process alongside the app.


SDK

import { SuperSendTX } from 'supersendtx'

const client = new SuperSendTX(process.env.SUPERSENDTX_API_KEY!)

const { webhook, secret } = await client.webhooks.create({
  url: 'https://yourapp.com/webhooks/supersendtx',
})

const { webhooks } = await client.webhooks.list()
const one = await client.webhooks.get(webhooks[0].id)
await client.webhooks.update(one.webhook.id, { enabled: false })
await client.webhooks.delete(webhooks[0].id)

CLI

supersendtx webhooks list
supersendtx webhooks create --url https://yourapp.com/hooks
supersendtx webhooks delete --id clx…

Requires SUPERSENDTX_API_KEY or --api-key.


OpenAPI

Machine-readable spec: openapi/supersendtx.yaml