What OpenSequence is
A self-hosted service that runs multi-step outreach sequences for any CRM, behind a small HTTP API.
OpenSequence runs multi-step outreach flows (an email, a wait, a condition, a text, a call task) on behalf of your application. You keep your CRM, your UI and your users; OpenSequence keeps the scheduling, the sending, the listening and the bookkeeping. It is one Docker image, a Postgres you own, a queue you choose, an operator token that creates projects, per-project API keys, and signed outbound webhooks. If you have run a self-hosted Svix, the shape is familiar.
What your application does
| You do | With |
|---|---|
| Register the people who send (a sender: a user with a Google account for mail and calendar, an Allo number, a LinkedIn profile) | senders |
| Register the people who receive (a contact: email, phone, LinkedIn URL, free attributes, SMS consent) | contacts |
| Design flows as JSON (a sequence, versioned, immutable once published) | sequences and versions |
| Start a contact on a sequence as a sender, or stop them | enrollments |
| Let senders do the manual steps (a call, a LinkedIn action) | tasks |
| Read what happened: replies and meetings per sequence, channel and step, and one contact's path | analytics, the journey |
| Branch on what the CRM knows (an open deal, its stage, a company attribute) | crm.* conditions, read live from Attio |
| Get told when something happens | outbound webhooks |
Everything else happens inside the service: it schedules each step, sends the email or the text through the sender's own accounts, pushes calls into the sender's dialer, throttles, listens for replies, bounces, opt-outs, call outcomes and calendar bookings, reads the CRM when a condition asks, exits contacts by rule, and records every decision. Your application never calls a provider, never runs a timer and never reads the service's database.
What it promises
- Never double-send and never lose a contact. Side effects are idempotent or at-most-once; the database is the source of truth; queues carry hints only.
- Dozens of live sequences, thousands of contacts, no workflow engine. External limits (mailbox caps, SMS lines) are the real constraint, so throttling and fairness come first.
- Self-contained. Own database, own queue, own workers, own provider connections. A client only needs HTTP.
- JSON-first. A sequence is one document, so a canvas, a script or an agent all edit the same thing through the same API.
- Debuggable. Every decision stores the facts it read and the branch it took.
- Independently deployable. One image, rollable back without touching any client.
- Generic and open.
project_idon every table, one API key per project, providers behind ports, Apache-2.0.
What it does not do (v1)
No built-in UI (you build yours on the API), no providers beyond Google, Allo and Attio (SMTP and IMAP, Twilio, HubSpot and automated LinkedIn come later behind the same ports), no SMS without consent, no A/B on content, no open and click tracking, no WhatsApp, no holidays in business-day math.
Quickstart
Six calls from docker compose up to a first enrollment.
Concepts
Project, sender, contact, sequence, version, enrollment, run, task, signal, webhook.
How it works
Three loops, the database is truth, what happens to one contact.
API reference
Every endpoint with a playground against your own instance.