Qualified Deals: what moves them on
Qualified Deals: what moves one to a proposal, who owns it, how long it waits and what holds it.
A qualified Deal has a value, a close date and a next step. It moves on when a call is held and a Quote goes out.
It moves on when
| To | When | The call | Event |
|---|---|---|---|
| Proposed | a call with the buyer was held and a Quote is attached | POST /{namespace}/deals/{deal}/propose | Deal.proposed |
| Lost | the buyer says no, with a reason | POST /{namespace}/deals/{deal}/lose | Deal.lost |
Who owns it
| Title | What it does here |
|---|---|
| AE | runs the call and drafts the Quote |
| SE | joins when the buyer asks security or setup questions |
How long it sits
| Median days in it | Deals | Stall line | Past it now |
|---|---|---|---|
9 d | 6 | 18 d | 1 |
The stall line is twice the median, read from each Deal’s statusSince · sample
The call that moves it
You, to your agent
Send Harbor Row its proposal. If a call with the buyer comes first, book it. Send nothing.
curl "https://api.sb/leaseline.app/deals?where=status%20%3D%20%22Qualified%22&sort=statusSince" \
-H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"
curl -X POST "https://api.sb/leaseline.app/deals/deal_33/propose?mode=try" \
-H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"quote":"quote_5"}'
curl -X POST "https://api.sb/leaseline.app/meetings/book?mode=try" \
-H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"contact":"contact_22","at":"2026-10-23T16:00:00Z"}'import { $ } from 'startup-builder'
const { deals } = await $.Deal.list({ where: 'status = "Qualified"', sort: 'statusSince' })
await $.Deal.propose({ deal: 'deal_33', quote: 'quote_5' }, { mode: 'try' }) // no call held with Harbor Row
// 422 · Harbor Row’s proposal did not send: no Meeting with the buyer has been held.
// no-meeting-held: Book a call with the buyer and hold it, then send the proposal again. · then Meeting.book
return await $.Meeting.book({ contact: 'contact_22', at: '2026-10-23T16: 00: 00Z' }, { mode: 'try' }) // the demo with the owner
npx startup-builder do Deal.list --json '{"where":"status = \"Qualified\"","sort":"statusSince"}'
npx startup-builder do Deal.propose --json '{"deal":"deal_33","quote":"quote_5"}' --try
npx startup-builder do Meeting.book --json '{"contact":"contact_22","at":"2026-10-23T16:00:00Z"}' --try{
"name": "do",
"arguments": {
"code": "const { deals } = await $.Deal.list({ where: 'status = \"Qualified\"', sort: 'statusSince' })\nawait $.Deal.propose({ deal: 'deal_33', quote: 'quote_5' }, { mode: 'try' }) // no call held with Harbor Row\n// 422 · Harbor Row’s proposal did not send: no Meeting with the buyer has been held.\n// no-meeting-held: Book a call with the buyer and hold it, then send the proposal again. · then Meeting.book\nreturn await $.Meeting.book({ contact: 'contact_22', at: '2026-10-23T16:00:00Z' }, { mode: 'try' }) // the demo with the owner",
"mode": "try"
}
}Response200
application/json{
"meeting": {
"$id": "https: //api.sb/ leaseline.app/ meetings/ meeting_17",
"$type": "Meeting",
"at": "2026-10-23T16: 00: 00Z",
"agenda": "Demo for Harbor Row’s owner: renewals and late-rent reminders"
},
"action": {
"$id": "https: //api.sb/ leaseline.app/ actions/ action_21",
"operation": "Meeting.book",
"status": "pending",
"reason": "awaitingApproval",
"mode": "try"
}
}
samplePreviewWhen it won’t move
| Check | Fix | Then |
|---|---|---|
no-meeting-held fail · Not live yet, gaps #2 | Book a call with the buyer and hold it, then send the proposal again. | POST /{namespace}/meetings/book |
JSON
{
"type": "https://startupbuilder.dev/errors/refused",
"title": "Refused",
"status": 422,
"detail": "Harbor Row’s proposal did not send: no Meeting with the buyer has been held.",
"checks": [
{
"check": "no-meeting-held",
"status": "fail",
"observed": "0 Meetings held, 0 booked",
"doc": "/code/refusals#check-no-meeting-held",
"fix": "Book a call with the buyer and hold it, then send the proposal again.",
"then": "Meeting.book"
}
]
}It says no, says why, and names the fix.
no-meeting-held is Not live yet, gaps #2; the card renders from the sample.
Plays that unstick it
| Play | What it does |
|---|---|
| Closer handoff | Hands a large Deal that stalled twice to a commissioned closer, paid only on collected revenue, and tests it against the Deals your agent keeps. |
| Buying committee | Writes to 3 or more roles at each named company, one a week, and hands each engaged company to your AE within a day. |
| Trust pack | Sends the trust page and prefilled security answers with every large Quote, and releases the security report only after a click-through Agreement. |
| 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. |
Compiled, not written: edit its page, 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.