URL: /revenue/replies-and-routing · Id: `page:/revenue/replies-and-routing`

# Replies and routing: every reply to an owner

> Every reply to every Play goes to one owner by title, with its next step and a deadline.

Replies and routing reads each reply, files it as one of seven kinds and hands it to one owner by title, with a deadline. It costs $0.01 a reply read and routed (sample).

```text title="Ask"
Route every reply to this week’s cold emails to its owner, and answer the ones our SDR agent can. Do not send.
```

```ts title="SDK"
import { $ } from 'startup-builder'

await $.Conversation.assign({ conversation: 'conversation_31', worker: 'worker_3' }, { mode: 'try' })   // Northgate Rentals: “Interested. Can you send times for Tuesday?” → the AE in 40 s
await $.Conversation.escalate({ conversation: 'conversation_34', reason: 'outOfScope' }, { mode: 'try' })   // “Do you sync with an accounting system?” → a person
return await $.Conversation.answer({ conversation: 'conversation_36', body: 'If it does not work in 30 days, we refund you.' }, { mode: 'try' })   // Lakeside Rentals: “Is there a guarantee?”
// 422 · The answer to Lakeside Rentals did not send: it promises money back that no Offer term grants.
// claim: Cut the line, or cite the Offer term that grants it. · then Conversation.answer
```

## What it does
| What you pay for | Price per unit (sample) | The call |
| --- | --- | --- |
| A reply read, filed and routed | $0.01 | <Op verb="Conversation.assign" /> |
| An answer drafted and sent | $0.04 | <Op verb="Conversation.answer" /> |
| A hand-off to a person | $0 | <Op verb="Conversation.escalate" /> |

| When they write back | Fixture reply | What happens | Who answers | By when | Call |
| --- | --- | --- | --- | --- | --- |
| Interested | “Interested. Can you send times for Tuesday?” | books the call; the Handoff Brief goes to the AE with what they said, what it chose and why | AE · Priya Shah (person) | 60 min | <Op verb="Meeting.book" /> |
| Send me pricing | “Send me pricing first.” | answers with the list Price from the Pricing Page and one next step | SDR · your agent | 5 min | <Op verb="Conversation.answer" /> |
| Not now | “Try us again in January.” | the follow-ups pause; a Trigger waits for the date they named | SDR · your agent | at once | <Op verb="Enrollment.pause" /> |
| Wrong person | “Sam, who runs operations, handles this.” | asks them to bring Sam in; it never writes to an address taken from their text | SDR · your agent | 1 business day | <Op verb="Conversation.answer" /> |
| Out of office | an auto-reply until Oct 28 | the next step waits for the return date | nobody | the return date | <Op verb="Message.schedule" /> |
| Question it can’t answer | “Do you sync with an accounting system?” | goes to a person, with the question in the Handoff Brief | AE · Priya Shah, or you | 60 min | <Op verb="Conversation.escalate" /> |
| Stop | “Please stop emailing me.” | nothing else sends, from any Play, on any channel | nobody | at once | <Op verb="Contact.unsubscribe" /> |

Every reply is routed first with <Op verb="Conversation.assign" />, 40 s after it lands. The Handoff Brief rides on the AE’s Task.

## Run it
| Step | Call | What it does here |
| --- | --- | --- |
| <a id="step-1"></a>1 | <Op verb="Conversation.assign" /> | Northgate Rentals: “Interested. Can you send times for Tuesday?” → the AE in 40 s |
| <a id="step-2"></a>2 | <Op verb="Conversation.escalate" /> | “Do you sync with an accounting system?” → a person |
| <a id="step-3"></a>3 | <Op verb="Conversation.answer" /> | Lakeside Rentals: “Is there a guarantee?” |

```json title="422 · sample"
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "The answer to Lakeside Rentals did not send: it promises money back that no Offer term grants.",
  "checks": [
    {
      "check": "claim",
      "status": "fail",
      "observed": "“If it does not work in 30 days, we refund you.”",
      "doc": "/code/refusals#check-claim",
      "fix": "Cut the line, or cite the Offer term that grants it.",
      "then": "Conversation.answer"
    }
  ]
}
```

## Set it up
| Check | On the day-0 Startup | Fix | Your time | Wait | Then |
| --- | --- | --- | --- | --- | --- |
| <a id="check-inbound-source"></a>`inbound-source` | fail | forward replies to your inbound address | 5 min | none | <Op verb="Integration.connect" /> |
| <a id="check-role-unstaffed"></a>`role-unstaffed` | warn | staff the AE, or leave it: Interested replies come to you | 0 min | none | <Op verb="Role.staff" /> |
| <a id="check-approved-pages"></a>`approved-pages` | pass | your pricing Page is live, so Send me pricing answers from it | 0 min | none | <Op verb="Site.publish" /> |

<div className="sbO-divider" role="separator" aria-label="Reference" data-divider="reference">Reference</div>

## The records
```json title="The Conversation, routed · sample"
{
  "conversation": {
    "$id": "https://api.sb/leaseline.app/conversations/conversation_31",
    "$type": "Conversation",
    "status": "open",
    "respondBy": "2026-10-19T16:41:00Z",
    "firstAnsweredAt": null
  }
}
```

```json title="The Task on the AE’s queue, with the Handoff Brief · sample"
{
  "task": {
    "$id": "https://api.sb/leaseline.app/tasks/task_118",
    "$type": "Task",
    "assignee": "worker_3",
    "due": "2026-10-19T16:41:00Z",
    "on": "conversation_31",
    "brief": {
      "who": "Lee Park, Northgate Rentals",
      "said": "Interested. Can you send times for Tuesday?",
      "kind": "interested",
      "next": "book the call"
    }
  }
}
```

## Calls
| Call | What it does | What else happens | Event |
| --- | --- | --- | --- |
| <Op verb="Conversation.assign" /> | Assign routes a Conversation to the Worker holding the right Role, by topic, Customer tier and language. | — | [`Conversation.assigned`](#event-conversation-assigned) |
| <Op verb="Conversation.escalate" /> | Escalate hands a Conversation and its summary to the Worker in the Role above, a Human only where one holds it. | A refund over a Limit is an Approval, not an escalation. | [`Conversation.escalated`](#event-conversation-escalated) |
| <Op verb="Conversation.answer" /> | Answer replies in a Conversation through the Channel it arrived on and closes the reply Task it opened. | Runs the reply through every Guard before it leaves. | [`Conversation.answered`](#event-conversation-answered) |
| <Op verb="Meeting.book" /> | Book schedules a Meeting with a Contact at a time both calendars hold free. | — | [`Meeting.booked`](#event-meeting-booked) |
| <Op verb="Enrollment.pause" /> | Pause stops one Contact’s run through a Sequence at its current step, without ending it. | — | [`Enrollment.paused`](#event-enrollment-paused) |
| <Op verb="Contact.unsubscribe" /> | Unsubscribe stops commercial Messages to a Contact in one click, for one topic or all, honored at once. | Writes a Suppression when no topic is named. | [`Contact.unsubscribed`](#event-contact-unsubscribed) |

## Events
<a id="event-conversation-assigned"></a>

```json title="Conversation.assigned · StartupBuilder-Signature"
{
  "$id": "https://api.sb/leaseline.app/events/event_1",
  "$type": "Event",
  "name": "Conversation.assigned",
  "at": "2026-10-22T12:00:00Z",
  "seq": 1,
  "data": {
    "conversation": {
      "$id": "https://api.sb/leaseline.app/conversations/conversation_1",
      "$type": "Conversation",
      "subject": "Example subject",
      "answeredAt": "2026-10-22T12:00:00Z"
    }
  }
}
```

<a id="event-conversation-escalated"></a>

```json title="Conversation.escalated · StartupBuilder-Signature"
{
  "$id": "https://api.sb/leaseline.app/events/event_1",
  "$type": "Event",
  "name": "Conversation.escalated",
  "at": "2026-10-22T12:00:00Z",
  "seq": 1,
  "data": {
    "conversation": {
      "$id": "https://api.sb/leaseline.app/conversations/conversation_1",
      "$type": "Conversation",
      "subject": "Example subject",
      "answeredAt": "2026-10-22T12:00:00Z"
    }
  }
}
```

<a id="event-conversation-answered"></a>

```json title="Conversation.answered · StartupBuilder-Signature"
{
  "$id": "https://api.sb/leaseline.app/events/event_1",
  "$type": "Event",
  "name": "Conversation.answered",
  "at": "2026-10-22T12:00:00Z",
  "seq": 1,
  "data": {
    "conversation": {
      "$id": "https://api.sb/leaseline.app/conversations/conversation_1",
      "$type": "Conversation",
      "subject": "Example subject",
      "answeredAt": "2026-10-22T12:00:00Z"
    }
  }
}
```

<a id="event-meeting-booked"></a>

```json title="Meeting.booked · StartupBuilder-Signature"
{
  "$id": "https://api.sb/leaseline.app/events/event_1",
  "$type": "Event",
  "name": "Meeting.booked",
  "at": "2026-10-22T12:00:00Z",
  "seq": 1,
  "data": {
    "meeting": {
      "$id": "https://api.sb/leaseline.app/meetings/meeting_1",
      "$type": "Meeting",
      "at": "2026-10-22T12:00:00Z"
    }
  }
}
```

<a id="event-enrollment-paused"></a>

```json title="Enrollment.paused · StartupBuilder-Signature"
{
  "$id": "https://api.sb/leaseline.app/events/event_1",
  "$type": "Event",
  "name": "Enrollment.paused",
  "at": "2026-10-22T12:00:00Z",
  "seq": 1,
  "data": {
    "enrollment": {
      "$id": "https://api.sb/leaseline.app/enrollments/enrollment_1",
      "$type": "Enrollment",
      "status": "active",
      "step": "Example step"
    }
  }
}
```

<a id="event-contact-unsubscribed"></a>

```json title="Contact.unsubscribed · StartupBuilder-Signature"
{
  "$id": "https://api.sb/leaseline.app/events/event_1",
  "$type": "Event",
  "name": "Contact.unsubscribed",
  "at": "2026-10-22T12:00:00Z",
  "seq": 1,
  "data": {
    "contact": {
      "$id": "https://api.sb/leaseline.app/contacts/contact_1",
      "$type": "Contact",
      "email": "dana@leaseline.app",
      "phone": "Example phone"
    }
  }
}
```

## Refuses when
| Check | Refuses | Fix | Then |
| --- | --- | --- | --- |
| [`claim`](/code/refusals#check-claim) | a term with no accepted terms Version, or money back that no Action keeps | Cut the line, or cite the Offer term that grants it. | <Op verb="Conversation.answer" /> |
| [`owned-by-a-person`](/code/refusals#check-owned-by-a-person) <NotLiveYet gap="play-dry-run-codes" /> | a send to a Contact whose Lead, open Deal or Conversation a person owns | Leave it to the person who owns it: the draft waits in their queue. | <Op verb="Task.assign" /> |
| [`suppressed-contact`](/code/refusals#check-suppressed-contact) | a send or Sequence step to a Contact on a Suppression, from any Play | Leave them out: run the List again, which drops every suppressed Contact. | <Op verb="Collection.query" /> |

```json title="422 · sample"
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "The answer to Lakeside Rentals did not send: it promises money back that no Offer term grants.",
  "checks": [
    {
      "check": "claim",
      "status": "fail",
      "observed": "“If it does not work in 30 days, we refund you.”",
      "doc": "/code/refusals#check-claim",
      "fix": "Cut the line, or cite the Offer term that grants it.",
      "then": "Conversation.answer"
    }
  ]
}
```


```json title="422 · sample"
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "Step two to Lakeside Rentals’ owner did not send: they asked us to stop on Oct 12.",
  "checks": [
    {
      "check": "suppressed-contact",
      "status": "fail",
      "observed": "Suppression suppression_6, unsubscribed 2026-10-12",
      "doc": "/code/refusals#check-suppressed-contact",
      "fix": "Leave them out: run the List again, which drops every suppressed Contact.",
      "then": "Collection.query"
    }
  ]
}
```


```json title="422 · sample"
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "Pinecrest Homes’ second visitor was not enrolled: no Consent on record for sales email.",
  "checks": [
    {
      "check": "suppressed-contact",
      "status": "pass"
    },
    {
      "check": "no-consent",
      "status": "fail",
      "observed": "no Consent for purpose sales-email",
      "doc": "/code/refusals#check-no-consent",
      "fix": "Record the Contact’s yes, with where they gave it, before the first send.",
      "then": "Consent.create"
    }
  ]
}
```

## Pauses when
| Stop | Pauses when | Fix | Then |
| --- | --- | --- | --- |
| [`unanswered-positive`](/code/refusals#stop-unanswered-positive) | a reply asking to meet that waits 60 minutes for a person | Answer the reply, then approve the resume. | <Op verb="Approval.approve" /> |

```json title="Campaign.paused · unanswered-positive · Not live yet, gaps #2 · sample"
{
  "$id": "https://api.sb/leaseline.app/events/event_951",
  "$type": "Event",
  "name": "Campaign.paused",
  "at": "2026-10-19T16:45:00Z",
  "data": {
    "campaign": {
      "$id": "https://api.sb/leaseline.app/campaigns/cold-email",
      "$type": "Campaign"
    },
    "reason": {
      "limit": "unanswered-positive",
      "observed": "64m",
      "bound": "60m",
      "window": "60m"
    },
    "task": {
      "$id": "https://api.sb/leaseline.app/tasks/task_88",
      "$type": "Task"
    }
  }
}
```

## Plays that use it
| Play | What it does | Its Metric |
| --- | --- | --- |
| [Instant response](/plays/instant-response) | Answers every form and email within 5 minutes from your own pages, books the call, starts the trial or hands it to the right person. | `inbound-meeting-rate` |
| [Cold email](/plays/cold-email) | Writes first to people at companies that showed two fresh public reasons to talk, three short emails at most, and answers every reply by kind. | `positive-reply-rate` |
| [Warm intros](/plays/warm-intros) | Finds who already knows each company you want, and that person asks them first, from their own account, before any introduction. | `intro-acceptance-rate` |
| [Proof-of-work outreach](/plays/proof-of-work-outreach) | Sends each Prospect one finished piece of your product’s work, made from their own public data, in a plain email that asks for nothing. | `proof-reply-rate` |
| [LinkedIn outbound](/plays/linkedin-outbound) | Picks each day’s People on LinkedIn, drafts the connection note and the Messages, and queues them in your send tray; you press every send. | `linkedin-reply-rate` |
| [Outbound calling](/plays/outbound-calling) | A disclosed voice agent calls back anyone who asks within 60 seconds and answers your number; a person dials every cold call. | `callback-meeting-rate` |
| [Gifting](/plays/gifting) | Sends one gift the Person picks after two relevant touches at a live moment, with you approving each, and counts the Meetings it adds. | `gift-meetings-per-100` |
| [Lead reactivation](/plays/lead-reactivation) | Writes once to each old Lead nobody works, only when something new answers what they asked, from their last contact at the Startup. | `reactivated-pipeline` |
| [Lead nurture](/plays/lead-nurture) | Follows up each unbought Lead with notes keyed to what they did, most in month one, until they buy, reply or go quiet 90 days. | `nurture-conversion` |
| [Account visits](/plays/account-visits) | Finds the fitting companies behind visits to your own buying pages and writes to the right person there, from facts, never from the visit. | `visit-reply-lift` |
| [Product signals](/plays/product-signals) | Finds teams getting value on a free account and writes to the right person, citing only their own usage, after you approve the first send. | `pql-deal-rate` |
| [Buying committee](/plays/buying-committee) | Writes to 3 or more roles at each named company, one a week, and hands each engaged company to your AE within a day. | `committee-deal-lift` |
| [Waitlist interviews](/plays/signup-interviews) | Interviews each Waitlist signup with your disclosed agent, admits by fit under a published cap, and sends a result built on their company. | `interview-activation-rate` |

Cost only: it moves no Metric itself, and what it costs counts against each Play that uses it.

## Hub guides it deepens
| On startupbuilder.dev | Id | What it holds |
| --- | --- | --- |
| [Conversation](https://startupbuilder.dev/business/nouns/conversation) | `noun:conversation` | the record, its fields and every call on it |
| [Inbound sales](https://startupbuilder.dev/workflows/processes/inbound-sales) | `process:inbound-sales` | the Process, its steps and its Roles |
| [AE](https://startupbuilder.dev/agents/sales/sales-lead) | `role:sales-lead` | the Role contract the seat fills |

## Example
| Leaseline, when | What happened | Cost (sample) |
| --- | --- | --- |
| 2026-10-19 15:41 | Northgate Rentals writes “Interested. Can you send times for Tuesday?” | — |
| 15:41:40 | filed as Interested and routed to the AE, with the Handoff Brief | $0.01 of Worker cost |
| 16:12 | the AE books Tuesday 14:00 Central, inside the 60-minute window | $0 |