Skip to content

Open Deals: next step, close month, stall line

Open Deals by Deal status: each count, ARR, median days and the call that moves it, with lost reasons ranked.

Every open Deal, by Deal status, with its next step, the month the buyer decides and the line where it stalls.

The record

Deal statusDealsARRConversion to WonMedian daysThe call that moves it
Open8$2,776 ARRwin rate by Deal status, Not live yet, gaps #26 d, stall at 12 dPOST /{namespace}/deals/{deal}/advance
Qualified6$4,128 ARRwin rate by Deal status, Not live yet, gaps #29 d, stall at 18 dPOST /{namespace}/deals/{deal}/propose
Proposed3$1,041 ARRwin rate by Deal status, Not live yet, gaps #211 d, stall at 22 dPOST /{namespace}/deals/{deal}/win
Won9 in 90 days$5,169 ARRnone: a final Deal statussales cycle, Not live yet, gaps #2POST /{namespace}/customers/{customer}/activate
Lost14 in 90 days$10,996 ARRnone: a final Deal statussales cycle, Not live yet, gaps #2POST /{namespace}/deals

Count, ARR and median days from statusSince · from GET /{namespace}/deals in the window below · sample

Expected from open Deals: +$1,388 ARR from 17 open Deals worth $7,945 ARR if all were won · Not live yet, gaps #2 · sample. It is each open Deal’s ARR times its Deal status’s 90-day win rate, and it feeds the cash projection.

DealDeal statusARR if wonBuyer decidesNext stepThe call that moves it
deal_28Proposed+$347 ARR2026-10-24Pinecrest Lofts: signing call on Oct 22POST /{namespace}/deals/{deal}/win
deal_33Qualified+$347 ARR2026-10-29Harbor Row: demo with the owner on Oct 23POST /{namespace}/deals/{deal}/propose
deal_31Qualified+$2,393 ARR2026-10-30Northgate Rentals: the two-year Quote once the discount is approvedPOST /{namespace}/deals/{deal}/propose
deal_35Open+$347 ARR2026-10-31Elm Court: security answers by Oct 27POST /{namespace}/deals/{deal}/advance
Lost reason, rankedDealsARR lostThe Play that answers it
price5−$5,827 ARRRisk-reversal offers
no-decision3−$3,087 ARRBuying committee
missing-capability2−$694 ARRLead reactivation
timing2−$694 ARRLead nurture
competitor1−$347 ARRSwitch kit
no-fit1−$347 ARRPositioning tournament

Run it

Move today’s Deals onMode try
You, to your agent

Show me every Deal by status, then move today’s three on: qualify Birchway Properties, send Pinecrest Lofts its proposal and mark Maple Street Homes won. Send nothing.

curl "https://api.sb/leaseline.app/deals?facets=status&total=true" \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"

curl -X POST "https://api.sb/leaseline.app/deals/deal_36/advance?mode=try" \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"

curl -X PATCH "https://api.sb/leaseline.app/deals/deal_36?mode=try" \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"closesOn":"2026-11-14","nextStep":"Demo with the 4 owners on Oct 22"}'

curl -X POST "https://api.sb/leaseline.app/deals/deal_28/propose?mode=try" \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"quote":"quote_4"}'

curl -X POST "https://api.sb/leaseline.app/deals/deal_27/win?mode=try" \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"
import { $ } from 'startup-builder'

const { facets } = await $.Deal.list({ facets: 'status', total: true })   // count, ARR and median days in status, from statusSince
await $.Deal.advance({ deal: 'deal_36' }, { mode: 'try' })   // Birchway Properties, Open to Qualified
// 422 · Birchway Properties did not move to Qualified: closesOn and nextStep are empty.
// stage-fields: Fill each field the refusal names, then move the Deal on again. · then Deal.update
await $.Deal.update({ id: 'deal_36', closesOn: '2026-11-14', nextStep: 'Demo with the 4 owners on Oct 22' }, { mode: 'try' })   // the two fields the refusal named
await $.Deal.propose({ deal: 'deal_28', quote: 'quote_4' }, { mode: 'try' })   // Pinecrest Lofts, call held Oct 15
return await $.Deal.win({ deal: 'deal_27' }, { mode: 'try' })   // Maple Street Homes signed the $29 plan
npx startup-builder do Deal.list --json '{"facets":"status","total":true}'
npx startup-builder do Deal.advance --json '{"deal":"deal_36"}' --try
npx startup-builder do Deal.update --json '{"id":"deal_36","closesOn":"2026-11-14","nextStep":"Demo with the 4 owners on Oct 22"}' --try
npx startup-builder do Deal.propose --json '{"deal":"deal_28","quote":"quote_4"}' --try
npx startup-builder do Deal.win --json '{"deal":"deal_27"}' --try
{
  "name": "do",
  "arguments": {
    "code": "const { facets } = await $.Deal.list({ facets: 'status', total: true })   // count, ARR and median days in status, from statusSince\nawait $.Deal.advance({ deal: 'deal_36' }, { mode: 'try' })   // Birchway Properties, Open to Qualified\n// 422 · Birchway Properties did not move to Qualified: closesOn and nextStep are empty.\n// stage-fields: Fill each field the refusal names, then move the Deal on again. · then Deal.update\nawait $.Deal.update({ id: 'deal_36', closesOn: '2026-11-14', nextStep: 'Demo with the 4 owners on Oct 22' }, { mode: 'try' })   // the two fields the refusal named\nawait $.Deal.propose({ deal: 'deal_28', quote: 'quote_4' }, { mode: 'try' })   // Pinecrest Lofts, call held Oct 15\nreturn await $.Deal.win({ deal: 'deal_27' }, { mode: 'try' })   // Maple Street Homes signed the $29 plan",
    "mode": "try"
  }
}
Response200application/json
{
  "deal": {
    "$id": "https://api.sb/leaseline.app/deals/deal_27",
    "$type": "Deal",
    "status": "Won",
    "value": {
      "amount": 348,
      "currency": "USD"
    },
    "closesOn": "2026-10-19",
    "statusSince": "2026-10-19T10:12:00Z",
    "owner": "worker_3"
  },
  "action": {
  …
samplePreview

Refuses when

422RefusedBirchway Properties did not move to Qualified: closesOn and nextStep are empty.
CheckFixThen
stage-fields failFill each field the refusal names, then move the Deal on again.PATCH /{namespace}/deals/{id}
JSON
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "Birchway Properties did not move to Qualified: closesOn and nextStep are empty.",
  "checks": [
    {
      "check": "stage-fields",
      "status": "fail",
      "observed": "closesOn, nextStep",
      "doc": "/code/refusals#check-stage-fields",
      "fix": "Fill each field the refusal names, then move the Deal on again.",
      "then": "Deal.update"
    }
  ]
}

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

CodeOnRefusesThen
stage-fieldsPOST /{namespace}/deals/{deal}/advancea field the next Deal status needs is emptyPATCH /{namespace}/deals/{id}
no-meeting-held · Not live yet, gaps #2POST /{namespace}/deals/{deal}/proposea proposal before any call with the buyer was heldPOST /{namespace}/meetings/book
stalled-deal · Stop · Not live yet, gaps #2every send to the Dealtwice its Deal status’s median days with no dated next stepPATCH /{namespace}/deals/{id}

Plays that use it

PlayWhat it does
Closer handoffHands 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 committeeWrites to 3 or more roles at each named company, one a week, and hands each engaged company to your AE within a day.
Instant responseAnswers every form and email within 5 minutes from your own pages, books the call, starts the trial or hands it to the right person.
Lead reactivationWrites once to each old Lead nobody works, only when something new answers what they asked, from their last contact at the Startup.
Switch kitWins your rival’s users with an importer tested on its exports and a dry run they see first, stating no rival fact without a source.

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.

Contents