Skip to main content

Send your first transactional email

This is the one-shot path to a first real send: verify your domain, create a sender, render a template, dispatch, and watch the result arrive on a webhook. Everything below is runnable — substitute your own API key, domain, and recipient. For the full day-one-to-at-scale plan (warm-up ramps, bulk patterns, deliverability posture), see the Email channel lifecycle guide. This page gets you to one delivered email; that one takes you to volume. You will:
  1. Verify your sending domain
  2. Create a sender profile
  3. Send a templated message
  4. Subscribe to delivery and bounce events
  5. Handle the suppression list
  6. Debug the common first-send errors
  7. Hand off to the at-scale plan
Prefer to skip DNS work while you learn the API? Finish the round trip first against the sandbox — a test key (dv_test_sk_...) or the X-Test-Mode: true header runs the same request shapes with nothing delivered and no real recipient touched. The sandbox guide is Sandbox and test mode; register the real domain in step 1 before your first live send.
Every example below assumes a verified domain and a registered sender. If you draft them against a sandbox key (dv_test_sk_...), they short-circuit before delivery but still exercise validation, so the integration code you write in the sandbox runs unchanged on live keys. Do the domain verification in step 1 before you flip to live traffic.

1. Verify your sending domain

Everything downstream — sender validation, tracking, deliverability — hangs off a verified domain. Add your domain under Channels → Email → Domains, which lists the exact DNS records (SPF, DKIM, DMARC, and the Return-Path CNAME) to publish at your DNS provider. Once the records propagate, run Verify DNS on the domain row and confirm the per-record traffic-light view grades green:
Every record you intend to sign with must grade valid. If your DNS lives in a Cloudflare zone, the Cloudflare auto-configure guide can create the missing records for you from the same domain row; either way, re-run Verify DNS after any manual change.

2. Create a sender profile

Sends need a registered sender row so the platform can bind your from address to a verified domain. Register one under Channels → Email → Senders, or over the API:
The response carries your sender id (esend_...). When you later omit from on a send, the sender marked isDefault resolves the address; set that flag on the one you want as the fallback. One sender row is enough for a first send — add aliases later.

3. Send a templated message

The send endpoint takes a finished html (or text) body — it does not accept a template_id. Either html or text must be non-empty, or the request is rejected before anything is queued. The one-shot send — inline body, curl, done:
A clean dispatch returns 202 with data.succeeded carrying one row per recipient, and the envelope meta.request_id to correlate with the webhook events below. For template variables ({{...}} merge tags in a saved block layout) you render first, then send the rendered HTML — two passes:
  1. Render with POST /api/v1/messages/email-builder/render. The response carries the rendered html, an AMP-for-Email alternative, and a templateId to correlate with a later save.
  2. Resolve every {{...}} tag in the rendered HTML, then dispatch it through the same send endpoint. An unresolved tag lands on the wire as the literal string, so resolve them all before sending.
Save the template for reuse with POST /api/v1/messages/email-builder/save — the full mechanics are in Using Templates.

4. Subscribe to delivery and bounce events

Register one endpoint that subscribes the delivery family and the engagement pair, and filter on channel: "email":
  • message.delivered — accepted by the recipient server
  • message.failed — bounced (hard or soft) or marked as spam
  • email.opened / email.clicked — engagement (first-open deduped; clicks fire on every distinct click)
Verify the X-Orbit-Signature header on every delivery and return 2xx within the delivery window — the walkthrough is in Receive your first webhook. In sandbox mode the send is short-circuited, so you can exercise your verification and retry handling without a live recipient; the sandbox guide covers the canned outcomes.

5. Handle the suppression list

Hard bounces, exhausted soft bounces, complaints, and unsubscribes are held out of future sends automatically, and the served quota slot is refunded at the pre-send gate. Manage the list yourself under Channels → Email → Suppressions — search it, export, add manual entries, or bulk-import from a previous ESP. Removal is a deliberate action: a re-bounce or a re-complaint re-suppresses the address. For a per-contact reachability check before you route a send, use the contact deliverability health guide.

6. Common first-send errors

  • Domain unverified (403). A provider-side 403 returns as 403 VALIDATION_ERROR with details.provider_message. Most often this is a sending domain whose verification regressed or never completed. Re-run Verify DNS, then check GET /api/v1/email/domains/:domainId/dns-status until every record grades valid.
  • CHANNEL_NOT_CONFIGURED (503). The email provider was never set up for the tenant. Finish step 1, then your sender in step 2.
  • Suppressed recipient (RECIPIENT_OPTED_OUT, 422). The recipient is on your suppression list and the quota slot is refunded. Route the flow to an alternate channel instead of un-suppressing by reflex.
  • Invalid from (NO_SENDER_CONFIGURED, 422). No sender resolved — either no row owns the address and no default applies, or the defaulted address never got registered. Re-check step 2.
  • VALIDATION_ERROR (422) on the body. Malformed addresses, an empty body, or a disallowed attachment. Either html or text must be non-empty; unresolved merge tags would ship the literal {{...}} string to the recipient, so resolve them all before dispatch.
  • RATE_LIMITED (429). You crossed the per-tenant channel pool (roughly 200 sends per minute). Back off and retry.
The full catalog with remediations is in Error Catalog.

7. At scale

This guide got you one clean send. The Email channel lifecycle guide is the day-one-to-at-scale plan — warm-up ramps before dedicated-IP volume, bulk sends up to 10,000 recipients per call, per-domain open and click tracking, and per-contact deliverability health. The Channels → Email reference indexes the full channel surface.