Skip to content

The sequences/ folder: one file and what it compiles to

What one sequences/ file holds, what each key compiles to, and the checks that read it.

One sequences/ file is one Sequence: its steps, waits and the replies that end it. SalesBuilder compiles it, and show traces every key.

sequences/cold-email-thread-founder.mdx
---
sending: for-human
steps:
  - { id: first, send: email }
  - { id: second, wait: 3d, send: email }
  - { id: third, wait: 7d, send: email }
  - { id: park, wait: 30d, branch: first }
exitOn: ["Message.created where direction = 'inbound'", Contact.suppressed, Meeting.booked, Deal.created]
---
Three emails from Dana’s own Mailbox, then a 30-day park.
show
$ npx startup-builder show sequences/cold-email-thread-founder.mdx
sending  for-human                                                                 sequences/cold-email-thread-founder.mdx:2
steps                                                                              sequences/cold-email-thread-founder.mdx:3
exitOn   ["Message.created where direction = 'inbound'", Contact.suppressed, Mee…  sequences/cold-email-thread-founder.mdx:8
owner    SalesBuilder
leaseline.app
leaseline.app/
├── plays/
│   ├── cold-email.mdx
│   ├── warm-intros.mdx
│   ├── signup-interviews.mdx
│   ├── lead-reactivation.mdx
│   └── events-and-webinars.mdx
├── audiences/
│   ├── small-property-managers.mdx
│   ├── lapsed-leads.mdx
│   └── renewal-season.mdx
├── sequences/   ← this folder
│   └── cold-email-thread-founder.mdx
├── funnels/
│   └── signup.mdx
├── workflows/
│   └── outbound.mdx
├── agents/
│   ├── sales/prospector.mdx
│   └── marketing/content-lead.mdx
├── systems/
│   └── sequences.mdx
├── domains/
│   └── leaseline.app.mdx
├── offers/
│   ├── pro.mdx
│   └── team.mdx
├── content/
│   └── webinars/60-day-notices.mdx
├── metrics/
│   ├── q4.mdx
│   └── positive-reply-rate.mdx
└── startups.lock

The file

KeyOn the pageCompiles toChecked by
sendingSends aswho the send is from: itself, or a person under their Mandate—
stepsStepsone send or wait per step; each send passes a code-tier CheckS2
exitOnStops onEvent selectors that end the Enrollment (POST /{namespace}/enrollments/{enrollment}/pause)S5

Checks

CheckIt holdsWhat dev prints
S2Every send passes a code-tier Check before it goes.sequences/cold-email-thread-founder.mdx:5 S2 steps.second sends with no code-tier Check. Add guards: [customer-collision].
S5Every on: names a registered Event.plays/lead-reactivation.mdx:4 S5 on: Lead.lapsed is not a registered Event. Did you mean Offer.trialed?

Refusals

CodeFix, then the call that clears it
address-capBundle the extra Tenants into the next message; the cap resets after 24 hours. Then POST /{namespace}/messages/{message}/schedule.
claimCut the line, or cite the Offer term that grants it. Then POST /{namespace}/conversations/{conversation}/answer.
consent-stopAsk once for a yes to the other Startup. Then POST /{namespace}/messages/{message}/schedule.
correction-capHold the correction for next week, or 30 days for the same Contact. Then POST /{namespace}/messages/{message}/schedule.
count-floorSay “2 people on your team”, never a name. Then POST /{namespace}/messages/{message}/schedule.
customer-collisionSend it to their CSM instead: the Contact leaves the List. Then POST /{namespace}/leads/{lead}/assign.
display-consentAsk the reviewer once; the Review shows when they agree. Then POST /{namespace}/messages/{message}/schedule.
domain-authenticatedAdd the 3 DNS records shown; it passes once they resolve, often within an hour. Then POST /{namespace}/domains/{domain}/authenticate.
double-opt-inWait for their yes on the introducer’s thread. Then GET /{namespace}/decisions.
evidenceAsk the publisher for subscriber and open numbers first. Then POST /{namespace}/messages/{message}/schedule.
gift-capPick a gift under the class cap, or send none to that Organization. Then POST /{namespace}/messages/{message}/schedule.
invite-bounceAsk the referrer to share the link instead of typing addresses. Then POST /{namespace}/messages/{message}/schedule.
mailbox-warmWait for the warm-up to finish, 14 days from day 0; warm intros keep running. Then POST /{namespace}/mailboxes/{mailbox}/warm.
movement-limitWait 30 days, or 180 days after 3 unanswered notes; send upward moves only. Then POST /{namespace}/messages/{message}/schedule.
named-scoreGet recorded Consent and the founder's approval, or leave the name out. Then POST /{namespace}/messages/{message}/schedule.
no-consentRecord the Contact’s yes, with where they gave it, before the first send. Then POST /{namespace}/consents.
obligation-voidSend the help Messages; the guarantee stands until then. Then POST /{namespace}/messages/{message}/schedule.
opt-inSend the introducer their opt-in page first. Then POST /{namespace}/messages/{message}/schedule.
owned-by-a-personLeave it to the person who owns it: the draft waits in their queue. Then POST /{namespace}/tasks/{task}/assign.
paying-userWait for the first paying connection; send the private link to one. Then POST /{namespace}/messages/{message}/schedule.
priceGet the discount approved, or quote at the floor. Then POST /{namespace}/approvals/{approval}/approve.
quiet-hoursWait for their window; the narrower of two time zones wins. Then POST /{namespace}/messages/{message}/schedule.
renewal-noticeSend the renewal notice with its amount; the renewal waits 30 days after it. Then POST /{namespace}/messages/{message}/schedule.
rights-holdAsk the host for the grant; the Page waits for it. Then POST /{namespace}/messages/{message}/schedule.
spam-brakeSend to a smaller List, or wait an hour for the rate to fall. Then POST /{namespace}/messages/{message}/broadcast.
supplied-addressAsk where to send it in the thread; ship only to their answer. Then POST /{namespace}/messages/{message}/schedule.
suppressed-contactLeave them out: run the List again, which drops every suppressed Contact. Then POST /{namespace}/collections/query.
visit-in-copyOpen on a public fact about the company instead. Then POST /{namespace}/messages/{message}/schedule.

Calls

sequences/ compiledMode try
You, to your agent

Create the founder thread, enroll one Contact, then pause them, as a dry run.

curl -X POST "https://api.sb/leaseline.app/sequences?mode=try" \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"steps":{}}'

curl -X POST "https://api.sb/leaseline.app/contacts/contact_1/enroll?mode=try" \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"sequence":"sequence_1"}'

curl -X POST "https://api.sb/leaseline.app/enrollments/enrollment_1/pause?mode=try" \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"
import { $ } from 'startup-builder'

await $.Sequence.create({ steps: {} }, { mode: 'try' })   // sequences/cold-email-thread-founder.mdx
await $.Contact.enroll({ contact: 'contact_1', sequence: 'sequence_1' }, { mode: 'try' })
return await $.Enrollment.pause({ enrollment: 'enrollment_1' }, { mode: 'try' })   // a reply pauses it the same way
npx startup-builder do Sequence.create --json '{"steps":{}}' --try
npx startup-builder do Contact.enroll --json '{"contact":"contact_1","sequence":"sequence_1"}' --try
npx startup-builder do Enrollment.pause --json '{"enrollment":"enrollment_1"}' --try
{
  "name": "do",
  "arguments": {
    "code": "await $.Sequence.create({ steps: {} }, { mode: 'try' })   // sequences/cold-email-thread-founder.mdx\nawait $.Contact.enroll({ contact: 'contact_1', sequence: 'sequence_1' }, { mode: 'try' })\nreturn await $.Enrollment.pause({ enrollment: 'enrollment_1' }, { mode: 'try' })   // a reply pauses it the same way",
    "mode": "try"
  }
}
Response200application/json
{
  "enrollment": {
    "$id": "https://api.sb/leaseline.app/enrollments/enrollment_1",
    "$type": "Enrollment",
    "status": "active",
    "step": "Example step"
  },
  "action": {
    "$id": "https://api.sb/leaseline.app/actions/action_1",
    "operation": "Enrollment.pause",
    "status": "done"
  }
}
sample
CallWhat it does
POST /{namespace}/contacts/{contact}/enrollEnroll adds a Contact to a Sequence, which sends its steps until the Contact replies or exits. Emits Contact.enrolled.
POST /{namespace}/enrollments/{enrollment}/pausePause stops one Contact’s run through a Sequence at its current step, without ending it. Emits Enrollment.paused.
POST /{namespace}/leads/{lead}/nurtureNurture takes a Lead that is not ready to buy off its owner’s queue and onto a Sequence, until it raises a hand again. Emits Lead.nurtured.
POST /{namespace}/messages/{message}/scheduleSchedule holds a Message until a set time and sends it then, unless it is canceled first. Emits Message.scheduled.

Compiled, not written: edit the records it reads (compile table; cap), then regenerate. Every step runs from a sentence or a line of code. In your words: the CRM words you know, and where each lives here.

Contents