Paid pilot
Runs your product on the buyer’s own data for a fee, against pass marks no higher than they already saw, signed before it starts.
- Step
- Make the sale
- Channel
- Offers and Deals
- Kind
- Conversion
- Summary
- startupbuilder.dev
Be our SE: when a buyer over 300 units wants to test Leaseline on their own leases, run the free check on 50 of them first, then propose a $400 pilot whose pass marks are no higher than what they saw. Priya owns the Deal and sends every message. A miss ends it with the refund. 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":"paid-pilot"}'import { $ } from 'startup-builder'
return await $.Campaign.create({ play: 'paid-pilot' }, { mode: 'try' }) // dry run on the day-0 Startup, 2026-07-06 · Not live yet, gaps #2
npx startup-builder do Campaign.create --json '{"play":"paid-pilot"}' --try # Not live yet (gaps #2){
"name": "do",
"arguments": {
"code": "return await $.Campaign.create({ play: 'paid-pilot' }, { mode: 'try' }) // dry run on the day-0 Startup, 2026-07-06 · Not live yet, gaps #2",
"mode": "try"
}
}application/json{
"type": "https: //startupbuilder.dev/ errors/ refused",
"title": "Refused",
"status": 422,
"detail": "paid-pilot can’t start yet: 1 check fails and 1 warns.",
"checks": [
{
"check": "use-when",
"status": "pass",
"observed": "3 open Deals a month at or over the $2, 400 median; 2 Deals won on a buyer’s own data",
"doc": "/plays/ paid-pilot#check-use-when",
"fix": "Nothing to do: it counts Deals at or over your median won value.",
"then": "Metric.query"
},
…
Hand our latest pilot ask 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(%22Quote.requested%22%2C%20%22Conversation.labeled%22%2C%20%22File.uploaded%22%2C%20%22Invoice.collected%22%2C%20%22Evaluator.scored%22%2C%20%22Agreement.signed%22%2C%20%22Conversation.answered%22%2C%20%22Contact.enriched%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_1394"}'
# Not live yet (gaps #7)
curl "https://api.sb/leaseline.app/decisions?where=on%20%3D%20%22deal_21%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_21%22" \
-H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"import { $ } from 'startup-builder'
const { events: [last] } = await $.Event.list({ where: 'name in ("Quote.requested", "Conversation.labeled", "File.uploaded", "Invoice.collected", "Evaluator.scored", "Agreement.signed", "Conversation.answered", "Contact.enriched")', 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 (\"Quote.requested\", \"Conversation.labeled\", \"File.uploaded\", \"Invoice.collected\", \"Evaluator.scored\", \"Agreement.signed\", \"Conversation.answered\", \"Contact.enriched\")","limit":1}'
npx startup-builder do Trigger.fire --json '{"like":"event_1394"}' --try # Not live yet (gaps #7)
npx startup-builder do Decision.list --json '{"where":"on = \"deal_21\""}' # Not live yet (gaps #7)
npx startup-builder do Action.list --json '{"where":"on = \"deal_21\""}' # Not live yet (gaps #7){
"name": "do",
"arguments": {
"code": "const { events: [last] } = await $.Event.list({ where: 'name in (\"Quote.requested\", \"Conversation.labeled\", \"File.uploaded\", \"Invoice.collected\", \"Evaluator.scored\", \"Agreement.signed\", \"Conversation.answered\", \"Contact.enriched\")', 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_574",
"$type": "Decision",
"choice": "propose-a-pilot",
"reason": "the free check on 50 of Larkfield’s leases read renewal dates right on 48 (96 %) on Oct 12; $2, 400 a year is at your median won Deal; Owen named the CFO, Hana Ito, as budget holder; 3 pilots are open, under the cap of 5",
"stakes": "medium",
"options": [
"check-their-sample",
"propose-a-pilot",
"check-only",
"start-the-term",
"end-on-the-miss",
"ask-the-budget-holder"
…
sample · 4 Not live yetPreviewOn PATCH /{namespace}/campaigns/{id}Off PATCH /{namespace}/campaigns/{id}Take this one POST /{namespace}/tasks/{task}/claim
action_3 is refused by design: Priya owns the Deal, so the proposal does not send as the agent. action_4 drafts it into her queue with the pass sheet and the Quote attached; she sends it from the Deal Thread.
75 per 100 against 40 before · before-after,
| Try another: the Deal | Choice | Reason |
|---|---|---|
| Larkfield Communities (640 units): “Can we test it on our own leases before we sign?” | propose-a-pilot | the free check is back at 96 %; at the median; budget holder named |
| Northgate Rentals (260 units): “Can it read our scanned leases?” | check-their-sample | a fit doubt: the free check on 50 of their leases first |
| Kestrel Rentals (40 units): “Can we pilot it?” | check-only | under the median won value: the free check answers it |
| Greystone Residential pilot, pass date Oct 9: 2 of 3 lines over their marks | end-on-the-miss | one deciding line under its mark: it ends that day, with the refund |
- 1 h 30 min week 1, then 1 h a pilot
- Your time
- Day 6: first pilot fee paid
- First signal
Where it sits: Stranger → Lead → Trialing → Activated → At risk → Churned → Won back · Technical win rate → New paying Customers → New Customers ↑ → ARR added each week → ARR
Worth’s formula: about +15 technical wins per 100 pilots (Other Startups’ results; no lift of your own yet) × 2 pilots a month × 0.60 wins to a first term × $2,393 first order ARR ≈ +$431; the $400 fees are one-time and left out. Under First signal: At 2 pilots a month, 90 days can tell nothing on its own, so your file reads before-after; the pass-line Variants pool across Other Startups.
sample · api.sb/
Start it this week
npx startup-builder add play paid-pilot # 1 · writes plays/paid-pilot.mdx (Not live yet, gaps #5)
# 2 · dry run; below, its 422 on 2026-07-06
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":"paid-pilot"}'
# 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":"paid-pilot"}'
# on
curl -X PATCH https://api.sb/leaseline.app/campaigns/paid-pilot \
-H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"endsAt":null}'
# off: no new pilot is offered; running pilots finish on their signed terms
curl -X PATCH https://api.sb/leaseline.app/campaigns/paid-pilot \
-H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"endsAt":"now"}' | Check | Fix | Then |
|---|---|---|
use-when pass · Not live yet, gaps #8 | Nothing to do: it counts Deals at or over your median won value. | POST /{namespace}/metrics/query |
baseline warn · Not live yet, gaps #8 | n 5: it reads before-after, not proof; the pass-line Variants pool across Other Startups. | POST /{namespace}/metrics/query |
price fail · Not live yet, gaps #1 | Publish the $400 pilot Offer and the plan’s price floor; no rescue discount. | POST /{namespace}/offers/{offer}/publish |
owned-by-a-person pass · Not live yet, gaps #8 | Nothing to do: every Deal-thread Message drafts into the owner’s queue. | POST /{namespace}/tasks/{task}/assign |
role-unstaffed warn · Not live yet, gaps #8 | Staff the AE, or leave it: every Deal and pilot comes to you. | POST /{namespace}/roles/{role}/staff |
JSON
{
"type": "https://startupbuilder.dev/errors/refused",
"title": "Refused",
"status": 422,
"detail": "paid-pilot can’t start yet: 1 check fails and 1 warns.",
"checks": [
{
"check": "use-when",
"status": "pass",
"observed": "3 open Deals a month at or over the $2,400 median; 2 Deals won on a buyer’s own data",
"doc": "/plays/paid-pilot#check-use-when",
"fix": "Nothing to do: it counts Deals at or over your median won value.",
"then": "Metric.query"
},
{
"check": "baseline",
"status": "warn",
"observed": "2 technical wins of 5 free proofs in 90 days",
"doc": "/plays/paid-pilot#check-baseline",
"fix": "n 5: it reads before-after, not proof; the pass-line Variants pool across Other Startups.",
"then": "Metric.query"
},
{
"check": "price",
"status": "fail",
"observed": "no pilot Offer and no price floor on the $2,400 plan",
"doc": "/plays/paid-pilot#check-price",
"fix": "Publish the $400 pilot Offer and the plan’s price floor; no rescue discount.",
"then": "Offer.publish"
},
{
"check": "owned-by-a-person",
"status": "pass",
"observed": "3 open Deals, each owned by a person",
"doc": "/plays/paid-pilot#check-owned-by-a-person",
"fix": "Nothing to do: every Deal-thread Message drafts into the owner’s queue.",
"then": "Task.assign"
},
{
"check": "role-unstaffed",
"status": "warn",
"roles": [
"sales-engineer",
"sales-lead"
],
"owned": 3,
"doc": "/plays/paid-pilot#check-role-unstaffed",
"fix": "Staff the AE, or leave it: every Deal and pilot comes to you.",
"then": "Role.staff"
}
]
}It says no, says why, and names the fix.
| Check | Fix (one call) | Your time | Wait |
|---|---|---|---|
use-when · baseline · pass: 3 Deals a month at the median; warn: 2 of 5 (gaps #8) | POST /{namespace}/metrics/query on technical-win-rate, which fills Before in Your number | 1 min | none |
price · fail (gaps #1) | POST /{namespace}/offers/{offer}/publish the pilot at $400 with the plan’s floor | 15 min | none |
owned-by-a-person · pass: 3 Deals owned by a person | nothing; every Deal-thread send drafts into the owner’s queue | 0 min | none |
role-unstaffed · warn (gaps #8): 3 open Deals have a person owner, you | POST /{namespace}/roles/{role}/staff, or leave it: pilots and Deal-thread drafts come to you | 0 min | none |
Your number · Before 40 per 100 · Now 75 per 100 technical wins · Target 70 by Dec 31 · before-after,
Each pilot spends model and compute under 10 % of its $400 fee, about $30, and the free check about $3 on 50 items (Worker cost). The pilot Tenant is deleted 30 days after a miss or a no-decision. That comes to about $60 a month at 2 pilots, paid for by their fees.
When it starts
| When | Trigger id | Starts on | Window | How it gets in |
|---|---|---|---|---|
| Someone on an open Deal asks to test it on their own data | pilot-ask | event on Quote.requested where deal.status = 'open' and kind = 'pilot' | a written answer within 1 business hour | a reply in the Deal Thread, labeled by PATCH /{namespace}/conversations/{id} |
| Their sample lands in the pilot Tenant | sample-uploaded | event on File.uploaded where tenant.kind = 'pilot' | free check back within 1 business day | POST /{namespace}/files in the pilot Tenant |
| The signed pass date arrives | pass-date-reached | at on Agreement.signed where agreement.passDate | the verdict the same day | the date on the signed pass sheet (POST /{namespace}/agreements/{agreement}/sign) |
+ 5 more: a fit doubt, the fee paid, a line out of reach at half the sample, a silent champion, and a buying-committee change (?lanes=) |
{
"$id": "https://api.sb/leaseline.app/events/event_1394" ,
"$type": "Event",
"name": "Quote.requested",
"at": "2026-10-19T15:48:20Z" ,
"seq": 1394,
"data": {
"deal": {
"$id": "https://api.sb/leaseline.app/deals/deal_21" ,
"company": "Larkfield Communities",
"units": 640,
"owner": "worker_3"
},
"contact": "contact_14",
"text": "Can we test it on our own leases before we sign?" ,
"check": {
"run": "runs/run_33" ,
"renewalDates": {
"right": 48,
"of": 50
}
}
}
}npx startup-builder trigger Quote.requested --like event_1394 # replays the delivery in test
npx startup-builder clock advance --by 10d # checks the proposal for a signature (reopensWhen)
npx startup-builder listen Agreement.signed --forward-to http://localhost:3000/hook Who runs it
SE · your agent (role:, worker_8) holds the Key Result: it runs the free check, drafts the pass sheet, runs the pilot and scores it. AE · Priya Shah (person) (role:, worker_3) owns every Deal and sends every Deal-thread Message from its draft; you (Dana Okafor, person, worker_1) write to the budget holder. Your number links to Did it work.
| Option | Rung today | Evidence (passed of n) | Moves up at | Drops back when | You can |
|---|---|---|---|---|---|
| Run the free check on their data · Stop at the free check | It drafts it for the AE | 7 of 7 checks back within 1 business day | never past the AE: she owns the Deal | — | POST /{namespace}/tasks/{task}/claim · POST /{namespace}/tasks/{task}/return |
| Propose a paid pilot · Start the first term | It drafts it; you approve the pass sheet | 5 proposals, 4 signed · 3 Quotes | Messages after 10 pilots with no number corrected by a buyer (4 so far); pass sheets never | a buyer corrects a number → You see each one first | POST /{namespace}/approvals/{approval}/approve · POST /{namespace}/approvals/{approval}/refuse |
| End it on the miss | It does it | 1 of 1, same day | — | — | none: a miss ends it, with no extension and no rescue discount |
| Ask the budget holder | You write it | 1 of 1 | never | — | POST /{namespace}/tasks/{task}/claim |
| Change a pass-line rule | You approve each one | 1 merged of 1 | never | — | POST /{namespace}/changes/{change}/merge · POST /{namespace}/changes/{change}/revert |
| Never: a mark over the free check, a second re-run, a pilot fee shown as recurring revenue | Refused, every time | 1 proposed, 1 refused | never | — | none: the Check holds it |
What it reads · What it may call. It reads the buyer’s own items, the pinned Evaluator and the signed pass sheet. A readout Page view never appears in a Message, and a pilot company never appears as a Customer or a reference until it pays a first term and says yes in writing. Its tools are POST /{namespace}/actions/{action}/evaluate, POST /{namespace}/tasks/{task}/assign, POST /{namespace}/quotes, POST /{namespace}/agreements, POST /{namespace}/content/draft, POST /{namespace}/quotes/{quote}/send, POST /{namespace}/invoices/{invoice}/refund, POST /{namespace}/agreements/{agreement}/terminate, and any other call becomes an Approval under the Role’s Mandate.
You hold the SE Key Result: 70 technical wins per 100 pilots by 2026-12-31. ← worker, metric
On each pilot ask, sample, score or date, choose one option and say why. ← triggers, chooses
Every number comes from an Evaluator run on this buyer’s items, with n and the date. ← copyRules 1
No pass mark above what the free check showed them. ← copyRules 2, Mark cap
A miss readout states the miss in its first sentence. ← copyRules 3
The AE owns the Deal: draft every Deal-thread Message into her queue. ← worker.owns, owned-by-a-person The slow loop, as a Change. decision_412 (2026-09-07, weekly) read 2 pilots whose pass sheets had 4 deciding lines, 1 passed, and 2 with 2 lines, both passed. change_25 capped pass sheets at 3 deciding lines (your file, line 7), and Dana merged it with POST /{namespace}/changes/{change}/merge. Replayed on past pilots, POST /{namespace}/changes/{change}/review passed 3 of 4; read back at +30d, 2 of 2 completed, n 2, ■□□□ Too early to tell (Example, day 98).
Bring your own agent (folded) starts at It does it, you can stop it when it matches or beats the seated agent on the eval suite, and at You approve each one when it does not; POST /{namespace}/roles/{role}/staff seats it.
npx startup-builder eval --scenario paid-pilot-9 --agent "claude -p" --seat sales-engineer # seated: 0 numbers corrected, 0 Checks failed sent, 7 % of fee spent · yours: 1 mark over the check → You approve each one What it can do next
| Option | Picked when | Decided by | Runs | Hands to | If it’s just you |
|---|---|---|---|---|---|
Run the free check on their data check-their-sample | a pilot ask or a fit doubt, with 50 of their items | Your rule (line 6) | POST /{namespace}/actions/{action}/evaluate on 50 random items → POST /{namespace}/tasks/{task}/assign the summary to the Deal owner | AE · Priya Shah sends it, due 1 business day · Take this one | you send it |
Propose a paid pilot propose-a-pilot | the check is back; at or over the median; budget holder named; under 5 open | Your rule (line 5) | pilot-proposal → POST /{namespace}/quotes (with the $400 credit) → POST /{namespace}/agreements (the pass sheet) | AE · Priya Shah sends it; you approve the pass sheet · Take this one | you |
Stop at the free check check-only | under the median, or the check already answers the doubt | Agent’s call, with its reason | POST /{namespace}/content/draft of the check’s numbers → POST /{namespace}/tasks/{task}/assign | AE · Priya Shah · Take this one | you |
Start the first term start-the-term | every deciding line at or over its mark on the pass date | Your rule (the pass sheet) | pilot-decision → POST /{namespace}/quotes/{quote}/send for the first term, with the fee credited | AE · Priya Shah, due 1 business day · Take this one | you |
End it on the miss end-on-the-miss | a line under its mark on the pass date, or out of reach at half the sample | Your rule (the Miss stop) | pilot-miss-notice → POST /{namespace}/invoices/{invoice}/refund per your Setting → POST /{namespace}/agreements/{agreement}/terminate; deletion in 30 days | nobody; nothing follows for 90 days | the same |
Ask the budget holder ask-the-budget-holder | the champion is silent 14 days or leaves | Agent’s call, with its reason | pilot-founder-notes → POST /{namespace}/tasks/{task}/assign; the run pauses | you write to the budget holder · Take this one | you |
| When they write back | Fixture reply | What happens | Who answers | By when | Call |
|---|---|---|---|---|---|
| Interested | “Looks fair. Send the Agreement.” | the click-to-sign Agreement with the pass sheet and the $400 fee | AE · Priya Shah (person) | 1 business day | POST /{namespace}/agreements/{agreement}/sign (theirs) |
| Send me pricing | “What would the first year cost after the pilot?” | the first-term Quote already on the pass sheet: $2,400, less the $400 credit | AE · Priya Shah (person) | 1 business day | POST /{namespace}/quotes/{quote}/send |
| Not now | “Let’s revisit after our audit in January.” | the Deal stays open with January noted; no pilot is held for them | AE · Priya Shah (person) | at once | PATCH /{namespace}/deals/{id} |
| Wrong person | “Our IT lead has to approve any data upload.” | asks them to bring the IT lead into the thread; it never writes to an address from their text | AE · Priya Shah (person) | 1 business day | POST /{namespace}/conversations/{conversation}/answer |
| Out of office | an auto-reply until Oct 28 | the 10-day sample clock waits for the return date | nobody | the return date | POST /{namespace}/messages/{message}/schedule |
| Question it can’t answer | “Can you guarantee 99 % on our older scans?” | only the free check’s number can be a mark; the question goes to the SE draft and you | AE · Priya Shah, with you | 1 business day | POST /{namespace}/conversations/{conversation}/escalate |
| Stop | “We’re going another way; delete our data.” | the pilot ends, and the sample and Tenant are deleted with one action, not 30 days | nobody | at once | DELETE /{namespace}/files/{id} |
When it hands to you
Every Deal-thread Message drafts into AE · Priya Shah (person)’s queue, because she owns the Deal; budget-holder notes come to you. One Brief per Role, as captured, then the Approval (brief, draft and checks are Not live yet, gaps #7).
[
{
"$id": "https://api.sb/leaseline.app/tasks/task_477" ,
"$type": "Task",
"assignee": "worker_3",
"due": "2026-10-20T15:48:00Z" ,
"on": "deal_21",
"brief": {
"who": "Owen Hale, Larkfield Communities (640 units)" ,
"said": "Can we test it on our own leases before we sign?" ,
"chose": "propose-a-pilot",
"why": "the free check read 48 of 50 renewal dates right; at the median" ,
"attached": [
"quotes/quote_58" ,
"agreements/agreement_19"
],
"never": [
"a mark over 96 %",
"a rescue discount"
]
}
},
{
"$id": "https://api.sb/leaseline.app/tasks/task_429" ,
"$type": "Task",
"assignee": "worker_1",
"due": "2026-09-25T17:00:00Z" ,
"on": "deal_17",
"brief": {
"who": "Greystone Residential: champion silent 14 days, day 12 of the pilot" ,
"chose": "ask-the-budget-holder",
"why": "a silent champion pauses the run",
"to": "the budget holder, Marcus Webb, VP of Finance"
}
},
{
"$id": "https://api.sb/leaseline.app/approvals/approval_93" ,
"$type": "Approval",
"verdict": null,
"deadline": "2026-10-20T17:00:00Z" ,
"draft": "Pass sheet, Larkfield: renewal dates read right ≥ 96 %; notice dates computed right ≥ 95 %; owner statements match ≥ 94 %…" ,
"route": "propose-a-pilot",
"checks": [
{
"check": "mark-cap",
"status": "pass"
},
{
"check": "price",
"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, and you with POST /{namespace}/approvals/{approval}/approve or POST /{namespace}/approvals/{approval}/refuse, each a one-call window. 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 her name. 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, 11 of 11 drafts claimed within 1 business day, median 2 h 40 min, n 11; you, 4 of 4 pass sheets approved by their deadline, n 4, ■□□□ Too early to tell beside Other Startups’ 94 % on time. Your queue: counted by kind: in week 1, 2 free-check summaries; during a pilot, about 1 pass sheet, 1 progress draft every 5 business days, and the readout.
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; Not live yet, gaps #8) | every Deal-thread send as the agent, because a person owns each open Deal | Leave it to the person who owns it: the draft waits in their queue. | POST /{namespace}/tasks/{task}/assign |
mark-cap (the record’s Mark cap) | a pass mark above the free check’s observed value, whoever proposes it | Set the mark at or below what the free check showed them. | PATCH /{namespace}/agreements/{id} |
pass-sheet-lock (the record’s Pass sheet lock) | any edit to a signed pass sheet; a change is a new version both sign, once | Draft a new version for both sides to sign; the pass date resets. | POST /{namespace}/agreements |
re-run-cap (the record’s Re-run cap) | a second re-run, or one without a fixed Product defect and the buyer’s written ask | One re-run, on a defect fixed within 5 business days, with no mark changed. | POST /{namespace}/issues/{issue}/resolve |
pilot-cap (the record’s Pilot cap) | a sixth open pilot | Wait in the queue for the dated start, or end a running pilot first. | POST /{namespace}/tasks/next |
price (gaps #1) | a Quote below the plan’s price floor, such as a rescue discount after a miss | Get the discount approved, or quote at the floor. | POST /{namespace}/approvals/{approval}/approve |
The captured refusal, then the Stop that fired as a Campaign.paused reason (Not live yet, gaps #2); the rewrite that went out is the Northgate pass sheet in Example.
| Check | Fix | Then |
|---|---|---|
mark-cap fail | Set the mark at or below what the free check showed them. | PATCH /{namespace}/agreements/{id} |
price pass · Not live yet, gaps #1 | — | POST /{namespace}/approvals/{approval}/approve |
JSON
{
"type": "https://startupbuilder.dev/errors/refused",
"title": "Refused",
"status": 422,
"detail": "The Northgate pass sheet did not go out: one mark is above what the free check showed them.",
"checks": [
{
"check": "mark-cap",
"status": "fail",
"doc": "/plays/paid-pilot#check-mark-cap",
"fix": "Set the mark at or below what the free check showed them.",
"then": "Agreement.update"
},
{
"check": "price",
"status": "pass"
}
]
}It says no, says why, and names the fix.
[
{
"reason": {
"limit": "label-hold",
"observed": "3 of 20 items disagree",
"bound": "2 of 20",
"window": "the day-4 hand-check, Greystone"
},
"doc": "/plays/paid-pilot#stop-label-hold" ,
"task": "task_421"
}
]Did it work
At 2 pilots a month, no held-back half reads, so the basis is before-after (rule o): the columns read Now and Before, and nothing prints as Added. The pass-line experiment draws each eligible Deal into a buyer-sample or a seller-set Variant and pools it across Other Startups. Each figure’s call is POST /{namespace}/metrics/query by node, and every node above the leaf is Not live yet (gaps #4).
75 per 100 against 40 before · before-after,
- Chose
- propose-a-pilot
- Why
- the free check on 50 of Larkfield’s leases read renewal dates right on 48 (96 %) on Oct 12; $2,400 a year is at your median won Deal; Owen named the CFO, Hana Ito, as budget holder; 3 pilots are open, under the cap of 5
- From
- check-their-sample · propose-a-pilot · check-only · start-the-term · end-on-the-miss · ask-the-budget-holder
- Expects
- the pilot Agreement signed and the $400 fee paid within 10 business days
- Reopens when
- no Agreement.signed for deal_21 within 10 business days of the proposal
- By
- worker_8
JSON
{
"$id": "decisions/decision_574",
"$type": "Decision",
"choice": "propose-a-pilot",
"reason": "the free check on 50 of Larkfield’s leases read renewal dates right on 48 (96 %) on Oct 12; $2,400 a year is at your median won Deal; Owen named the CFO, Hana Ito, as budget holder; 3 pilots are open, under the cap of 5",
"stakes": "medium",
"options": [
"check-their-sample",
"propose-a-pilot",
"check-only",
"start-the-term",
"end-on-the-miss",
"ask-the-budget-holder"
],
"by": "worker_8",
"on": "deal_21",
"expected": "the pilot Agreement signed and the $400 fee paid within 10 business days",
"reopensWhen": "no Agreement.signed for deal_21 within 10 business days of the proposal"
}| Node | Now (105 days) | Before (the 90 days of free proofs) | Added | Confidence | Basis |
|---|---|---|---|---|---|
technical-win-rate | 75 per 100: 3 of 4 completed pilots passed · 1 still running | 40 per 100: 2 of 5 free proofs | — · Worth about +$430 a month | — | before-after, not proof · Other Startups’ results +15 per 100, ■■■□ Likely, n 380 pilots |
new-paying-customers | 2 from pilots, 1 still deciding · Booked $4,786: credited, not all caused by this Play | 1 from a free proof | — | — | before-after; pilot fees are one-time and left out |
new-arr ↑ | $4,786, 2 Customers on the $2,400 plan | $2,393, 1 Customer | — | — | before-after; $1,600 of pilot fees roll off as one-time-rolloff-arr |
net-new-arr · arr | carried from new-arr | carried | — | — | carried |
Before against after reads completed pilots in this window against the free proofs of the 90 days before it; it is not proof. Technical win counts a pilot whose every deciding line met its mark on the pass date.
How it moves it: each buyer saw your product score their own leases against marks no higher than the free check, and a miss ended the pilot that day; before, a free proof ran on your demo data (technical-win-rate by Variant).
Guardrails: before against after: passed pilots that started a first term, 2 of 3 against a floor of 5 of 10, and miss refunds, 1 of 4 against a floor of 25 % over 90 days.
{
"$id": "https://api.sb/leaseline.app/campaigns/paid-pilot" ,
"$type": "Campaign",
"play": "play:paid-pilot@1" ,
"path": [
"technical-win-rate",
"new-paying-customers",
"new-arr",
"net-new-arr",
"arr"
],
"experiment": {
"metric": "technical-win-rate",
"unit": "per-100",
"heldBack": 0,
"decision": null
},
"readout": {
"value": null,
"n": 4,
"maturing": 1,
"interval": null,
"readability": "inadmissible",
"basis": "before-after",
"pooled": true
},
"ledger": {
"spend": 126,
"workerCost": 6,
"hours": 7.2,
"pipelineArr": 2400,
"wonArr": 4786,
"projectedArr": 431,
"paybackDays": 9
}
}Outside benchmark: the catalog holds none for this Play yet, so Other Startups’ results stand in: +15 technical wins per 100 pilots, ■■■□ Likely, n 380 pilots.
Before it · After it. Before it: instant-response, moment-outreach and buying-committee open the Deals whose buyers ask to test. After it: a passed pilot’s first term carries its Tenant into onboarding, a miss reaches objection-watch as a dated no, and run-beside reports a side-by-side on the buyer’s own items.
Example
Leaseline ran it from 2026-07-06 to 2026-10-19 (105 days): 9 Decisions on 7 open Deals, 7 free checks and 5 pilots proposed, 4 signed. 4 pilots completed: 3 passed and 1 missed. Read every captured thread at ?threads=; three follow the tables.
| What happened, by option | Decisions | Done | Won (credited, not all caused by this Play) |
|---|---|---|---|
| Run the free check on their data · Stop at the free check | 7 · 2 | 7 checks back within 1 business day · 2 stopped there | 0 |
| Propose a paid pilot | 5 | 4 signed, 4 fees paid ($1,600, one-time) | — |
| Start the first term · End it on the miss · Ask the budget holder | 3 · 1 · 1 | 2 started, 1 deciding · 1 refunded the same day · 1 run resumed | 2 on the $2,400 plan (+$4,786 ARR) · 0 · — |
| At 2 Deals a month (the Use it when volume) | about 7 in 105 days | before-after, not proof | Other Startups’ results: +15 per 100, ■■■□ Likely, n 380 pilots |
| Day | Event | What happened | Your time |
|---|---|---|---|
| 0 | event_101 Campaign.created | the three steps; the dry run fails price: no pilot Offer, no floor | 30 min |
| 0 | event_104 Offer.published | the $400 pilot, credited to the $2,400 plan’s first term | 15 min |
| 6 | event_160 Invoice.collected | the first pilot fee paid: Harborview Living | — |
| 58 | event_640 Campaign.paused | label-hold on Greystone’s day-4 hand-check; labels fixed, run resumed in 1 day | 40 min |
| 63 · 98 | event_702 Change.merged · event_1015 Readout.created | pass sheets capped at 3 lines: replayed 3 of 4 passed, read back 2 of 2 | 5 min |
| 95 | event_988 Invoice.refunded | end-on-the-miss: Greystone’s owner-statement line at 91 % against a 94 % mark; refunded that day | 10 min |
| 1–105 | event_133 Task.assigned, first of 26 | Priya sent every Deal-thread draft; you approved 4 pass sheets; weekly reviews, from the POST /{namespace}/tasks/next log | 5 h 30 min · total 7.2 h measured, 7 h asked |
Priya Shah → Rosa, Harborview Living, Jul 29, from the agent’s draft · Your pilot passed on all 3 lines.¹ Renewal dates read right: 97.2 % (243 of 250, mark 96 %). Notice dates computed right: 98.0 % (mark 95 %). Owner statements match: 96.4 % (mark 94 %), scored Jul 28.² Your first term starts Aug 5 at $2,400 a year, less your $400 credit, unless you cancel before then on the same Page.³
Rosa, Jul 29, 16:20 · “Great. Go ahead.”
POST /{namespace}/quotes/{quote}/accept, and the first term started on Aug 5.
- Scanned leases read right: 98 % or better.
+ Scanned leases read right: 94 % or better (the free check read 47 of 50 on Sep 11). Greystone Residential pilot, 2026-09-24 · the champion silent 14 days on day 12 · the run paused (
silence-hold), and the Brief went to Dana (task_429). Dana wrote to the budget holder, Marcus Webb, on Sep 25 at 10:15, inside the due time; he confirmed the pilot the same afternoon and the run resumed.
¹ The verdict first, as the readout requires. ² Every number from the pinned Evaluator on their own 250 leases, with n and the date. ³ The contingent start date and its cancel action in one sentence.
Your settings
---
fee: 400 # credited to the first term
refund: full-on-miss
---
Over 300 units and at our median Deal, propose the pilot after the free check.
Any fit doubt gets the free check on 50 of their items first.
At most 3 deciding lines on a pass sheet.
Priya owns the Deal and sends every message; I write to the budget holder. $ npx startup-builder show plays/paid-pilot
fee $400 credited · refund in full on a miss · pilot over 300 units after the free check · 3 lines at most · the AE sends your file plays/paid-pilot.mdx:2,3,5,6,7,8 (Ask 2026-07-06; line 7 by change_25, 2026-09-07)
family conversion · worker role:sales-engineer, owns never · chooses 6 (4 rule, 2 read) · sequences pilot-proposal, pilot-run-updates, pilot-decision, pilot-founder-notes, pilot-miss-notice · approval every-send · checks owned-by-a-person, mark-cap, pass-sheet-lock, re-run-cap, pilot-cap, price · stops 11 catalog play:paid-pilot@1 (Not live yet, gaps #5) Every key from the catalog
Compiled, not written: edit the Play record paid-pilot 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.