URL: /code/files/sequences · Id: `page:/code/files/sequences`

# 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](https://startupbuilder.dev/business/nouns/sequence): its steps, waits and the replies that end it. SalesBuilder compiles it, and `show` traces every key.

```mdx title="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.
```

```text title="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
```

```text title="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
| Key | On the page | Compiles to | Checked by |
| --- | --- | --- | --- |
| `sending` | Sends as | who the send is from: itself, or a person under their Mandate | — |
| `steps` | Steps | one send or wait per step; each send passes a code-tier Check | [S2](/code/checks#s2) |
| `exitOn` | Stops on | Event selectors that end the Enrollment (<Op verb="Enrollment.pause" />) | [S5](/code/checks#s5) |

## Checks
| Check | It holds | What dev prints |
| --- | --- | --- |
| [S2](/code/checks#s2) | Every 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].` |
| [S5](/code/checks#s5) | Every `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
| Code | Fix, then the call that clears it |
| --- | --- |
| [`address-cap`](/code/refusals#check-address-cap) | Bundle the extra Tenants into the next message; the cap resets after 24 hours. Then <Op verb="Message.schedule" />. |
| [`claim`](/code/refusals#check-claim) | Cut the line, or cite the Offer term that grants it. Then <Op verb="Conversation.answer" />. |
| [`consent-stop`](/code/refusals#check-consent-stop) | Ask once for a yes to the other Startup. Then <Op verb="Message.schedule" />. |
| [`correction-cap`](/code/refusals#check-correction-cap) | Hold the correction for next week, or 30 days for the same Contact. Then <Op verb="Message.schedule" />. |
| [`count-floor`](/code/refusals#check-count-floor) | Say “2 people on your team”, never a name. Then <Op verb="Message.schedule" />. |
| [`customer-collision`](/code/refusals#check-customer-collision) | Send it to their CSM instead: the Contact leaves the List. Then <Op verb="Lead.assign" />. |
| [`display-consent`](/code/refusals#check-display-consent) | Ask the reviewer once; the Review shows when they agree. Then <Op verb="Message.schedule" />. |
| [`domain-authenticated`](/code/refusals#check-domain-authenticated) | Add the 3 DNS records shown; it passes once they resolve, often within an hour. Then <Op verb="Domain.authenticate" />. |
| [`double-opt-in`](/code/refusals#check-double-opt-in) | Wait for their yes on the introducer’s thread. Then <Op verb="Decision.list" />. |
| [`evidence`](/code/refusals#check-evidence) | Ask the publisher for subscriber and open numbers first. Then <Op verb="Message.schedule" />. |
| [`gift-cap`](/code/refusals#check-gift-cap) | Pick a gift under the class cap, or send none to that Organization. Then <Op verb="Message.schedule" />. |
| [`invite-bounce`](/code/refusals#check-invite-bounce) | Ask the referrer to share the link instead of typing addresses. Then <Op verb="Message.schedule" />. |
| [`mailbox-warm`](/code/refusals#check-mailbox-warm) | Wait for the warm-up to finish, 14 days from day 0; warm intros keep running. Then <Op verb="Mailbox.warm" />. |
| [`movement-limit`](/code/refusals#check-movement-limit) | Wait 30 days, or 180 days after 3 unanswered notes; send upward moves only. Then <Op verb="Message.schedule" />. |
| [`named-score`](/code/refusals#check-named-score) | Get recorded Consent and the founder's approval, or leave the name out. Then <Op verb="Message.schedule" />. |
| [`no-consent`](/code/refusals#check-no-consent) | Record the Contact’s yes, with where they gave it, before the first send. Then <Op verb="Consent.create" />. |
| [`obligation-void`](/code/refusals#check-obligation-void) | Send the help Messages; the guarantee stands until then. Then <Op verb="Message.schedule" />. |
| [`opt-in`](/code/refusals#check-opt-in) | Send the introducer their opt-in page first. Then <Op verb="Message.schedule" />. |
| [`owned-by-a-person`](/code/refusals#check-owned-by-a-person) | Leave it to the person who owns it: the draft waits in their queue. Then <Op verb="Task.assign" />. |
| [`paying-user`](/code/refusals#check-paying-user) | Wait for the first paying connection; send the private link to one. Then <Op verb="Message.schedule" />. |
| [`price`](/code/refusals#check-price) | Get the discount approved, or quote at the floor. Then <Op verb="Approval.approve" />. |
| [`quiet-hours`](/code/refusals#check-quiet-hours) | Wait for their window; the narrower of two time zones wins. Then <Op verb="Message.schedule" />. |
| [`renewal-notice`](/code/refusals#check-renewal-notice) | Send the renewal notice with its amount; the renewal waits 30 days after it. Then <Op verb="Message.schedule" />. |
| [`rights-hold`](/code/refusals#check-rights-hold) | Ask the host for the grant; the Page waits for it. Then <Op verb="Message.schedule" />. |
| [`spam-brake`](/code/refusals#check-spam-brake) | Send to a smaller List, or wait an hour for the rate to fall. Then <Op verb="Message.broadcast" />. |
| [`supplied-address`](/code/refusals#check-supplied-address) | Ask where to send it in the thread; ship only to their answer. Then <Op verb="Message.schedule" />. |
| [`suppressed-contact`](/code/refusals#check-suppressed-contact) | Leave them out: run the List again, which drops every suppressed Contact. Then <Op verb="Collection.query" />. |
| [`visit-in-copy`](/code/refusals#check-visit-in-copy) | Open on a public fact about the company instead. Then <Op verb="Message.schedule" />. |

## Calls

```text title="sequences/ compiled · Ask"
Create the founder thread, enroll one Contact, then pause them, as a dry run.
```

```ts title="sequences/ compiled · SDK"
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
```

```json title="sequences/ compiled · Response · sample"
{
  "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"
  }
}
```

| Call | What it does |
| --- | --- |
| <a id="contact-enroll"></a><Op verb="Contact.enroll" /> | Enroll adds a Contact to a Sequence, which sends its steps until the Contact replies or exits. Emits [`Contact.enrolled`](/code/events#contact-enrolled). |
| <a id="enrollment-pause"></a><Op verb="Enrollment.pause" /> | Pause stops one Contact’s run through a Sequence at its current step, without ending it. Emits [`Enrollment.paused`](/code/events#enrollment-paused). |
| <a id="lead-nurture"></a><Op verb="Lead.nurture" /> | Nurture 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`](/code/events#lead-nurtured). |
| <a id="message-schedule"></a><Op verb="Message.schedule" /> | Schedule holds a Message until a set time and sends it then, unless it is canceled first. Emits [`Message.scheduled`](/code/events#message-scheduled). |