Skip to content

Written references

Answers a buyer’s reference request within days with a reference an opted-in Customer writes and signs, its credit shown on it.

Channel
Reviews and referrals
Run oneMode try
You, to your agent

Hand our latest reference request to the SE agent and show me what it chose and why. Don’t send.

curl "https://api.sb/leaseline.app/events?where=name%20in%20(%22Action.asked%22%2C%20%22Customer.activated%22%2C%20%22Action.attested%22%2C%20%22Message.received%22%2C%20%22Consent.withdrawn%22%2C%20%22Monitor.checked%22%2C%20%22Deal.won%22)&limit=1" \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"

# Not live yet (gaps #7)
curl -X POST "https://api.sb/leaseline.app/triggers/fire?mode=try" \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"like":"event_1297"}'

# Not live yet (gaps #7)
curl "https://api.sb/leaseline.app/decisions?where=on%20%3D%20%22deal_9%22" \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"

# Not live yet (gaps #7)
curl "https://api.sb/leaseline.app/actions?where=on%20%3D%20%22deal_9%22" \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"
import { $ } from 'startup-builder'

const { events: [last] } = await $.Event.list({ where: 'name in ("Action.asked", "Customer.activated", "Action.attested", "Message.received", "Consent.withdrawn", "Monitor.checked", "Deal.won")', limit: 1 })   // { play } compiled to this Play’s Trigger Events
const { subject } = await $.Trigger.fire({ like: last.$id }, { mode: 'try' })   // the same Event again, in try mode · Not live yet, gaps #7
const { decisions: [decision] } = await $.Decision.list({ where: `on = "${subject}"` })   // what it chose, and why · Not live yet, gaps #7
const { actions } = await $.Action.list({ where: `on = "${subject}"` })   // what it did, with its checks · Not live yet, gaps #7
return { decision, actions }
npx startup-builder do Event.list --json '{"where":"name in (\"Action.asked\", \"Customer.activated\", \"Action.attested\", \"Message.received\", \"Consent.withdrawn\", \"Monitor.checked\", \"Deal.won\")","limit":1}'
npx startup-builder do Trigger.fire --json '{"like":"event_1297"}' --try   # Not live yet (gaps #7)
npx startup-builder do Decision.list --json '{"where":"on = \"deal_9\""}'   # Not live yet (gaps #7)
npx startup-builder do Action.list --json '{"where":"on = \"deal_9\""}'   # Not live yet (gaps #7)
{
  "name": "do",
  "arguments": {
    "code": "const { events: [last] } = await $.Event.list({ where: 'name in (\"Action.asked\", \"Customer.activated\", \"Action.attested\", \"Message.received\", \"Consent.withdrawn\", \"Monitor.checked\", \"Deal.won\")', limit: 1 })   // { play } compiled to this Play’s Trigger Events\nconst { subject } = await $.Trigger.fire({ like: last.$id }, { mode: 'try' })   // the same Event again, in try mode · Not live yet, gaps #7\nconst { decisions: [decision] } = await $.Decision.list({ where: `on = \"${subject}\"` })   // what it chose, and why · Not live yet, gaps #7\nconst { actions } = await $.Action.list({ where: `on = \"${subject}\"` })   // what it did, with its checks · Not live yet, gaps #7\nreturn { decision, actions }",
    "mode": "try"
  }
}
Response200application/json
{
  "decision": {
    "$id": "https://api.sb/leaseline.app/decisions/decision_349",
    "$type": "Decision",
    "choice": "match-and-ask",
    "reason": "Northgate manages 300 units for 3 owners; Fernhill Property Group (310 units, 3 owners) is in the pool with 1 of 2 references left this quarter",
    "stakes": "low",
    "options": [
      "match-and-ask",
      "send-one-on-file",
      "to-the-ae",
      "grow-the-pool",
      "after-the-first-call"
    ],
  …
sample · 4 Not live yetPreview

On PATCH /{namespace}/campaigns/{id}Off PATCH /{namespace}/campaigns/{id}Take this one POST /{namespace}/tasks/{task}/claim

action_2 is the ask to Fernhill’s ops lead, held 2 minutes. action_3 waits for their signed reference, then drafts the delivery into Priya’s queue, because she owns the Deal.

2.1 days median against 7 before · before-after, not proof · n 5 · path → arr

Try another: the requestChoiceReason
Northgate Rentals: “Can we hear from a customer our size?”match-and-askFernhill is the buyer’s size, with capacity left
Lakeside Lofts: a reference request; Kestrel’s signed one is 30 days oldsend-one-on-filea reference on file fits, its Consent current
Alder & Co: “Can I call one of your customers?”to-the-aea live call is the AE’s
Summit Row, 900 units: a reference requestgrow-the-poolno pool Customer is over 400 units

Where it sits: Stranger → Lead → Trialing → Activated → At risk → Churned → Won back · Reference turnaround → New paying Customers → New Customers ↑ → ARR added each week → ARR

Worth’s formula: about +8 Deals won per 100 with a reference in 3 days (Other Startups’ results; no lift of your own yet) × 3 requests a month × $2,000 first order ARR ≈ +$480. Under First signal: At 3 requests a month, 90 days can tell only a 4-day drop or more, so your file starts at holdout: 0 and reads before-after.

sample · api.sb/leaseline.app · 41 Customers at 2026-10-19 · on Action.asked · first ask 11m 20s · 8 keys Not live yet

Start it this week

Terminal
npx startup-builder add play written-references   # 1 · writes plays/written-references.mdx (Not live yet, gaps #5)

# 2 · dry run; below, its 422 on 2026-08-24
curl -X POST "https://api.sb/leaseline.app/campaigns?mode=try" \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"play":"written-references"}'

# 3 · keep it, at You approve each one
curl -X POST https://api.sb/leaseline.app/campaigns \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"play":"written-references"}'

# on
curl -X PATCH https://api.sb/leaseline.app/campaigns/written-references \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"endsAt":null}'

# off: requests come to you; issued credits and delivered references stay
curl -X PATCH https://api.sb/leaseline.app/campaigns/written-references \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"endsAt":"now"}'
422Refusedwritten-references can’t start yet: 1 check fails and 2 warn.
CheckFixThen
use-when fail · Not live yet, gaps #8Invite Customers past their first outcome to the reference pool; it passes at 5.POST /{namespace}/messages/{message}/broadcast
baseline warn · Not live yet, gaps #8n 4: it reads before-after, not proof, until volume allows a held-back half.POST /{namespace}/metrics/query
role-unstaffed warn · Not live yet, gaps #8Staff the AE, or leave it: deliveries for your 6 open Deals go to your queue.POST /{namespace}/roles/{role}/staff
JSON
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "written-references can’t start yet: 1 check fails and 2 warn.",
  "checks": [
    {
      "check": "use-when",
      "status": "fail",
      "observed": "4 requests in 90 days; 0 Customers in the reference pool",
      "doc": "/plays/written-references#check-use-when",
      "fix": "Invite Customers past their first outcome to the reference pool; it passes at 5.",
      "then": "Message.broadcast"
    },
    {
      "check": "baseline",
      "status": "warn",
      "observed": "median 7 days to a reference, n 4 in 90 days",
      "doc": "/plays/written-references#check-baseline",
      "fix": "n 4: it reads before-after, not proof, until volume allows a held-back half.",
      "then": "Metric.query"
    },
    {
      "check": "role-unstaffed",
      "status": "warn",
      "roles": [
        "sales-engineer",
        "sales-lead"
      ],
      "owned": 6,
      "doc": "/plays/written-references#check-role-unstaffed",
      "fix": "Staff the AE, or leave it: deliveries for your 6 open Deals go to your queue.",
      "then": "Role.staff"
    }
  ]
}

It says no, says why, and names the fix.

CheckFix (one call)Your timeWait
use-when · fail (gaps #8): 4 requests in 90 days, 0 in the poolPOST /{namespace}/messages/{message}/broadcast the pool invite to your 14 Customers past their first outcome; it passes at 5 opt-ins10 minthe opt-ins, 6 days here
baseline · warn: median 7 days, n 4POST /{namespace}/metrics/query on reference-turnaround; it fills Before in Your number0 minnone
role-unstaffed · warn: 6 of your open Deals have a person owner, youPOST /{namespace}/roles/{role}/staff, or leave it: every delivery is drafted into the Deal owner’s queue0 minnone

Your number · Before 7 days · Now 2.1 days median to a signed reference · Target 3 days or less by Dec 31 · before-after, not proof · n 5 delivered

Each written reference costs its credit, the lesser of one month’s Price and $200 ($79 for a Team referee), under a $1,000 monthly Limit, plus $0.06 per ask from your Domain (Worker cost). That comes to about $360 a month at 3 requests.

When it starts

WhenTrigger idStarts onWindowHow it gets in
A buyer on a qualified Deal asks for a referencereference-requestedevent on Action.asked where kind = 'reference' and deal.status in ('qualified', 'proposed')match within 1 business hour; 3dthe Deal room’s reference button calls POST /{namespace}/actions/{action}/ask, or forward the email
A Customer reaches its first outcome and 2 paid Invoices or 60 daysreference-eligibleevent on Customer.activated where invoicesPaid >= 2 or subscriptionDays >= 6030d; one pool invitePOST /{namespace}/integrations/connect (Stripe) and your app’s POST /{namespace}/events/capture
An ask has had no answer for 24 business hoursreferee-ask-timeoutstate on Action.asked where ask.status = 'open' and ask.askedAt < now - 24 business hoursa state, read each hournone: it reads the ask’s own status
+ 5 more for submissions, follow-up questions, ended Consent, a thin pool and closed Deals (?lanes=all)
One signed delivery · StartupBuilder-Signature
{
  "$id": "https://api.sb/leaseline.app/events/event_1297",
  "$type": "Event",
  "name": "Action.asked",
  "at": "2026-10-19T15:31:08Z",
  "seq": 1297,
  "data": {
    "deal": "deal_9",
    "contact": "contact_14",
    "kind": "reference",
    "said": "Can we hear from a customer our size?",
    "units": 300,
    "owners": 3
  }
}
Reproduce it in test
npx startup-builder trigger Action.asked --like event_1297   # replays the delivery
npx startup-builder clock advance --by 1d   # then runs the ask’s nudge, which ends when they accept
npx startup-builder listen Action.asked --forward-to http://localhost:3000/hook

Who runs it

SE · your agent (role:sales-engineer, worker_6) holds the Key Result. Every delivery and every call request goes to the Deal’s owner, AE · Priya Shah (person) (role:sales-lead, worker_3, staffed on day 9); before day 9 they came to you (Dana Okafor, person, worker_1). Your number links to Did it work.

OptionRung todayEvidence (passed of n)Moves up atDrops back whenYou can
Match and ask a CustomerIt does it, you can stop it3 of 3met on day 20 (the first 3 asks)any ask fails a Check → You approve each onePOST /{namespace}/actions/{action}/cancel inside the hold
Send one on file · Say when, and grow the pool · After the first callIt does it2 of 2 · 0 · 0—an expired Consent is sent → You approve each onePOST /{namespace}/actions/{action}/redirect
To the AEIt does it1 of 1——POST /{namespace}/tasks/{task}/return
Change the match ruleYou approve each one0 mergednever—POST /{namespace}/changes/{change}/merge · POST /{namespace}/changes/{change}/revert
Never: a word of the reference changed, a credit tied to praise, a priceTo a person, every time1 asked, 1 handed overnever—POST /{namespace}/approvals/{approval}/approve on the AE’s Quote

What it reads · What it may call. It reads the request, the pool’s Consent and capacity, and the referee’s own signed words. It never edits a reference, and the credit is the same whatever the reference says. Its tools are POST /{namespace}/credit-grants/issue, GET /{namespace}/consents/{id}, POST /{namespace}/conversations/{conversation}/escalate, POST /{namespace}/tasks/{task}/assign, POST /{namespace}/conversations/{conversation}/answer, and any other call becomes an Approval under the Role’s Mandate.

The brief (folded): compiled Agent-register Markdown · play:written-references@1 · each line names its record key
You hold the SE Key Result: references delivered in a median of 3 days or less by 2026-12-31. ← worker, metric
On each reference request, choose one option and say why.                        ← triggers, chooses
Match on units and owners within a third of the buyer’s, from Customers with capacity left. ← your file, line 4
Never change a word a referee signed; deliver it whole, with its credit line.    ← copyRules, Disclosure stop
Never write to a Deal a person owns: draft it into their queue.                  ← worker.owns, owned-by-a-person

The slow loop. The weekly Decisions kept a third as the size band, and no Change was merged in the window, so there is no replay or read-back to print.

What it can do next

OptionPicked whenDecided byRunsHands toIf it’s just you
Match and ask a Customer match-and-aska qualified Deal, and a pool Customer within a third of its sizeYour rule (line 4)referee-ask-email → on signing POST /{namespace}/credit-grants/issue → reference-delivery-emailPOST /{namespace}/tasks/{task}/assign → AE · Priya Shah, due 60 min after signing · Take this oneyou, within 60 min
Send one on file send-one-on-filea signed reference under 90 days old fitsAgent’s call, with its reasonGET /{namespace}/consents/{id} → reference-delivery-emailPOST /{namespace}/tasks/{task}/assign → AE · Priya Shah, due 60 min · Take this oneyou
To the AE to-the-aea live call, price or termsAgent’s call, with its reasonPOST /{namespace}/conversations/{conversation}/escalatePOST /{namespace}/tasks/{task}/assign → AE · Priya Shah, due 60 min · Take this oneyou
Say when, and grow the pool grow-the-poolno pool Customer fitsAgent’s call, with its reasonPOST /{namespace}/conversations/{conversation}/answer with an honest date → reference-pool-invite-emailnobodythe same
After the first call after-the-first-callthe Deal is unqualifiedYour rule (the intake)POST /{namespace}/conversations/{conversation}/answer: references follow the first callthe Deal’s owneryou
When they write backFixture replyWhat happensWho answersBy whenCall
InterestedFernhill: “Happy to. Send me the form.”the compose form; they write and sign it, with the credit line shownthe Customer2 business daysPOST /{namespace}/actions/{action}/attest (theirs)
Send me pricingNorthgate: “Thanks. What would 3 owners cost a year?”To the AE: price is hersAE · Priya Shah (person)60 minPOST /{namespace}/conversations/{conversation}/escalate
Not nowa referee: “Busy this month.”the ask closes and the next match is asked; customer-ask-cap frees the CustomerSE · your agentat onceGET /{namespace}/decisions
Wrong persona referee: “Ask our ops lead, Mo.”asks them to bring Mo in; it never writes to an address from their textSE · your agent1 business dayPOST /{namespace}/conversations/{conversation}/answer
Out of officean auto-reply until Oct 28the next match is asked at onceSE · your agentat oncePOST /{namespace}/messages/{message}/schedule
Question it can’t answerNorthgate: “Did Fernhill see fewer late renewals?”To the AE: only the referee’s own words are quotedAE · Priya Shah (person)60 minPOST /{namespace}/conversations/{conversation}/escalate
Stopa referee: “Please take us off the reference list.”out of the pool at once; their references on file stop sendingnobodyat oncePOST /{namespace}/consents/{consent}/withdraw

When it hands to you

Every delivery and call request goes to the Deal’s owner, AE · Priya Shah (person); the first asks came to you to approve. One Brief per Role, then the Approval, as captured (brief, draft and checks are Not live yet, gaps #7).

What lands in each queue · sample
[
  {
    "$id": "https://api.sb/leaseline.app/tasks/task_521",
    "$type": "Task",
    "assignee": "worker_3",
    "due": "2026-10-21T10:40:00Z",
    "on": "deal_9",
    "brief": {
      "who": "Northgate Rentals, open Deal on the $2,400 plan",
      "said": "Can we hear from a customer our size?",
      "chose": "match-and-ask",
      "why": "Fernhill: 310 units, 3 owners, signed Oct 21 09:40",
      "send": "the signed reference whole, with its credit line",
      "never": [
        "a word of the reference changed",
        "a price"
      ]
    }
  },
  {
    "$id": "https://api.sb/leaseline.app/approvals/approval_44",
    "$type": "Approval",
    "verdict": null,
    "deadline": "2026-08-31T12:00:00Z",
    "draft": "Hi Jo, a property manager your size asked to hear from a Leaseline customer…",
    "route": "match-and-ask",
    "checks": [
      {
        "check": "keep-first",
        "status": "pass"
      },
      {
        "check": "customer-ask-cap",
        "status": "pass"
      }
    ]
  }
]

Priya answers with POST /{namespace}/tasks/{task}/claim (Take this one), POST /{namespace}/tasks/{task}/return with a reason, or POST /{namespace}/actions/{action}/redirect, each a one-call window. Once she claims, the agent’s pending Actions on that Deal cancel with claimedByPerson (Not live yet, gaps #7), and every reply goes to her queue. A Task nobody claims by its due time goes up a Role through POST /{namespace}/tasks/{task}/escalate (AE to you), and person-promise fires.

On time: AE · Priya Shah, 5 of 5 claimed within 60 min, median 22 min, n 5, ■□□□ Too early to tell beside Other Startups’ 92 % on time. Your queue: in week 1, 3 approvals; after the promotion, about 1 delivery a week in Priya’s queue.

The fixed line: POST /{namespace}/deals/{deal}/assign sets owner to the receiving person, the agent is never a Deal’s owner, and Meetings land on the owner’s calendar under the owner’s name.

When it won’t send

Check (refuses one send)RefusesFixThen
owned-by-a-person (rule j, gaps #8)a send to a buyer on a Deal a person owns, or to a referee whose Conversation a person claimedLeave it to the person who owns it: the draft waits in their queue.POST /{namespace}/tasks/{task}/assign
keep-first (rule j, gaps #8)a reference ask to a Customer who is at risk, past due or has an unsubscribe pendingLet their CSM reach them first, then ask again once they are healthy.POST /{namespace}/tasks/next
customer-ask-cap (gaps #3)a second open ask to one Customer in a window, from any Playreview-requests holds them until Nov 2.GET /{namespace}/decisions
authorship (the record’s Authorship stop)a reference that overlaps the ask’s prompt by over 40 %Ask the referee to confirm it, or write it in their own words.POST /{namespace}/conversations/{conversation}/answer
claim (hub, on POST /{namespace}/conversations/{conversation}/answer)a delivery line that says more than the referee signedQuote only the referee’s own words.POST /{namespace}/conversations/{conversation}/answer
Stop (pauses the Play)Pauses whenThen
turnaroundthe median passes 5 days, after 10 requeststhe Deal room button hides; requests get an honest date
miss3 requests in a row undelivered at day 7new requests pause; POST /{namespace}/decisions for you
declinedeclines and timeouts pass 50 % of asks, after 20asks pause in that size band; POST /{namespace}/decisions
withdrawal2 references withdrawn in 90 daysasks pause; you review what referees were asked
complainta complaint or opt-out after an ask; 2 in 30 daysthat referee leaves the pool; at 2 the Play pauses
disclosurea delivery renders without its credit lineevery delivery waits until the template is restored
bouncebounces pass 2 % of a day’s sendsPOST /{namespace}/mailboxes/{mailbox}/rest
kill-switchyou press itevery ask stops; credits issued and references delivered stay

The captured refusal, then the Stop that fired as a Campaign.paused reason (Not live yet, gaps #2); the rewrite that sent is the Lakeside Lofts thread in Example.

422RefusedThe delivery to Lakeside Lofts did not send: it says Kestrel cut late renewals by 80 %, which Kestrel never wrote.
CheckFixThen
claim failQuote only the referee’s own words.POST /{namespace}/conversations/{conversation}/answer
owned-by-a-person pass · Not live yet, gaps #8—POST /{namespace}/tasks/{task}/assign
JSON
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "The delivery to Lakeside Lofts did not send: it says Kestrel cut late renewals by 80 %, which Kestrel never wrote.",
  "checks": [
    {
      "check": "claim",
      "status": "fail",
      "doc": "/plays/written-references#check-claim",
      "fix": "Quote only the referee’s own words.",
      "then": "Conversation.answer"
    },
    {
      "check": "owned-by-a-person",
      "status": "pass"
    }
  ]
}

It says no, says why, and names the fix.

The Stops that fired, as Campaign.paused reasons · sample
[
  {
    "reason": {
      "limit": "bounce",
      "observed": "2.6 %",
      "bound": "2 %",
      "window": "1 day"
    },
    "doc": "/plays/written-references#stop-bounce",
    "task": "task_433"
  }
]

Did it work

At 3 requests a month, no held-back half reads within 90 days, and every request gets a reference, so the basis is before-after (rule o): the columns read Now and Before, and nothing prints as Added. Each figure’s call is POST /{namespace}/metrics/query by node, and every node above the leaf is Not live yet (gaps #4).

2.1 days median against 7 before · before-after, not proof · n 5 · path → arr

Chose
match-and-ask
Why
Northgate manages 300 units for 3 owners; Fernhill Property Group (310 units, 3 owners) is in the pool with 1 of 2 references left this quarter
From
match-and-ask · send-one-on-file · to-the-ae · grow-the-pool · after-the-first-call
Expects
a signed reference delivered to deal_9 within 3d
Reopens when
no Action.attested for deal_9 within 3d
By
worker_6
JSON
{
  "$id": "decisions/decision_349",
  "$type": "Decision",
  "choice": "match-and-ask",
  "reason": "Northgate manages 300 units for 3 owners; Fernhill Property Group (310 units, 3 owners) is in the pool with 1 of 2 references left this quarter",
  "stakes": "low",
  "options": [
    "match-and-ask",
    "send-one-on-file",
    "to-the-ae",
    "grow-the-pool",
    "after-the-first-call"
  ],
  "by": "worker_6",
  "on": "deal_9",
  "expected": "a signed reference delivered to deal_9 within 3d",
  "reopensWhen": "no Action.attested for deal_9 within 3d"
}
NodeNow (56 days)Before (the 90 days, per 56)AddedConfidenceBasis
reference-turnaround ↓2.1 days median: 5 of 6 requests delivered, 1 handed to the AE for a call7 days: 2 of 4 undelivered at day 7, counted as 7——before-after, not proof · Other Startups’ results −4.2 days, ■■■□ Likely, n 860
new-paying-customers3 of 5 Deals with a reference won · 2 still deciding1 of 4——before-after
new-arr ↑$5,731, 3 Customers · Booked: credited, not all caused by this Play$1,489— · Worth about +$480 a month—before-after · 2 Deals still deciding
net-new-arr · arrcarried from new-arrcarried——carried

The leaf is the median days from a confirmed request to the delivered reference, with a request undelivered at day 7 counted as 7. Before against after reads one window against the 90 days before it; it is not proof, and Other Startups’ results print beside it.

How it moves it: a signed reference from a Customer the buyer’s size in a median of 2.1 days, where the founder used to chase one by hand for a week.

Guardrails: before against after: Deals won per reference delivered, 3 of 5, and days to close on those Deals, 24 against 31; credits used, $358 of the $1,000 monthly Limit.

The Campaign card · sample
{
  "$id": "https://api.sb/leaseline.app/campaigns/written-references",
  "$type": "Campaign",
  "play": "play:written-references@1",
  "path": [
    "reference-turnaround",
    "new-paying-customers",
    "new-arr",
    "net-new-arr",
    "arr"
  ],
  "experiment": {
    "metric": "reference-turnaround",
    "unit": "days",
    "heldBack": 0,
    "decision": null
  },
  "readout": {
    "value": null,
    "n": 5,
    "maturing": 2,
    "interval": null,
    "readability": "inadmissible",
    "basis": "before-after",
    "pooled": true
  },
  "ledger": {
    "spend": 358,
    "workerCost": 1,
    "hours": 1.4,
    "pipelineArr": 4786,
    "wonArr": 5731,
    "projectedArr": 480,
    "paybackDays": 23
  }
}

Outside benchmark: 62 % of business software buyers ask for a customer reference before signing, and 1 in 4 waits over a week for it (a buyer survey of 1,100 companies, 2026-06-30).

Before it · After it. Before it: review-requests and customer-referrals fill the pool with Customers past their first outcome, and trust-pack answers the security half of the same review. After it: closer-handoff hears the Deals a reference moved, and sso-rung hears the Customers it asked; keep-first holds a referee while they are at risk.

Example

Leaseline ran it from 2026-08-24 to 2026-10-19 (56 days): 6 reference requests on 6 Deals, 5 delivered, 1 handed to the AE for a call; 9 Customers joined the pool. Read every captured thread at ?threads=all; three follow the tables.

What happened, by optionRequestsDeliveredWon (credited, not all caused by this Play)
Match and ask a Customer33, median 2.1 days, $358 in credits2 on the $2,400 plan (+$4,786 ARR)
Send one on file · To the AE · Say when · After the first call2 · 1 · 0 · 02, median 0.4 days · a call held by Priya · — · —1 on Team (+$945 ARR), 2 still deciding
At 2 a month (the Use it when volume)about 4 in 56 daysbefore-after, not proofOther Startups’ results: −4.2 days, ■■■□ Likely, n 860
DayEventWhat happenedYour time
0event_119 Campaign.createdthe three steps; dry run fails use-when: 0 in the pool10 min
0event_122 POST /{namespace}/messages/{message}/broadcastthe pool invite to 14 Customers past their first outcome10 min
6event_241 Consent.created, the fifththe pool reaches 5; use-when passes—
9event_301 Role.staffedAE · Priya Shah (person) takes role:sales-lead; deliveries move to her queue—
11event_342 Action.attestedthe first reference signed and delivered: Juniper Homes for Lakeside Lofts—
33event_590 Campaign.pausedbounce: 2.6 % on one day; the Mailbox rested and resumed5 min
1–56event_131 Approval.created, first of 3you approved 3 asks; weekly reviews, from the POST /{namespace}/tasks/next log45 min · total 1.4 h measured, 1.6 h asked

Leaseline → Fernhill’s ops lead, Oct 19, 15:44 · Hi Jo, a property manager with 300 units for 3 owners asked to hear from a Leaseline customer their size.¹ Would you write a few lines in your own words? Leaseline credits you one month, $200, whatever you write.² *Signed with the Role’s disclosure line.*³

Jo, Oct 21, 09:40 · signed 140 words on the form. Action.attested; the delivery reached Priya’s queue at 09:41 and Northgate at 10:02.

Lakeside Lofts, 2026-09-04 · the delivery claim refused, then the rewrite that sent
- Kestrel cut late renewals by 80 % in their first month with Leaseline.
+ Kestrel’s ops lead wrote: “Renewal notices go out on time now, and our owners stopped asking.”

Alder & Co, 2026-10-02 11:10 · “Can I call one of your customers?” · Leaseline, 11:11 · *Thanks. Priya, your account lead, replies by 12:10 to set up the call.*⁴ The Brief went to Priya (task_468); she booked the call at 11:35.

¹ The buyer’s size, never their name, before they agree. ² The credit is the same whatever the reference says. ³ The fixed signature line, compiled from the Role’s disclosure Setting. ⁴ The routed line, compiled from the Role’s Settings.

Your settings

plays/written-references.mdx
---
holdout: 0        # every request gets a reference; it reads before-after
---
Match on units and owners within a third of the buyer’s. Credit the lesser of one month and $200, up to $1,000 a month.
Put every delivery in the Deal owner’s queue.
Text
$ npx startup-builder show plays/written-references
holdout 0 · size band a third · credit cap $200, $1,000 a month     your file  plays/written-references.mdx:2,4,5 (Ask 2026-08-24)
family demand · worker role:sales-engineer, owns never · chooses 5 (2 rule, 3 read) · sequences reference-pool-invite-email, referee-ask-email, reference-delivery-email · checks owned-by-a-person, keep-first, customer-ask-cap, authorship, claim · stops 8 · placements gmail, outlook, yahoo-mail    catalog  play:written-references@1 (Not live yet, gaps #5)

Every key from the catalog

KeyIdWhat it is
Tacticreference-pool-inviteReference pool invite asks each eligible Customer, after its review and referral asks, to join the reference pool under a scoped reference grant. Starts at You approve each one.
Tacticreference-intakeReference intake turns a buyer’s button press or Message on an open Deal into one confirmed request with questions and a running clock. Starts at Sends nothing.
Tacticreference-matchReference match ranks consenting referees by fit to one request, after rule filters, and never by sentiment. Starts at Sends nothing.
Tacticreferee-askReferee ask asks matched referees one at a time, or two in parallel against a deadline, with the questions verbatim and the credit stated. Starts at You approve each one.
Tacticreference-composeReference compose gives a signed-in referee a form with no generated text, a live preview with the disclosure, and a signature, then issues the credit. Starts at Sends nothing.
Tacticreference-deliverReference deliver renders a signed reference with its disclosure into the Deal room and the Deal Thread, unread by the Startup and unheld for content. Starts at Sends nothing.
Tacticreference-readoutReference readout measures turnaround by interval, pool capacity and topic gaps, and reads win rate by Experiment arm. Starts at Sends nothing.
Tacticsend-gate-checkSend gate check: Checks Suppression, a live reason, the Market, the basis stamp, the Person-month grant, the facts and the labels before any cold Message exists. Starts at Sends nothing.
Triggerreference-requestedReference requested: event on Action.asked, window 3d.
Triggerreference-eligibleReference eligible: event on Customer.activated, window 30d.
Triggerreferee-ask-timeoutReferee ask timeout: state on Action.asked, window 1d.
Triggerreference-submittedReference submitted: event on Action.attested, window 1d.
Triggerreference-follow-upReference follow-up: event on Message.received, window 3d.
Triggerreference-consent-endedReference consent ended: event on Consent.withdrawn, window 1h.
Triggerpool-thinPool thin: threshold on Monitor.checked, window 7d.
Triggerreference-deal-closedReference deal closed: event on Deal.won, window 90d.
Sequencereference-pool-invite-emailReference pool invite email: 2 steps; it ends on Opt-in; Decline; Opt-out or Suppression; 14 days.
Sequencereferee-ask-emailReferee ask email: 3 steps; it ends on Submission; Decline; Release; Accept timeout; Writing window end.
Sequencereference-delivery-emailReference delivery email: 2 steps; it ends on Follow-up question; Deal closed; 14 days.

Compiled, not written: edit the Play record written-references and its Leaseline run, 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.