Contact .enroll
Start one person on a Sequence that sends from your inbox and stops on reply.
- Action class
send- Approval
- Sends on its own
- Emits
Contact.enrolled- Sites
- Gmail, LinkedIn, Outlook
- Price
- Free
POST https: //api.sb/ {your-domain}/ contacts/ enroll
Starts one person on a Sequence that sends from your Mailbox and stops the moment they reply. The hub’s definition of Contact.enroll.
Inputs
| Name | Type | Default | Meaning |
|---|---|---|---|
contact | Contact | Required | The Contact to enroll. |
sequence | Sequence | Required | The Sequence to run. |
Outputs
| Field | Type | What null means |
|---|---|---|
contact | Contact | Never null. |
enrollment | Enrollment | Never null. In try mode, the run as it would start; nothing is stored. |
enrollment.status | string | Never null: active from the first step until the run ends. |
enrollment.step | string | Never null: the step the Contact is on, starting at the first. |
enrollment.nextAt | datetime | Null while paused or once exited: no step is waiting. |
enrollment.exitReason | string | Null while the run is active. |
firstStep | Message | Null in send and do. In try mode, the first step rendered for this Contact, so you read it before anything sends. |
Effects
- Action class
send: an approval rule onsendcan make it wait for your OK- Modes
try: Renders the first step for this Contact and when each later step would fire; nothing sends and no Enrollment is stored.send: Returns the active Enrollment at once; each step sends at its own time.do: Returns the active Enrollment at once; each step sends at its own time.
- Idempotency
Only with a key: the same
Idempotency-Keyand input return the first Action, and the same key with other input returns409. A Contact already active on the Sequence is never enrolled twice: the repeat returns the open Enrollment.- Saved or shared
The Enrollment is saved on the Contact. A reply, a bounce, an unsubscribe or a purchase ends it and records its
exitReason.- Emits
Contact.enrolledwith{ contact,enrollment, sequence, nextAt } - Performed by
- Price
Free on your own account: the platform charges nothing for the call.
- Standing approval
It goes out on its own, inside the Limits of your standing approval: a
Mandategranted withMandate.authorize. One approval rule makes it wait for your OK.
On each Venue
| Site | Fields |
|---|---|
| Gmail | from, to, subject, body, purpose |
body Formats 3 | |
| Outlook | to, subject, body, purpose |
Gmail
Through Gmail.
| Our field | Gmail’s field |
|---|---|
Message.from | raw: (Your address, or a send-as alias you set up in Gmail) |
Message.to | raw: |
Message.subject | raw: (A reply keeps the thread’s subject, so Gmail threads it) |
Message.body | raw: |
Message.purpose | raw: (A commercial purpose adds the one-click unsubscribe headers Gmail shows as a link) |
- Cold sends. 30 a day per inbox after 14 days of warm-up, held by your standing approval; a Sequence spreads the rest over the next days.
- Replies. Gmail pushes each new message within seconds; the platform renews the mailbox watch daily, inside the 7 days Gmail allows.
Through LinkedIn.
| Our field | LinkedIn’s field |
|---|---|
Message.body | invitation note or message (Typed into LinkedIn’s own screens by the browser agent) |
- Follow-ups. One first message and one follow-up per person; any reply stops the rest.
- Replies. Read from your LinkedIn inbox every 30 minutes on weekdays, since LinkedIn sends no webhook for member messages.
Outlook
Through Outlook.
| Our field | Outlook’s field |
|---|---|
Message.to | message.toRecipients |
Message.subject | message.subject |
Message.body | message.body (contentType html or text) |
Message.purpose | message.internetMessageHeaders (A commercial purpose adds the one-click unsubscribe headers) |
- Cold sends. 30 a day per inbox after 14 days of warm-up, held by your standing approval; a Sequence spreads the rest over the next days.
What try does
| Account | What try does |
|---|---|
| Gmail | Renders the exact email, headers included, and returns it with the time it would send; nothing reaches Gmail and no draft is saved. |
| Posts render as LinkedIn will show them and nothing is sent; requests and messages return each person, the note and the day it goes, and no browser session opens. | |
| Outlook | Renders the exact email or invite and returns it with the time it would go; nothing reaches Outlook and no draft or event is saved. |
Refuses when
| Check | Error | Fix | Then call |
|---|---|---|---|
| A send or Sequence step whose purpose the Contact has given no Consent for | no-consent | Record the Contact’s yes, with where they gave it, before the first send. | Consent.create |
| A send or Sequence step to a Contact on a Suppression, from any Play | suppressed-contact | Leave them out: run the List again, which drops every suppressed Contact. | Collection.query |
| A new-lead send to a Contact with an active Subscription | customer-collision | Talk to them yourself instead: the Contact leaves the List. | Lead.assign |
| A first cold email from a Mailbox that has not finished warming | mailbox-warm | Wait for the warm-up to finish, 14 days from day 0; warm intros keep running. | Mailbox.warm |
Every call through an account can also meet the shared account refusals: grant-missing, needs-reauth, account-not-connected, over-mandate, quota-reached, venue-rejected.
The no-consent payload
{
"type": "https://startupbuilder.dev/errors/no-consent" ,
"title": "No yes on record",
"status": 422,
"detail": "A send or Sequence step whose purpose the Contact has given no Consent for.",
"fix": "Record the Contact’s yes, with where they gave it, before the first send." ,
"next": {
"verb": "Consent.create",
"input": {}
},
"instance": "https://api.sb/leaseline.app/actions/action_1"
}When it waits
Returns in one response; nothing waits.
Example
Put Maya Chen at Cedar Hollow Rentals on the personal first touch, the
first of today’s 12.To retry, send the same Idempotency-Key: the retry returns the first answer for $0. A new key reads again.
Test values
A sk_test_ key answers these the same way every time, at $0 (every test value).
| Test value | Always returns | What it is for |
|---|---|---|
contact_test_active | {"status": | Enrolls and renders the first step without sending, so your agent can read the run it starts. |
contact_test_suppressed | Refuses with suppressed-contact | The address sits on a Suppression, so the enroll refuses before any step is planned. |
contact_test_no_consent | Refuses with no-consent | The Contact gave no Consent for the Sequence’s purpose, so the enroll refuses. |
maxCost: | Refuses with max-cost | Any priced call with a maxCost of 0.0001 is refused before it spends: the price is above the cap. |
rate-limited.test | Refuses with rate-limited | Any call naming this hostname answers 429 with Retry-After, so your retry logic runs. |
sources-busy.test | Refuses with sources-busy | Any call naming this hostname answers 503 as if every route were busy, and nothing is spent. |
Used by
- Agent tasks: Personal first touch
- Jobs: Reach out
- Integrations: Gmail · LinkedIn · Outlook
Related
None.