Skip to main content

Email API

Endpoints under the /api/v1/email base path. This page covers the public one-click unsubscribe handler and the authenticated recipient validation (list-hygiene) endpoints. Sending email goes through the unified Messaging API. Base path: /api/v1/email

Unsubscribe

The public one-click unsubscribe surface that the List-Unsubscribe and List-Unsubscribe-Post headers in outbound email reference. RFC 8058 compliant. Authentication: HMAC-token (embedded in URL). Not Clerk-authenticated — these URLs are designed to be opened by the recipient’s mail client without any session. You don’t typically call these endpoints from your own application — Orbit injects the URLs into outbound email automatically.

Recipient validation

Real-time recipient list-hygiene checks (SendGrid Email Validation API parity). Score an address before you send to it: syntax, disposable-domain and role-account detection, MX presence, a likely-typo correction, and an aggregate 01 risk score with a coarse low/medium/high band. Pure DNS + heuristics — no SMTP mailbox probing and no third-party feed. Addresses are not persisted (transient validation only). Authentication: standard workspace auth (X-API-Key or dashboard session). Both endpoints require an authenticated workspace, but the auth level differs: single-address POST /email/validate additionally requires an owner or admin role, while POST /email/validate/bulk is open to any authenticated workspace member. A non-admin caller hitting POST /email/validate gets a 403.

POST /api/v1/email/validate

Requires an owner or admin role. A workspace member without one of these roles receives a 403. Request body:
Response data:

POST /api/v1/email/validate/bulk

Available to any authenticated workspace member — no owner/admin role required. Validate up to 1000 addresses in one call. Input is de-duplicated case-insensitively before scoring. Request body:
Response data:
Each row carries a single machine-readable reason code — one of deliverable, invalid_syntax, no_mx_record, disposable_domain, role_account, possible_typo, or mx_unknown — so importers can branch deterministically. The summary.risky count is the number of deliverable but flagged rows (disposable / role / typo / non-low band) a sender should review before importing.

See also