> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Email sender go-live checklist: domain, sender, first send, suppression, day-two ops

> The launch runbook for a transactional email sender on Devotel Orbit — verify the sending domain over manual DNS or the Cloudflare auto-configure lane, register the sender identity, make the first transactional send, import and test the suppression surface, and arm day-two delivery monitoring — as an owner-assigned go-live checklist.

# Email Sender Go-Live Checklist

This is the email-channel launch runbook for taking a transactional sender live on Devotel Orbit, including the migration case: bringing a sender off a previous ESP with its reputation and suppression history intact. The platform-wide [Production go-live checklist](/guides/go-live-checklist) owns the shared gates — KYC, live keys, webhook hygiene, wallet — and the voice runbooks own telephony ([CCaaS](/guides/voice-ccaas-go-live-checklist), [PSTN](/guides/voice-telephony-go-live-checklist)). This page owns what is specific to email: domain authentication, sender identity, the first transactional send, suppression, and the deliverability surface you watch from day two.

Work sections 1 through 5 in order; each proves the previous one. Then run section 6 as the sign-off. Put an owner on every checkbox before launch day — an unnamed line is an unowned risk.

## 1. The email-sender shape

Four pieces make a sender live:

* **Verified domain.** The sending domain with every DNS record graded `valid`, published manually at your DNS provider or created by the Cloudflare auto-configure lane (section 2).
* **Sender identity.** A registered sender row that binds your `from` address to that domain so the platform can sign and present it (section 2).
* **Transactional template.** The body you dispatch. The send endpoint takes finished `html` or `text`, rendered from your template with every merge tag resolved (section 3).
* **Live API key with send permission.** A `dv_live_sk_` key minted under **Settings → API Keys** for the service that sends. Its `dv_test_sk_` sandbox twin runs the identical request shapes, so the integration code you prove in sandbox runs unchanged on the live key (section 3).

If campaign or newsletter mail will also run through Orbit, decide the stream split now: transactional and marketing on separate senders, per [isolating transactional and marketing streams](/guides/email-streams-isolate-transactional-and-marketing). Bulk volume on a shared sender drags your receipts' deliverability down with it.

## 2. Verify the domain

Add the domain under **Channels → Email → Domains**. The domain row lists the exact record set to publish — the **DKIM** signing record, the **SPF** record, the **DMARC** policy, and the **Return-Path CNAME** — with names and values taken from the console; this page links the DNS lanes rather than re-teaching DNS.

**Manual DNS lane.** Publish the records at your DNS provider, allow for propagation, then run **Verify DNS** on the domain row (or its API equivalent) and read the per-record traffic-light view until every record grades `valid`:

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/settings/channels/email/verify-dns \
  -H "X-API-Key: dv_live_sk_..."
```

```bash theme={null}
curl https://api.orbit.devotel.io/api/v1/email/domains/:domainId/dns-status \
  -H "X-API-Key: dv_live_sk_..."
```

Every record you intend to sign with must grade `valid`. Re-run Verify DNS after any manual change.

**Cloudflare auto-configure lane.** If the zone sits on Cloudflare, the [auto-configure guide](/guides/email-cloudflare-dns-auto-configure) creates the missing records from the same domain row; run Verify DNS afterwards to confirm the green board.

* [ ] **The domain row is fully green.** DKIM, SPF, DMARC, and the Return-Path CNAME all grade `valid` on a Verify DNS run performed today. *Owner: Operations.*

## 3. First transactional send through the API

With a green domain and a registered sender, make the one-shot send. The dispatch endpoint takes a finished body — `html` or `text`, at least one non-empty — and a clean dispatch returns **202** with `data.succeeded` carrying one row per recipient, plus `meta.request_id` to correlate with the webhooks in section 5.

Read the 202 precisely. **Accepted** means Orbit validated the request and queued the send. **Delivered** is the later `message.delivered` webhook, fired when the recipient's mail server accepts the message. A 202 is not inbox placement; never build success or retry logic on it alone.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.orbit.devotel.io/api/v1/messages/email \
    -H "X-API-Key: dv_live_sk_..." \
    -H "Content-Type: application/json" \
    -d '{
      "to": "user@example.com",
      "from": "hello@yourdomain.com",
      "subject": "Your Acme code",
      "html": "<p>Your one-time code: 123456</p>"
    }'
  ```

  ```typescript Node.js theme={null}
  import { Devotel } from '@devotel-orbit/node';

  const orbit = new Devotel({ apiKey: process.env.ORBIT_API_KEY });

  const message = await orbit.messages.sendEmail({
    to: 'user@example.com',
    from: 'hello@yourdomain.com',
    subject: 'Your Acme code',
    html: '<p>Your one-time code: 123456</p>',
  });
  console.log(message.data.succeeded); // one row per accepted recipient
  ```
</CodeGroup>

If the template lives in the visual builder or as a saved block layout, render it first with `POST /api/v1/messages/email-builder/render`, resolve every `{{...}}` merge tag in the returned HTML, then dispatch the rendered body through the same endpoint; an unresolved tag ships to the recipient as the literal string. The full walkthrough, including the sandbox path and the first-send error catalog, is [Send your first transactional email](/guides/first-transactional-email).

* [ ] **A live send returns 202 and the inbox receives it.** The `data.succeeded` row and the later `message.delivered` webhook agree. *Owner: Engineering.*

## 4. The suppression and reputation surface

Hard bounces, exhausted soft bounces, complaints, and unsubscribes are held out of future sends automatically, and the quota slot a held send would have spent is refunded at the pre-send gate. Manage the list under **Channels → Email → Suppressions**: search it, export it, add manual entries, or bulk-import it from your previous ESP on migration day so the suppression posture you built there carries over.

Suppression is also an event stream, not just a table. Bounces and complaints fire on your webhook endpoint inside `message.failed`, held sends surface as suppression events, and a direct send to a suppressed address answers `422 RECIPIENT_OPTED_OUT` with the slot refunded. The field-by-field payload reference is [Email suppression event payloads](/guides/email-suppression-event-payloads); read it before writing the handler so a hard bounce and a complaint are distinguishable in your logs.

Removal from the list is a deliberate act: a re-bounce or a re-complaint re-suppresses the address. For a per-contact reachability read before routing a send, use [contact deliverability health](/guides/contact-deliverability-health).

* [ ] **The previous ESP's suppression list is imported.** Every hard bounce and complaint from the old platform is on the Orbit list before the first live send. *Owner: Operations.*
* [ ] **The handler distinguishes bounce classes.** The webhook consumer parses `message.failed` and the suppression payloads per the [payload reference](/guides/email-suppression-event-payloads) and records them. *Owner: Engineering.*

## 5. Day two — delivery logs, bounce-rate alarm, DLR webhook

Launch day is the easy day. The surface you watch afterwards is what keeps the sender healthy.

**Watch Delivery Logs.** The [Delivery Logs](/guides/delivery-log) view is the per-message event trail — accepted, delivered, bounced, opened — and the first place to look when a recipient domain starts misbehaving. Correlate rows with the `meta.request_id` from your sends.

**Set the bounce-rate alarm.** Arm an alarm over the hard-bounce stream — your webhook consumer, or a Delivery Logs export, computing the hard-bounce share per sender — and page the sender owner when it crosses your threshold inside the launch window. The [Email channel lifecycle guide](/guides/email-lifecycle-guide) covers the warm-up ramps and deliverability posture the threshold protects.

**Wire the DLR webhook.** Subscribe the receipt family — `message.delivered`, `message.failed`, plus `email.opened` and `email.clicked` if you track engagement — on one HTTPS endpoint that verifies `X-Orbit-Signature`, dedupes on the delivery `id`, and acks inside the window. Signature and replay rules live in [webhook security](/webhooks/security); the receiver pattern is in [Receive your first webhook](/guides/first-webhook-quickstart).

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/webhooks \
  -H "X-API-Key: dv_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://yourapp.example.com/webhooks/orbit",
    "events": ["message.delivered", "message.failed", "email.opened", "email.clicked"]
  }'
```

* [ ] **The DLR webhook is live and verified.** Duplicated deliveries produce exactly one side effect in your system. *Owner: Engineering.*
* [ ] **The bounce-rate alarm pages a named owner.** A test hard bounce trips it during the drill, not for the first time during an incident. *Owner: Operations.*

## 6. Go-live checklist

The sign-off. Check a box only when the evidence exists, and only the named owner checks it.

* [ ] **DNS live.** DKIM, SPF, DMARC, and the Return-Path CNAME grade `valid` on a Verify DNS run performed today. *Owner: Operations.*
* [ ] **Sender approved.** The sender row binds the intended `from` address to the verified domain, with `isDefault` set on the fallback sender. *Owner: Operations.*
* [ ] **Template approved.** The transactional body renders with every merge tag resolved, `html` or `text` non-empty, and the compliance owner has signed off the content. *Owner: Compliance.*
* [ ] **First send proven.** A live send returned 202, the inbox received it, and `message.delivered` fired. *Owner: Engineering.*
* [ ] **Suppression webhook tested.** A send to a suppressed address returned `422 RECIPIENT_OPTED_OUT` with the slot refunded, and the bounce and complaint handler records payloads per the reference. *Owner: Engineering.*
* [ ] **Bounce-rate alarm armed.** The alarm pages the sender owner, and Delivery Logs are on the launch-day screen. *Owner: Operations.*
* [ ] **Streams split where needed.** Marketing mail, if any, sends on its own sender per [stream isolation](/guides/email-streams-isolate-transactional-and-marketing). *Owner: Operations.*
* [ ] **Wallet funded.** The balance covers launch volume plus headroom, and low-balance alerts reach the on-call owner. *Owner: Operations/Finance.*

## Related reading

* [Send your first transactional email](/guides/first-transactional-email) — the one-shot first-send walkthrough this checklist stacks on
* [Email channel lifecycle guide](/guides/email-lifecycle-guide) — day one to at-scale: warm-up ramps, bulk patterns, deliverability posture
* [Auto-configure email DNS on Cloudflare](/guides/email-cloudflare-dns-auto-configure) — the automated DNS lane
* [Email suppression event payloads](/guides/email-suppression-event-payloads) — the payload reference for the suppression stream
* [Delivery Logs](/guides/delivery-log) — the per-message event trail
* [Production go-live checklist](/guides/go-live-checklist) — the platform-wide gates this page stacks on
* [PSTN voice go-live checklist](/guides/voice-telephony-go-live-checklist) — the voice sibling of this runbook


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.