Skip to content

Revenue: where ARR moved, and which Deals close next

From the first reply to ARR.

Where ARR moved this week, and which Deals close next. The six moves add up to the change, and your SDR, AE and CSM each get one next step.

  1. $2,082New Customers
  2. $0Won back
  3. $347Upgrades
  4. $0Downgrades
  5. $1,041Lost Customers
  6. $0One-time sales ending
  7. $0Not yet traced
  8. +$1,388ARR added this week
Sent by your other Startups: 0 % · ARR $9,021 · target +$1,800 a weeksample · leaseline.app · week of 2026-10-19
ARR added each week
You, to your agent

Where did ARR move this week, and which Deals close next?

# Not live yet (gaps #4)
curl -X POST https://api.sb/leaseline.app/metrics/query \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"metric":"net-new-arr","shape":"trend","window":"56d"}'
import { $ } from 'startup-builder'

return await $.Metric.query({ metric: 'net-new-arr', shape: 'trend', window: '56d' })   // eight Mondays, each split into the six moves · Not live yet, gaps #4
npx startup-builder do Metric.query --json '{"metric":"net-new-arr","shape":"trend","window":"56d"}'   # Not live yet (gaps #4)
{
  "name": "do",
  "arguments": {
    "code": "return await $.Metric.query({ metric: 'net-new-arr', shape: 'trend', window: '56d' })   // eight Mondays, each split into the six moves · Not live yet, gaps #4"
  }
}
Response200application/json
{
  "metric": {
    "$id": "https://api.sb/leaseline.app/metrics/net-new-arr",
    "$type": "Metric",
    "name": "Net new ARR"
  },
  "asOf": "2026-10-19T00:00:00Z",
  "rows": [
    {
      "week": "2026-08-31",
      "value": 694
    },
    {
      "week": "2026-09-07",
  …
sample · 1 Not live yet

+$1,388 ARR added this week · ■■■■ Clear · n 26 Customers · path → arr

$.Metric.query({ metric: 'net-new-arr', shape: 'trend', window: '56d' }) · sample

Monday review

Biggest mover: Lost Customers, −$1,041 ARR: 3 Customers, 2 of them at risk a week earlier. Against your number, the week is $412 ARR short of the +$1,800 ARR a week it needs.

TitleHours this weekWhat it doesExpectedThe call that starts it
CSM2 hthe 4 Customers now at risk, Juniper Homes first: it renews Nov 3Lost Customers better than −$400 ARR by Oct 26POST /{namespace}/renewals/open
AE1 hNorthgate Rentals: approve 30 % off the $2,400 plan on a two-year termNew Customers +$1,675 ARR once Northgate Rentals is wonPOST /{namespace}/approvals/{approval}/approve
SDR1 happrove the first wave to the 18 Leads lead reactivation re-openedDeals and trials opened +4 by Oct 26POST /{namespace}/approvals/{approval}/approve
Monday: the next step for SDR, AE and CSMMode try
You, to your agent

Where is the number this week, and what do we change? Start the next step for our SDR, AE and CSM in try mode.

curl -X POST "https://api.sb/leaseline.app/renewals/open?mode=try" \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"subscription":"subscription_7"}'

curl -X POST "https://api.sb/leaseline.app/approvals/approval_3/approve?mode=try" \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"note":"Two-year term"}'

curl -X POST "https://api.sb/leaseline.app/approvals/approval_5/approve?mode=try" \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"

# Not live yet (gaps #4)
curl -X POST https://api.sb/leaseline.app/metrics/query \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"metric":"net-new-arr","shape":"trend","window":"7d","breakdown":"node"}'
import { $ } from 'startup-builder'

const { renewal } = await $.Renewal.open({ subscription: 'subscription_7' }, { mode: 'try' })   // CSM · 2 h · the 4 Customers now at risk, Juniper Homes first (renews Nov 3)
const discount = await $.Approval.approve({ approval: 'approval_3', note: 'Two-year term' }, { mode: 'try' })   // AE · 1 h · 30 % off for Northgate Rentals on a two-year term
const wave = await $.Approval.approve({ approval: 'approval_5' }, { mode: 'try' })   // SDR · 1 h · the first wave to the 18 re-opened Leads
return await $.Metric.query({ metric: 'net-new-arr', shape: 'trend', window: '7d', breakdown: 'node' })   // the week, by move · Not live yet, gaps #4
npx startup-builder do Renewal.open --json '{"subscription":"subscription_7"}' --try
npx startup-builder do Approval.approve --json '{"approval":"approval_3","note":"Two-year term"}' --try
npx startup-builder do Approval.approve --json '{"approval":"approval_5"}' --try
npx startup-builder do Metric.query --json '{"metric":"net-new-arr","shape":"trend","window":"7d","breakdown":"node"}'   # Not live yet (gaps #4)
{
  "name": "do",
  "arguments": {
    "code": "const { renewal } = await $.Renewal.open({ subscription: 'subscription_7' }, { mode: 'try' })   // CSM · 2 h · the 4 Customers now at risk, Juniper Homes first (renews Nov 3)\nconst discount = await $.Approval.approve({ approval: 'approval_3', note: 'Two-year term' }, { mode: 'try' })   // AE · 1 h · 30 % off for Northgate Rentals on a two-year term\nconst wave = await $.Approval.approve({ approval: 'approval_5' }, { mode: 'try' })   // SDR · 1 h · the first wave to the 18 re-opened Leads\nreturn await $.Metric.query({ metric: 'net-new-arr', shape: 'trend', window: '7d', breakdown: 'node' })   // the week, by move · Not live yet, gaps #4",
    "mode": "try"
  }
}
Response200application/json
{
  "week": "2026-10-19",
  "moves": {
    "newArr": 2082,
    "reactivatedArr": 0,
    "expansionArr": 347,
    "contractionArr": 0,
    "churnedArr": -1041,
    "oneTimeRolloffArr": 0,
    "unexplained": 0,
    "netNewArr": 1388,
    "arr": 9021
  },
  "target": {
  …
sample · 1 Not live yet

The hub runs this review as the Workflow monday-role-review.

Deal review

Lost reasonDealsARR 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

The typed reason is Not live yet, gaps #2; today POST /{namespace}/deals/{deal}/lose keeps the free text, and the window reads it from the Deal.lost Events.

Why Deals were lost
You, to your agent

Why are we losing deals, and what do we change?

curl "https://api.sb/leaseline.app/events?where=name%20%3D%20%22Deal.lost%22%20and%20at%20%3E%3D%20%222026-07-21%22&limit=14" \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"

# Not live yet (gaps #2)
curl "https://api.sb/leaseline.app/deals?where=status%20%3D%20%22Lost%22&facets=lostReason" \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"
import { $ } from 'startup-builder'

const { events } = await $.Event.list({ where: 'name = "Deal.lost" and at >= "2026-07-21"', limit: 14 })   // 14 Deals lost in 90 days, each with its free-text reason
return await $.Deal.list({ where: 'status = "Lost"', facets: 'lostReason' })   // the typed reason, ranked by ARR · Not live yet, gaps #2
npx startup-builder do Event.list --json '{"where":"name = \"Deal.lost\" and at >= \"2026-07-21\"","limit":14}'
npx startup-builder do Deal.list --json '{"where":"status = \"Lost\"","facets":"lostReason"}'   # Not live yet (gaps #2)
{
  "name": "do",
  "arguments": {
    "code": "const { events } = await $.Event.list({ where: 'name = \"Deal.lost\" and at >= \"2026-07-21\"', limit: 14 })   // 14 Deals lost in 90 days, each with its free-text reason\nreturn await $.Deal.list({ where: 'status = \"Lost\"', facets: 'lostReason' })   // the typed reason, ranked by ARR · Not live yet, gaps #2"
  }
}
Response200application/json
{
  "total": 14,
  "facets": {
    "lostReason": [
      {
        "value": "price",
        "deals": 5,
        "arr": 5827,
        "answeredBy": "risk-reversal-offers"
      },
      {
        "value": "no-decision",
        "deals": 3,
        "arr": 3087,
  …
sample · 1 Not live yetPreview

Expected from open Deals

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.

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

It is each open Deal’s ARR times the 90-day win rate of its Deal status. It feeds the cash projection, whose spend state sets what Your Play mix buys.

Deals likely to close this month
You, to your agent

Which of my open deals are likely to close this month?

curl "https://api.sb/leaseline.app/deals?where=status%20in%20(%22Open%22%2C%20%22Qualified%22%2C%20%22Proposed%22)%20and%20closesOn%20%3C%3D%20%222026-10-31%22&sort=closesOn" \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"

# Not live yet (gaps #2)
curl -X POST https://api.sb/leaseline.app/metrics/query \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"metric":"weighted-pipeline","shape":"trend","window":"90d"}'
import { $ } from 'startup-builder'

const { deals } = await $.Deal.list({ where: 'status in ("Open", "Qualified", "Proposed") and closesOn <= "2026-10-31"', sort: 'closesOn' })   // open Deals the buyer expects to decide this month
return await $.Metric.query({ metric: 'weighted-pipeline', shape: 'trend', window: '90d' })   // each open Deal’s ARR times its status’s 90-day odds · Not live yet, gaps #2
npx startup-builder do Deal.list --json '{"where":"status in (\"Open\", \"Qualified\", \"Proposed\") and closesOn <= \"2026-10-31\"","sort":"closesOn"}'
npx startup-builder do Metric.query --json '{"metric":"weighted-pipeline","shape":"trend","window":"90d"}'   # Not live yet (gaps #2)
{
  "name": "do",
  "arguments": {
    "code": "const { deals } = await $.Deal.list({ where: 'status in (\"Open\", \"Qualified\", \"Proposed\") and closesOn <= \"2026-10-31\"', sort: 'closesOn' })   // open Deals the buyer expects to decide this month\nreturn await $.Metric.query({ metric: 'weighted-pipeline', shape: 'trend', window: '90d' })   // each open Deal’s ARR times its status’s 90-day odds · Not live yet, gaps #2"
  }
}
Response200application/json
{
  "deals": [
    {
      "$id": "https://api.sb/leaseline.app/deals/deal_28",
      "$type": "Deal",
      "status": "Proposed",
      "value": {
        "amount": 348,
        "currency": "USD"
      },
      "closesOn": "2026-10-24",
      "statusSince": "2026-10-16T14:10:00Z",
      "nextStep": "Pinecrest Lofts: signing call on Oct 22"
    },
  …
sample · 1 Not live yetPreview

Seat scorecards

Your number · 4 of 6 · target 6 by Dec 31 · gap 2 · ■■■□ Likely · n 31

$.Metric.query({ metric: 'opened-deals-and-trials', shape: 'trend', window: '7d' }) · sample

TitleIts numberNowTargetShort by
You, as head of salesARR added each week+$1,388 ARR+$1,800 ARR by Dec 31$412 ARR
SDRDeals and trials opened a week46 by Dec 312
AENew paying Customers from Deals, a week23 by Dec 311
CSMNet revenue retention on its book85 %100 % by Dec 3115 points

Coverage, how many times open Deals cover a gap, prints once the hub holds it (Not live yet, gaps #2).

The SDR, AE and CSM numbers
You, to your agent

How far am I from my target this quarter?

curl "https://api.sb/leaseline.app/key-results?where=deadline%20%3D%20%222026-12-31%22" \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"

# Not live yet (gaps #4)
curl -X POST https://api.sb/leaseline.app/metrics/query \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"metric":"opened-deals-and-trials","shape":"trend","window":"7d"}'
import { $ } from 'startup-builder'

const { keyResults } = await $.KeyResult.list({ where: 'deadline = "2026-12-31"' })   // the quarter’s four Key Results, three of them held by a seat
return await $.Metric.query({ metric: 'opened-deals-and-trials', shape: 'trend', window: '7d' })   // the SDR’s number this week · Not live yet, gaps #4
npx startup-builder do KeyResult.list --json '{"where":"deadline = \"2026-12-31\""}'
npx startup-builder do Metric.query --json '{"metric":"opened-deals-and-trials","shape":"trend","window":"7d"}'   # Not live yet (gaps #4)
{
  "name": "do",
  "arguments": {
    "code": "const { keyResults } = await $.KeyResult.list({ where: 'deadline = \"2026-12-31\"' })   // the quarter’s four Key Results, three of them held by a seat\nreturn await $.Metric.query({ metric: 'opened-deals-and-trials', shape: 'trend', window: '7d' })   // the SDR’s number this week · Not live yet, gaps #4"
  }
}
Response200application/json
{
  "keyResults": [
    {
      "$id": "https://api.sb/leaseline.app/key-results/key_result_1",
      "$type": "KeyResult",
      "metric": "net-new-arr",
      "baseline": 0,
      "target": 1800,
      "deadline": "2026-12-31",
      "now": 1388
    },
    {
      "$id": "https://api.sb/leaseline.app/key-results/key_result_2",
      "$type": "KeyResult",
  …
sample · 1 Not live yetPreview

The tree

NumberThis weekOwnerWorked by
ARR$9,021 ARRfounderYou, as head of sales
ARR added each week+$1,388 ARRfounderYou, as head of sales
New Customers+$2,082 ARRfounderYou, as head of sales
People reached412marketing-leadContent Lead
New Leads38marketing-leadSDR
Deals and trials opened11sales-leadSDR
New paying Customers6sales-leadAE
First order size+$347 ARRsales-leadAE
Activation rate65 %team:productOnboarding
Referred Customers4 %team:marketingPartnerships
Sent by your other Startups0 %marketing-leadPartnerships
Won back$0 ARRcustomer-leadHead of customers
Upgrades+$347 ARRcustomer-leadCSM
Downgrades$0 ARRcustomer-leadCSM
Lost Customers−$1,041 ARRcustomer-leadCSM
Month 3 retention81 %team:customerOnboarding
One-time sales ending$0 ARRcustomer-leadHead of customers
Not yet traced$0 ARRfounderYou, as head of sales

Each number links its page, with the Plays, pages and title that move it.

Net revenue retention

Reading90 daysCustomers
Net revenue retention85 %13
The gross line, before upgrades and win-backs (Not live yet, gaps #4)69 %13
logo-churn31 %4 of 13

85 % net revenue retention · ■■□□ Early sign · n 13 Customers · 90 days

$.Metric.query({ metric: 'net-revenue-retention', shape: 'retention', window: '90d' }) · sample

Credit

How they first arrivedNew ARR this week
outbound+$694 ARR
direct+$694 ARR
referral+$347 ARR
search+$347 ARR
answer$0 ARR
ad$0 ARR
agent$0 ARR
Not yet traced$0 ARR
New Customers+$2,082 ARR

Credited new ARR plus Not yet traced equals New Customers every week. Credit splits it by page and by Play.

Where Deals wait

Deal statusDealsMedian days in itStall linePast the stall lineThe call that moves it
Open86 d12 d1POST /{namespace}/deals/{deal}/advance
Qualified69 d18 d1POST /{namespace}/deals/{deal}/propose
Proposed311 d22 d1POST /{namespace}/deals/{deal}/win
HandoffWindowWaiting nowThe call
Marketing Lead to SDRanswered within 5 minutesfirst answer 40 s on first-response-time; speed to lead is Not live yet, gaps #6POST /{namespace}/leads/{lead}/assign
SDR to AEa call booked within 60 minutes of an Interested reply1 · the unanswered-positive Stop holds itPOST /{namespace}/meetings/book
AE to Onboardingthe Won Deal starts onboard-customer0POST /{namespace}/customers/{customer}/activate
CSM to AEan upgrade signal opens a Deal1POST /{namespace}/deals/{deal}/advance

Meetings held is Not live yet, gaps #6, so no row counts it.

Your quarter

Goal or Key ResultBaselineNowTargetBy
Reach $25k ARR by year end$0$9,021 ARR$25,000 ARR2026-12-31
ARR added each week, a week$0 ARR+$1,388 ARR+$1,800 ARR2026-12-31
Deals and trials opened, a week (SDR)2462026-12-31

Ten weeks remain: $15,979 ARR to go, +$1,598 ARR a week against a Key Result of +$1,800 ARR.

The quarter
You, to your agent

How far are we from $25k ARR by year end?

curl https://api.sb/leaseline.app/goals/goal_1 \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"

curl https://api.sb/leaseline.app/key-results/key_result_1 \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"
import { $ } from 'startup-builder'

const goal = await $.Goal.get({ id: 'goal_1' })   // Reach $25k ARR by year end
return await $.KeyResult.get({ id: 'key_result_1' })   // ARR added each week, against 1,800
npx startup-builder do Goal.get --json '{"id":"goal_1"}'
npx startup-builder do KeyResult.get --json '{"id":"key_result_1"}'
{
  "name": "do",
  "arguments": {
    "code": "const goal = await $.Goal.get({ id: 'goal_1' })   // Reach $25k ARR by year end\nreturn await $.KeyResult.get({ id: 'key_result_1' })   // ARR added each week, against 1,800"
  }
}
Response200application/json
{
  "$id": "https://api.sb/leaseline.app/key-results/key_result_1",
  "$type": "KeyResult",
  "goal": "goals/goal_1",
  "metric": "net-new-arr",
  "baseline": 0,
  "target": 1800,
  "deadline": "2026-12-31"
}
samplePreview

Offers and Deals

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