Public Endpoints

These routes are public-facing and usually accessed from email links or embedded forms.

These routes are public-facing and usually accessed from email links or embedded forms.

Health check

  • GET /api/v1/health

Tracking

  • GET /t/o/:emailSendId (open pixel)
  • GET /t/c/:emailSendId/:encodedUrl (click redirect + tracking)

Unsubscribe

  • POST /unsub/:token (RFC 8058 one-click unsubscribe)
  • GET /unsub/verify/:token (validate token and fetch page context)

Preference center

  • GET /prefs/verify/:token
  • POST /prefs/update/:token

Contact double opt-in

  • GET /confirm/doi/verify?token=...
  • POST /confirm/doi?token=...

Form submission

  • POST /forms/:formId

Campaign archive

  • GET /archive/:token — returns the archived HTML snapshot of a sent campaign

Public-facing endpoint for "View in Browser" links. Returns the campaign content as it appeared at send time.

200 OK — success bodies use the action-mode envelope { "ok": true, "data": { ... } }:

{
  "ok": true,
  "data": {
    "html": "<html>...</html>",
    "subject": "Our biggest sale of the year",
    "sentAt": 1741616400000,
    "organizationName": "Acme Inc."
  }
}

sentAt is a Unix-millisecond timestamp (a number), not an ISO string.

404 Not Found — the token does not match any archived campaign. Failures use the locked error envelope:

{
  "error": {
    "category": "not_found",
    "message": "Archive not found",
    "data": { "reason": "archive_not_found" }
  }
}

The archive token is unique per campaign and included in the email's "View in Browser" link. Archive endpoints are rate limited and CORS enabled. Successful responses set Cache-Control: public, max-age=3600.

  • GET /share/:token — returns the HTML snapshot of a shared email template preview

Public-facing endpoint for expiring share links created from the email editor. Returns the email content as it appeared when the link was created. Links expire after 48 hours.

Responses:

  • 200 OK — valid share link. Success bodies use the action-mode envelope { "ok": true, "data": { ... } }:
{
  "ok": true,
  "data": {
    "html": "<html>...</html>",
    "subject": "Welcome to our product",
    "previewText": "Here's what you need to know",
    "organizationName": "Acme Inc.",
    "expiresAt": 1742486400000
  }
}

expiresAt is a Unix-millisecond timestamp (a number).

  • 404 Not Found — token is invalid or the link has been revoked. The locked error envelope carries category: "not_found" and data.reason: "share_link_not_found":
{
  "error": {
    "category": "not_found",
    "message": "Share link not found",
    "data": { "reason": "share_link_not_found" }
  }
}
  • Expired link (48-hour window passed) — data.reason is expired:
{
  "error": {
    "category": "not_found",
    "message": "This share link has expired",
    "data": { "reason": "expired" }
  }
}
Expired-link status

The expired case maps to HTTP 404 (not_found), not 410 Gone — the shell derives the status from the error category and has no 410 mapping. Discriminate on data.reason: "expired" rather than on the status code.

The share token is a 24-character random string. Share link endpoints set Cache-Control: no-store (unlike archive, which is cacheable for an hour) since the content expires.

Inbound MTA callbacks

These routes live on the same HTTP router but are server-to-server callbacks from the bundled MTA and IMAP services, not browser- or email-link flows. They are authenticated at the transport layer (shared secret / HMAC), so general clients should not call them.

  • POST /webhooks/mta-mailbox — Postbox (personal-mail) inbound delivery from the MTA. See Postbox Architecture.
  • POST /webhooks/mta-verify-credential — app-password verification for MTA SMTP submission and IMAP/SMTP client auth (HMAC-signed). See Postbox Architecture.

The bounce/complaint/IP delivery-event callback POST /webhooks/mta is documented on the Webhooks page.

Notes

  • CORS is enabled where required for browser-based flows
  • Public endpoints are rate-limited by IP (per-recipient token endpoints such as archive/share/unsubscribe are keyed on IP+token)
  • Tokenized endpoints return structured JSON for invalid/expired tokens