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.
- Step
- Make the sale
- Channel
- Reviews and referrals
- Kind
- Conversion
- Summary
- startupbuilder.dev
Be our SE: when a buyer on an open Deal asks for a reference, ask a Customer their size to write and sign one, credit them a month, and put it in our AE’s queue for that Deal. Show me what’s missing; don’t send.
# Not live yet (gaps #2)
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"}'import { $ } from 'startup-builder'
return await $.Campaign.create({ play: 'written-references' }, { mode: 'try' }) // dry run on the day-0 Startup, 2026-08-24 · Not live yet, gaps #2
npx startup-builder do Campaign.create --json '{"play":"written-references"}' --try # Not live yet (gaps #2){
"name": "do",
"arguments": {
"code": "return await $.Campaign.create({ play: 'written-references' }, { mode: 'try' }) // dry run on the day-0 Startup, 2026-08-24 · Not live yet, gaps #2",
"mode": "try"
}
}application/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"
},
…
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"
}
}application/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 yetPreviewOn 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,
| Try another: the request | Choice | Reason |
|---|---|---|
| Northgate Rentals: “Can we hear from a customer our size?” | match-and-ask | Fernhill is the buyer’s size, with capacity left |
| Lakeside Lofts: a reference request; Kestrel’s signed one is 30 days old | send-one-on-file | a reference on file fits, its Consent current |
| Alder & Co: “Can I call one of your customers?” | to-the-ae | a live call is the AE’s |
| Summit Row, 900 units: a reference request | grow-the-pool | no pool Customer is over 400 units |
- 30 min week 1, then 10 a week
- Your time
- Day 3: first reference delivered
- First signal
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: and reads before-after.
sample · api.sb/
Start it this week
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"}' | Check | Fix | Then |
|---|---|---|
use-when fail · Not live yet, gaps #8 | Invite Customers past their first outcome to the reference pool; it passes at 5. | POST /{namespace}/messages/{message}/broadcast |
baseline warn · Not live yet, gaps #8 | n 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 #8 | Staff 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.
| Check | Fix (one call) | Your time | Wait |
|---|---|---|---|
use-when · fail (gaps #8): 4 requests in 90 days, 0 in the pool | POST /{namespace}/messages/{message}/broadcast the pool invite to your 14 Customers past their first outcome; it passes at 5 opt-ins | 10 min | the opt-ins, 6 days here |
baseline · warn: median 7 days, n 4 | POST /{namespace}/metrics/query on reference-turnaround; it fills Before in Your number | 0 min | none |
role-unstaffed · warn: 6 of your open Deals have a person owner, you | POST /{namespace}/roles/{role}/staff, or leave it: every delivery is drafted into the Deal owner’s queue | 0 min | none |
Your number · Before 7 days · Now 2.1 days median to a signed reference · Target 3 days or less by Dec 31 · before-after,
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
| When | Trigger id | Starts on | Window | How it gets in |
|---|---|---|---|---|
| A buyer on a qualified Deal asks for a reference | reference-requested | event on Action.asked where kind = 'reference' and deal.status in ('qualified', 'proposed') | match within 1 business hour; 3d | the 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 days | reference-eligible | event on Customer.activated where invoicesPaid >= 2 or subscriptionDays >= 60 | 30d; one pool invite | POST /{namespace}/integrations/connect (Stripe) and your app’s POST /{namespace}/events/capture |
| An ask has had no answer for 24 business hours | referee-ask-timeout | state on Action.asked where ask.status = 'open' and ask.askedAt < now - 24 business hours | a state, read each hour | none: it reads the ask’s own status |
+ 5 more for submissions, follow-up questions, ended Consent, a thin pool and closed Deals (?lanes=) |
{
"$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
}
}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:, worker_6) holds the Key Result. Every delivery and every call request goes to the Deal’s owner, AE · Priya Shah (person) (role:, 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.
| Option | Rung today | Evidence (passed of n) | Moves up at | Drops back when | You can |
|---|---|---|---|---|---|
| Match and ask a Customer | It does it, you can stop it | 3 of 3 | met on day 20 (the first 3 asks) | any ask fails a Check → You approve each one | POST /{namespace}/actions/{action}/cancel inside the hold |
| Send one on file · Say when, and grow the pool · After the first call | It does it | 2 of 2 · 0 · 0 | — | an expired Consent is sent → You approve each one | POST /{namespace}/actions/{action}/redirect |
| To the AE | It does it | 1 of 1 | — | — | POST /{namespace}/tasks/{task}/return |
| Change the match rule | You approve each one | 0 merged | never | — | POST /{namespace}/changes/{change}/merge · POST /{namespace}/changes/{change}/revert |
| Never: a word of the reference changed, a credit tied to praise, a price | To a person, every time | 1 asked, 1 handed over | never | — | 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.
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
| Option | Picked when | Decided by | Runs | Hands to | If it’s just you |
|---|---|---|---|---|---|
Match and ask a Customer match-and-ask | a qualified Deal, and a pool Customer within a third of its size | Your rule (line 4) | referee-ask-email → on signing POST /{namespace}/credit-grants/issue → reference-delivery-email | POST /{namespace}/tasks/{task}/assign → AE · Priya Shah, due 60 min after signing · Take this one | you, within 60 min |
Send one on file send-one-on-file | a signed reference under 90 days old fits | Agent’s call, with its reason | GET /{namespace}/consents/{id} → reference-delivery-email | POST /{namespace}/tasks/{task}/assign → AE · Priya Shah, due 60 min · Take this one | you |
To the AE to-the-ae | a live call, price or terms | Agent’s call, with its reason | POST /{namespace}/conversations/{conversation}/escalate | POST /{namespace}/tasks/{task}/assign → AE · Priya Shah, due 60 min · Take this one | you |
Say when, and grow the pool grow-the-pool | no pool Customer fits | Agent’s call, with its reason | POST /{namespace}/conversations/{conversation}/answer with an honest date → reference-pool-invite-email | nobody | the same |
After the first call after-the-first-call | the Deal is unqualified | Your rule (the intake) | POST /{namespace}/conversations/{conversation}/answer: references follow the first call | the Deal’s owner | you |
| When they write back | Fixture reply | What happens | Who answers | By when | Call |
|---|---|---|---|---|---|
| Interested | Fernhill: “Happy to. Send me the form.” | the compose form; they write and sign it, with the credit line shown | the Customer | 2 business days | POST /{namespace}/actions/{action}/attest (theirs) |
| Send me pricing | Northgate: “Thanks. What would 3 owners cost a year?” | To the AE: price is hers | AE · Priya Shah (person) | 60 min | POST /{namespace}/conversations/{conversation}/escalate |
| Not now | a referee: “Busy this month.” | the ask closes and the next match is asked; customer-ask-cap frees the Customer | SE · your agent | at once | GET /{namespace}/decisions |
| Wrong person | a referee: “Ask our ops lead, Mo.” | asks them to bring Mo in; it never writes to an address from their text | SE · your agent | 1 business day | POST /{namespace}/conversations/{conversation}/answer |
| Out of office | an auto-reply until Oct 28 | the next match is asked at once | SE · your agent | at once | POST /{namespace}/messages/{message}/schedule |
| Question it can’t answer | Northgate: “Did Fernhill see fewer late renewals?” | To the AE: only the referee’s own words are quoted | AE · Priya Shah (person) | 60 min | POST /{namespace}/conversations/{conversation}/escalate |
| Stop | a referee: “Please take us off the reference list.” | out of the pool at once; their references on file stop sending | nobody | at once | POST /{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).
[
{
"$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) | Refuses | Fix | Then |
|---|---|---|---|
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 claimed | Leave 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 pending | Let 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 Play | review-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 signed | Quote only the referee’s own words. | POST /{namespace}/conversations/{conversation}/answer |
| Stop (pauses the Play) | Pauses when | Then |
|---|---|---|
turnaround | the median passes 5 days, after 10 requests | the Deal room button hides; requests get an honest date |
miss | 3 requests in a row undelivered at day 7 | new requests pause; POST /{namespace}/decisions for you |
decline | declines and timeouts pass 50 % of asks, after 20 | asks pause in that size band; POST /{namespace}/decisions |
withdrawal | 2 references withdrawn in 90 days | asks pause; you review what referees were asked |
complaint | a complaint or opt-out after an ask; 2 in 30 days | that referee leaves the pool; at 2 the Play pauses |
disclosure | a delivery renders without its credit line | every delivery waits until the template is restored |
bounce | bounces pass 2 % of a day’s sends | POST /{namespace}/mailboxes/{mailbox}/rest |
kill-switch | you press it | every 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.
| Check | Fix | Then |
|---|---|---|
claim fail | Quote 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.
[
{
"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,
- 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"
}| Node | Now (56 days) | Before (the 90 days, per 56) | Added | Confidence | Basis |
|---|---|---|---|---|---|
reference-turnaround ↓ | 2.1 days median: 5 of 6 requests delivered, 1 handed to the AE for a call | 7 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-customers | 3 of 5 Deals with a reference won · 2 still deciding | 1 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 · arr | carried from new-arr | carried | — | — | 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.
{
"$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=; three follow the tables.
| What happened, by option | Requests | Delivered | Won (credited, not all caused by this Play) |
|---|---|---|---|
| Match and ask a Customer | 3 | 3, median 2.1 days, $358 in credits | 2 on the $2,400 plan (+$4,786 ARR) |
| Send one on file · To the AE · Say when · After the first call | 2 · 1 · 0 · 0 | 2, 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 days | before-after, not proof | Other Startups’ results: −4.2 days, ■■■□ Likely, n 860 |
| Day | Event | What happened | Your time |
|---|---|---|---|
| 0 | event_119 Campaign.created | the three steps; dry run fails use-when: 0 in the pool | 10 min |
| 0 | event_122 POST /{namespace}/messages/{message}/broadcast | the pool invite to 14 Customers past their first outcome | 10 min |
| 6 | event_241 Consent.created, the fifth | the pool reaches 5; use-when passes | — |
| 9 | event_301 Role.staffed | AE · Priya Shah (person) takes role:; deliveries move to her queue | — |
| 11 | event_342 Action.attested | the first reference signed and delivered: Juniper Homes for Lakeside Lofts | — |
| 33 | event_590 Campaign.paused | bounce: 2.6 % on one day; the Mailbox rested and resumed | 5 min |
| 1–56 | event_131 Approval.created, first of 3 | you approved 3 asks; weekly reviews, from the POST /{namespace}/tasks/next log | 45 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.
- 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
---
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.$ 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
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.