First sequence
Build a multichannel sequence, load leads without sending anything, then launch it behind a preview and a spend cap.
A sequence is one journey per lead, mixing email, LinkedIn, WhatsApp, rep call tasks, and CRM tasks. Building it and enrolling leads spends nothing and sends nothing; only starting it dispatches.
Attach a sender first
Sidebar → Sequencer → Accounts (/sequencer/accounts). Tabs: Senders, LinkedIn, Email, WhatsApp, Phone numbers.
- Email tab → Add inboxes
- LinkedIn tab → Connect LinkedIn account
- Senders tab → New sender — one person's inboxes plus their LinkedIn and WhatsApp accounts as one sending identity.
oxygen senders list --json and oxygen mailboxes list --json show what is connected. oxygen senders connect --country DE mints a shareable hosted-auth link, valid 10 minutes; --country is the account owner's normal LinkedIn login country, not your target market.
Build it in the app
Sidebar → Sequencer (/sequencer) → New sequence opens /sequencer/sequences/<id>: an empty draft with four stages — Leads → Sequence → Senders → Launch. The Next: … button at the bottom moves through them.
Leads. Import leads offers Upload a file (CSV, JSON, JSONL, or XLSX), Copy from a table, or HubSpot list. Imported rows are deduped and enrolled automatically — there is no separate enroll button. On the toast N leads imported but not enrolled — no LinkedIn URL, open Identifiers beside the import button, map the LinkedIn column, and re-import.
Sequence. The canvas opens on Sequence start. Click the + between steps ("Add a step") and pick from the catalogue: Send email, Reply email, Send invite, Send message, Send InMail, WhatsApp message, Call task, Create CRM task, Wait, Wait for signal, Branch on signal or data. Copy fields interpolate {{column}} from the lead's row; use {{column|fallback}} where a value may be missing.
Senders. Add senders chooses who this sequence sends from.
Launch. Sending schedule (timezone, days, From/To) and Sending settings: Emails per day / Sends per day across every sender, blank for no limit, reset at UTC midnight. Profile views and other reads don't count.
Build it from the CLI
oxygen sequences create --name "Q3 founders" --slug q3-founders \
--steps-file ./steps.json --table <table-id> --jsonsteps.json holds { "steps": [...] }, each step with its own id:
{
"steps": [
{ "id": "s1", "channel": "email", "kind": "email_send",
"subject_template": "{{company}} + inbound",
"body_template": "Hi {{first_name|there}} — quick question." },
{ "id": "s2", "kind": "wait", "days": 3 },
{ "id": "s3", "channel": "email", "kind": "email_reply",
"body_template": "Bumping this once, {{first_name}}." }
]
}Enrolling is inert — no provider call, no credits, no message:
oxygen sequences enroll q3-founders --from-table --json--from-table takes up to 500 not-yet-enrolled rows per run; re-run while from_table.has_more is true. For leads outside the bound table, pass --leads-file with { "leads": [{ "row_values": { "email": "…" }, "lead_name": "…" }] }. Attach senders with oxygen sequences update q3-founders --senders <ids>.
Set the do-not-contact list before launching
Sidebar → Sequencer → Do not contact (/sequencer/do-not-contact). Add entries takes pasted people, emails, phones, or company identities; Sync HubSpot pulls in a saved list. Enrollment always enforces this list.
oxygen suppressions add --lead <linkedin-provider-id> --reason manual
oxygen suppressions import --file ./dnc.txt --reason manual
oxygen suppressions addresses --jsonimport takes a mixed file of emails, bare domains, and LinkedIn URLs, up to 5000 entries. --reason is required when the file contains any domain — a domain block silences everyone at that company.
Launch
No flags means preview only: it activates nothing and sends nothing.
oxygen sequences start q3-founders --jsonRead launch_readiness.blockers, copy_preview (exact rendered samples per lead), and the estimated credits.
--dry-run activates the sequence in simulated mode: every step advances, with no provider call, CRM write, or credit.
oxygen sequences start q3-founders --dry-run --jsonThis command sends real messages to real people.
oxygen sequences start q3-founders --approved --max-live-sends 200 --max-credits 5000 --json--max-live-sends is a positive-integer ceiling on real external actions, required for any sequence with email, WhatsApp, or CRM-task steps — those cost 0 Oxygen credits, so --max-credits cannot bound them. Omitting it fails with sequence_send_cap_required. --max-credits bounds the LinkedIn track and is optional — omit it for an unbounded run. Every per-action LinkedIn charge is 0 credits today (pricing reference).
In the app the same gate is Review & start on the Launch stage: a dialog listing pending enrollments, estimated credits, rendered copy samples, and any blockers. Start live confirms, and stays disabled while a blocker is listed.
It is hidden until the draft has at least one step and — for LinkedIn or WhatsApp — at least one sender; the CLI reports these as sequence_no_steps and sequence_no_senders.
Watch it and pause it
A reply stops that lead's enrollment automatically, on every channel — nothing to configure. To stop the replier's colleagues too, create the sequence with --stop-on-reply-scope company_domain (freemail domains are never company-matched).
| What you want | Where |
|---|---|
| Funnel: enrolled, sent, replied, reply rate | oxygen sequences stats q3-founders --json, or Sequencer → Analytics (/sequencer/analytics) |
| Every send, failure, deferral, open, click, reply, bounce | oxygen sequences events q3-founders --limit 50 --json |
| Per-lead state and the last error | oxygen sequences enrollments q3-founders --json |
| The replies themselves | Unibox (/unibox) |
oxygen sequences pause q3-founders stops new dispatches; oxygen sequences resume q3-founders restarts them, and enrollments pick up where they left off. In the app: Pause while active, Resume live while paused.