Set up email sending
Buy or bring sending domains, provision mailboxes, fix DNS, and warm up — so a Sequence has somewhere to send from.
Cold email needs separate sending domains, mailboxes on them, correct DNS, and a warm-up before the first campaign. Pick a road first — switching later means buying twice.
| Managed (OXYGEN buys) | BYOK (your Cloudflare) | |
|---|---|---|
| Prerequisite | none | a Cloudflare account; Registrar access for new domains |
| Domain purchase | billed in OXYGEN credits at the live price | billed to your Cloudflare card, 0 OXYGEN credits |
| SPF / DKIM / DMARC / MX | set by the vendor | vendor setup for managed inboxes, or domains dns plan then dns apply |
| Mailbox | billed in OXYGEN credits per inbox monthly | buy managed inboxes or supply existing Google/Microsoft accounts |
Managed inboxes bill monthly per inbox, in credits (100 credits = $1). From the 2026-09 repricing date a managed Google Workspace or Microsoft 365 inbox is 400 credits ($4) a month together: a flat 300-credit mailbox plus the 100-credit ($1) connected-inbox fee every sending mailbox pays, billed separately, with warm-up included. An Azure tenant (one dedicated Microsoft tenant per domain, a flat monthly charge for up to 100 inboxes) is 4,000 credits ($40) a month, and every inbox on it holds the same connection. The pricing page lists the prices in force in credits and dollars, and oxygen managed-inboxes list --json reports them under prices. A domain registered through OXYGEN costs the registrar's price once a year, 1,250 credits ($12.50) for a .com. Until the repricing date warm-up is its own monthly line. Inbox placement is always an optional add-on. Warm-up is not a managed-road-only cost: a BYOK mailbox enrolled with oxygen mailboxes warmup enable carries the same monthly per-inbox line, so both roads pay it while warm-up runs. From the 2026-09 repricing, warm-up on a mailbox you connected yourself is included in that mailbox's 100-credit monthly connection once the connection is charged; the warm-up preview's included_in_connection says whether it applies to you yet, and then quotes 0. Every price is in the pricing reference. The live preview reports the connection commitment and any separately billed add-ons.
Where this lives
Sidebar Sequencer → Accounts (/sequencer/accounts), tabs Senders / LinkedIn / Email / WhatsApp / Phone numbers. The Email tab nests inboxes under their domains; top-right is Add inboxes. Domains have their own page at /sequencer/domains — by URL only, deliberately not in the sidebar.
Road A — managed inboxes
In the app: Email tab → Add inboxes → Buy managed. The wizard steps Domains → Inboxes → Review; the last button is Buy · <n> cr. The first order asks for a Registrant contact (the WHOIS record); later orders reuse it. Closing mid-order saves the cart — the button becomes Resume order.
From the CLI, preview first — without --approved nothing is ordered or charged:
oxygen managed-inboxes subscribe send-acme.com --provider google \
--file ./mailboxes.json --billing ./registrant.json --jsonThe order includes warm-up by default (--no-warmup opts out); inbox placement is added only with --placement. The preview lists the mailbox line, the add-on lines and, once the all-in price applies, each inbox's mailbox connection (connection_monthly_credits, reserved from your balance once the inbox connects, not charged with the order); total_monthly_credits is what the inboxes cost every month. Check quote_id, the lines, and warmup_activation, then order:
oxygen managed-inboxes subscribe send-acme.com --provider google \
--file ./mailboxes.json --billing ./registrant.json \
--approved --quote <quote_id>--approved spends real credits and registers a real domain. Without a fresh --quote it is refused with quote_required, never charged; a stale quote is refused with quote_mismatch.
subscribe registers a new domain, puts the first inboxes on a domain you bought on its own through OXYGEN, or uses an existing Cloudflare domain with --existing-domain (below). A domain that already has inboxes grows with add-inboxes instead. A domain holds at most 5 Google or Microsoft inboxes (100 on azure), counting existing ones:
oxygen managed-inboxes add-inboxes send-acme.com --count 3 --prefix ada --json
oxygen managed-inboxes add-inboxes send-acme.com --count 3 --prefix ada --approved --quote <quote_id>Who the inboxes are ordered for — the sender profile and its photo
An order is placed for a person: pass --sender <id> (from oxygen senders profiles list --json) and every mailbox in it is stamped with that sender profile's first name, last name, and profile picture. The vendor cannot change any of the three after provisioning, so the profile is the identity to get right, once.
The photo follows one rule. A sender profile with a LinkedIn account attached carries that account's LinkedIn photo automatically — attaching the account (oxygen senders profiles attach <id> --senders <sender-id>, or picking it when creating the sender) mirrors the picture into Oxygen's own storage, and profiles connected before this rule are backfilled. A photo you upload yourself (oxygen senders profiles set-photo <id> --file <path>) or set by URL is your choice and is never overwritten by the LinkedIn one, so an upload always wins; removing the photo of a LinkedIn-connected sender is temporary, because the LinkedIn photo is adopted again on the next sync. Read the result back on the profile: avatar_source says where the picture came from, and avatar_durable: true means Oxygen hosts it and the vendor will still be able to fetch it hours after the order. avatar_durable: false means only an expiring LinkedIn link could be kept — Oxygen re-syncs the LinkedIn account and retries on its own; to fix it right now, upload a file.
Recover canceled managed inboxes
Recovery keeps the original domain, addresses, sender profiles and history when the provider still permits restoration. Inspect canceled subscriptions, then request a free preview:
oxygen managed-inboxes list --status cancelled --json
oxygen managed-inboxes recover send-acme.com --jsonReview eligibility, upfront credits and ongoing hosting plus connection costs. Approve only that scope with oxygen managed-inboxes recover send-acme.com --approved --quote <quote_id> --max-credits <upfront_credits> --json. Microsoft replacement licenses require a new --rebuy preview and separate approval. Hosted MCP offers the same flow through oxygen_managed_inboxes_recover.
An unfinished cancellation must settle before recovery. After provider restoration, verify each inbox's sending authorization and warm-up progress, then resume healthy senders within their existing bounce protections and ramp limits.
Buy a domain on its own
Without a Cloudflare account of your own, Buy domains on /sequencer/domains registers the domain through OXYGEN. It costs the registrar's price in credits for one year (a .com is 1,250 credits) and renews yearly at the registrar's renewal price, charged 30 days before expiry. If your balance cannot pay the renewal, OXYGEN retries for 7 days and then lets the domain lapse.
oxygen domains search acme-mail --json # free: names with their yearly price in credits
oxygen domains buy acme-mail.com --json # free preview + quote_id
oxygen domains buy acme-mail.com --approved --quote <quote_id> --billing ./registrant.json
oxygen domains check acme-mail.com try-acme.com # free: exact names, same prices
oxygen domains renewal acme-mail.com --off # stop renewing; it lapses at expiryThe first purchase needs the registrant (--billing); later ones reuse it. oxygen domains list --json shows the domain under registered_domains with its expiry and next renewal charge. OXYGEN hosts its DNS and sets the mail records when inboxes are added; editing them yourself is not offered.
To send from it, order its first inboxes with the same subscribe command as Road A, or Add inboxes on its row on /sequencer/domains. The preview shows domain_source: owned and no registration charge; Google and Microsoft inboxes are offered:
oxygen managed-inboxes subscribe acme-mail.com --provider google --sender <id> --locals ada,ada.lee --jsonoxygen domains delete acme-mail.com (or Delete on its row) ends the registration: any inboxes on it are cancelled, renewal stops, and the domain leaves the workspace. It stays registered until its expiry, which is not refunded, and this cannot be undone.
Road B — your own Cloudflare
Connect the account once at Connections (/connections), or Connect Cloudflare on /sequencer/domains. The dialog needs a user-owned Cloudflare API token (account-owned tokens cannot use the Registrar API) scoped Zone → Zone: Read, Zone → DNS: Read (DNS Edit to let OXYGEN fix records), and Account → Registrar: Domains: Edit; finish with Verify & connect. Until then the Domains page shows the connect card, not the domain table.
With Cloudflare connected, Buy domains buys through your own Registrar instead. In the app: Buy domains → Get quote → Approve purchase, or from the CLI:
oxygen domains check acme-mail.com try-acme.com # free
oxygen domains buy acme-mail.com --json # priced preview + quote_id
oxygen domains buy acme-mail.com --approved --quote <quote_id>That purchase is non-refundable and bills your Cloudflare account. Registration can stay pending — oxygen domains registration-status acme-mail.com --wait polls to a terminal state.
Already own the domain? Add domain → Apex domain → Create zone, then set the printed nameservers at your registrar (CLI: oxygen domains add acme.com). Nothing works until the nameservers move.
Then write the mail records: plan is free, apply writes into your zone for 0 credits:
oxygen domains dns plan send-acme.com --provider google --json
oxygen domains dns apply send-acme.com --provider google --approved --plan <plan_hash>A stale plan_hash is rejected — re-run plan. Both only work on Cloudflare zones; a managed domain's records are vendor-held, so read them with oxygen domains dns send-acme.com --json instead (--deep is ignored there).
Buy managed inboxes on your existing Cloudflare domains
You can keep the domain at your registrar and purchase Google or Microsoft inboxes through Oxygen. After syncing the domain from Cloudflare, preview:
In the app, open Buy inboxes → Use Cloudflare domains, select domains and set Max inboxes on each domain. Review the DNS scope, blockers and costs before Buy.
oxygen managed-inboxes subscribe acme-mail.com --existing-domain --provider google \
--sender <id> --locals ada,ada.lee --max-per-domain 2 --jsonThe preview shows domain_source: external, zero domain registration charge, the monthly cost and sender identity. existing_domain lists occupied addresses, connection requirements, and the DNS scope. --max-per-domain 2 saves a limit with the approved order of two addresses on that domain, including existing or parked inboxes; future add-inboxes orders honor it. Preview does not save the limit or change workspace data.
For a free connection setup preview, run oxygen integrations connect cloudflare --json without credentials, then use the returned Connections link to enter the token. Use only the permissions required by this mailbox quote; the general integration recommendations also cover domain registration. Submitting credentials creates or replaces the connection immediately. Run oxygen domains sync --json after connecting, then preview the mailbox order again.
Approval connects only the named domain using your customer Cloudflare token and then buys mailboxes once the connection is confirmed active. It does not transfer the registrar, change nameservers or set website forwarding. Use a token with Zone Read and DNS Edit scoped to the selected domain. Oxygen verifies the token's complete policy before sharing it; an unavailable verification or broader grant blocks the connection. DNS Edit permits changes to any DNS record on that domain; the planned connection changes email records. Keep token-management permissions off the delegated token. Oxygen keeps its shared platform token private. During approved managed setup, the inbox provider generates and applies MX, SPF, DKIM and DMARC. This preview shows current records and planned record types; it does not include the provider-generated values. The separate domains dns plan/apply tools are for self-managed DNS. A new provider connection requires all listed existing email DNS records to be absent, even when they match the chosen provider. Your DNS administrator can remove them in Cloudflare after confirming they are unused and approving the exact removal. If the domain receives email, keep the records and choose another domain. Preview again after the records are removed. Oxygen does not delete them automatically. A first subscription on an occupied domain is also blocked until its existing inboxes are reconciled; use add-inboxes for a domain already subscribed through Oxygen. If executable is false, resolve the listed blockers and get a fresh quote. Repeat the same inputs with --approved --quote <quote_id> only after reviewing the cost and DNS scope.
Connect the mailboxes
Your existing Gmail or Microsoft 365 inbox
Where managed mailbox connection is enabled, Add inboxes → Connect existing uses Composio's managed sign-in application for Gmail, Microsoft 365, Exchange Online and Outlook. Each mailbox owner signs in and grants mail access. Reviews contain up to 10 exact addresses. Self-hosted Exchange is not supported.
After importing a missing address, preview its connection:
oxygen mailboxes connect-oauth --provider google --vendor composio \
--mailboxes [email protected] --jsonUse --provider microsoft for Microsoft accounts. Review the 100 credits per
mailbox per month, then repeat with --approved and open the returned
authorization link. Existing paid mailbox coverage is reused. History import,
ongoing sync and CRM analysis are included; analysis adds no separate credit charge.
If the managed connection is unavailable, contact support to finish connecting.
Inbox, Sent and archive history imports in bounded pages while recent mail keeps syncing. Spam, trash and drafts are excluded. Business messages create contacts, companies and email activities, with summaries and intent in Unibox. Personal and automated messages remain in Unibox without CRM records. Existing CRM fields and relationships are preserved; ambiguous identities and deal/stage suggestions need review. Historical messages do not execute campaign reply actions.
oxygen mailboxes sync [email protected] --json
oxygen mailboxes sync [email protected] --action pause --json
oxygen mailboxes sync [email protected] --action pause --approved --jsonThe first command reads history and CRM progress. Actions preview before applying;
resume continues, start restarts history, and disconnect stops importing,
analysis and sending while retaining mail and CRM records. The mailbox panel also
shows progress and links to its Unibox. Existing native and provisioned connections
continue on their current authorization until explicitly reconnected.
Provisioned inboxes and existing native authorization
Provisioning and native campaign sending use separate authorization contracts. For an InboxKit-managed Google order, OXYGEN completes its destination-bound OAuth authorization automatically and unattended after the domain approval lands; verify the exact mailbox with oxygen mailboxes oauth-health instead of opening a second customer sign-in by default. The vendor approval usually lands within minutes, but that is not an SLA: while oauth-health reports client_id_not_approved, no customer action is required and the worker keeps retrying. Zapmail-linked rows use the same operator rule when automatic_repair is non-null: queued or cooldown means OXYGEN owns the next retry, even if a lower-level compatibility verdict still says consent_required; do not ask the mailbox owner to sign in or run connect-oauth. Only rows with automatic_repair: null follow their explicit manual remedy. Only oxygen_native_send.state: connected proves the transport is authorized, and even that does not mean warm-up or the actual-sending campaign ramp is complete. BYOK/imported Google and ordinary Microsoft accounts sign in individually, in reviews of at most 10. In the app: Add inboxes → Connect existing (paste up to 500 exact addresses) or Import a file for a CSV/JSON/JSONL/XLSX export. A dedicated Microsoft sending tenant can instead use one Entra Global Administrator or Privileged Role Administrator authorization per resolved tenant, followed by read-only verification of only the exact addresses you submitted. Those built-in roles are required because tenant mode requests Microsoft Graph application permissions; an ordinary Application Administrator cannot grant them.
oxygen mailboxes import --file ./mailboxes.csv --validate-only --json # local, no network
oxygen mailboxes import --file ./mailboxes.csv
oxygen mailboxes connect-oauth --provider google --vendor oxygen \
--mailboxes [email protected] --json # preview
oxygen mailboxes connect-oauth --provider google --vendor oxygen \
--mailboxes [email protected] --approvedVerify with oxygen mailboxes oauth-health --json: it lists every Google/Microsoft inbox with no usable grant — a token on one mailbox proves nothing about another. The detailed existing-mailbox guide covers the Entra tenant and individual paths, secure file fields, and managed-mailbox fallback. Which origins support warm-up and monitoring at all: mailbox compatibility.
Which IP address connected mailboxes are used from, for sends, reply reads and token refreshes: oxygen egress status. That is the address your IT team allowlists in Microsoft Conditional Access or Google context-aware access; a workspace-only IP is described under dedicated sending IP.
Warm up before you send
A managed order with the warm-up add-on activates itself after provisioning — do not enable it a second time. A non-managed Microsoft mailbox first needs one separate OXYGEN Warm-up Outlook authorization for that exact mailbox, even when an Entra administrator authorized the selected tenant for native sending; there is no tenant-wide warm-up shortcut. A compatible Google import uses its mailbox-scoped app password. A connected Google inbox without that credential uses separate owner sign-in: preview oxygen mailboxes warmup google --mailboxes <address>, approve its fresh setup plan at --max-credits 0, open the returned link as that exact inbox, then poll with --status. The app's Enable Warmup button follows this Google sign-in flow. Authorization starts no warm-up and charges no credits. Then, for BYOK, imported, or opted-out inboxes:
oxygen mailboxes warmup enable --mailboxes [email protected] --json
oxygen mailboxes warmup enable --mailboxes [email protected] \
--approved --plan <plan_hash> --max-credits <n>Both --plan and --max-credits must echo the fresh preview. The JSON field plan_hash supplies the value for the CLI flag --plan. A pending enrollment hold is reserved credit, not a captured charge; its recovery preview reports existing and additional credits separately. In the app: the flame icon on a mailbox row (Enable OXYGEN Warm-up); the dialog quotes 4 weeks and confirms with Approve <n> credits/month, or Start warm-up when warm-up is included in the mailbox connection (--max-credits 0). Track it with oxygen mailboxes warmup status --json.
For read-only activity inspection, use oxygen mailboxes get <email> --json.
The status refresh above persists state and may auto-pause a runaway mailbox.
An enabled warm-up or a missing graph is not proof of sending or zero sending:
see warm-up activity and history troubleshooting.
Campaign ramp-up and warm-up are separate. A new inbox's campaign sending ramps up over actual days with accepted sends: by default 5/day with 0–2 completed UTC sending days, 10/day with 3–5, 20/day with 6–8, then the mailbox's daily campaign limit from 9 completed sending days onward (25/day by default, maximum 50/day). Idle days since import do not advance this ramp. Historical accepted sends count. oxygen mailboxes get <email> --json exposes configured and effective limits under effective_cap, including the ramp's levels (ramp_schedule) and the sending day it reaches the daily limit (full_cap_on_sending_day); oxygen limits show reports technical limits.
Optional standard warm-up starts at 1/day, increases by 1/day and targets 10/day. Dedicated infrastructure retains its more restrictive domain-density profile. Warm-up settings remain configurable; OXYGEN Warm-up does not support the configured reply-rate percentage, which the panel and API report explicitly. Before launching, account for campaign plus known warm-up volume; Oxygen warns when that combined volume exceeds 50/day and cannot measure mail sent outside Oxygen. This combined-volume warning is separate from the 50/day maximum campaign cap per mailbox. These defaults do not guarantee inbox placement.
Click a mailbox address to open its panel — OXYGEN Warm-up / Settings / Campaigns. On Settings, set Daily campaign limit and Ramp-up: Standard (5, 10, then 20 a day), Custom (a starting volume plus an increase every few sending days, climbing to the daily limit), or Off for an inbox that already has a sending history elsewhere. The panel shows the resulting levels and the inbox's current sending day. The same settings from the CLI, or oxygen_mailboxes_set_ramp over MCP:
oxygen mailboxes cap set [email protected] --daily-cap 30
oxygen mailboxes ramp set [email protected] --start-per-day 5 --increase-every-days 2 --step 5
oxygen mailboxes ramp set [email protected] --off # full daily limit from the first sending day
oxygen mailboxes ramp set [email protected] --clear # back to the standard rampA custom ramp's optional --cap holds the inbox at that number for good, even when its daily limit is higher; leave it out to climb to the limit.
Check before launching
Check recipient addresses separately from your sending mailboxes: Email verification explains the free preview, catch-all handling, provider availability and the credit ceiling needed for a live check.
oxygen mailboxes health --json # deliverability reputation per mailbox
oxygen mailboxes oauth-health --json
oxygen billing balance --jsonIf one inbox degrades, pull it from rotation without losing its warm-up: tick its checkbox and hit Pause in the selection bar, or oxygen mailboxes status [email protected] --status paused. Sequences pick from this pool at their Senders stage.