Skip to content

Single sign-on upgrade

Answers each single sign-on ask within one business hour with the plan that includes it, and the admin tests sign-in before paying.

Channel
More seats and upgrades
Run oneMode try
You, to your agent

Hand our latest single sign-on ask to the CSM agent and show me what it chose and why. Don’t send.

curl "https://api.sb/leaseline.app/events?where=name%20in%20(%22Message.received%22%2C%20%22Entitlement.checked%22%2C%20%22Quote.requested%22%2C%20%22Thread.joined%22%2C%20%22Tenant.thresholdCrossed%22%2C%20%22Domain.verified%22%2C%20%22Renewal.opened%22%2C%20%22Deal.lost%22%2C%20%22SSOConnection.failed%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_1288"}'

# Not live yet (gaps #7)
curl "https://api.sb/leaseline.app/decisions?where=on%20%3D%20%22customer_33%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%22customer_33%22" \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"
import { $ } from 'startup-builder'

const { events: [last] } = await $.Event.list({ where: 'name in ("Message.received", "Entitlement.checked", "Quote.requested", "Thread.joined", "Tenant.thresholdCrossed", "Domain.verified", "Renewal.opened", "Deal.lost", "SSOConnection.failed")', 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 (\"Message.received\", \"Entitlement.checked\", \"Quote.requested\", \"Thread.joined\", \"Tenant.thresholdCrossed\", \"Domain.verified\", \"Renewal.opened\", \"Deal.lost\", \"SSOConnection.failed\")","limit":1}'
npx startup-builder do Trigger.fire --json '{"like":"event_1288"}' --try   # Not live yet (gaps #7)
npx startup-builder do Decision.list --json '{"where":"on = \"customer_33\""}'   # Not live yet (gaps #7)
npx startup-builder do Action.list --json '{"where":"on = \"customer_33\""}'   # Not live yet (gaps #7)
{
  "name": "do",
  "arguments": {
    "code": "const { events: [last] } = await $.Event.list({ where: 'name in (\"Message.received\", \"Entitlement.checked\", \"Quote.requested\", \"Thread.joined\", \"Tenant.thresholdCrossed\", \"Domain.verified\", \"Renewal.opened\", \"Deal.lost\", \"SSOConnection.failed\")', 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"
  }
}
Response200application/json
{
  "decision": {
    "$id": "https://api.sb/leaseline.app/decisions/decision_347",
    "$type": "Decision",
    "choice": "set-up-first",
    "reason": "Pinecrest’s admin opened single sign-on setup on Team; 22 active members is under the 50-seat line, so they test sign-in before paying",
    "stakes": "low",
    "options": [
      "answer-the-ask",
      "set-up-first",
      "to-the-ae",
      "note-the-plan",
      "not-now"
    ],
  …
sample · 4 Not live yetPreview

On PATCH /{namespace}/campaigns/{id}Off PATCH /{namespace}/campaigns/{id}Take this one POST /{namespace}/tasks/{task}/claim

action_2 opens a test connection that signs in nobody until the admin presses Test; action_3 is the answer, held 2 minutes.

63 per 100 asks upgraded against 17 before · before-after, not proof · n 8 · path → arr

Try another: the CustomerChoiceReason
Pinecrest Management: their admin opened single sign-on setup on Team, 22 membersset-up-firstan admin at setup, under the 50-seat line
Quarry Lane Homes: “Do you support SSO with our Google accounts?”answer-the-aska written ask on Team, under the line
Northgate Rentals: the open Deal’s security questionnaire asks for SAMLto-the-aea questionnaire on an open Deal is the AE’s
Ridgeway Rentals: 21 active members, a sign-in Domain verified, no asknote-the-planpast 20 members with no ask; one note in 90 days
Harbor Row: asked about SSO, at risk since Oct 2not-nowkeep-first: their CSM sees them first

Where it sits: Stranger → Lead → Trialing → Activated → At risk → Churned → Won back · Tier upgrade rate → Upgrades ↑ → ARR added each week → ARR

Worth’s formula: about +21 upgrades per 100 asks (Other Startups’ results; no lift of your own yet) × 4 asks a month × $1,448 per Team-to-annual upgrade ≈ +$1,216. Under First signal: At 4 asks a month, 90 days can tell only +45 per 100 or more, so your file starts at holdout: 0 and reads before-after.

sample · api.sb/leaseline.app · 41 Customers at 2026-10-19 · on Entitlement.checked · first answer 6m 40s · 8 keys Not live yet

Start it this week

Terminal
npx startup-builder add play sso-rung   # 1 · writes plays/sso-rung.mdx (Not live yet, gaps #5)

# 2 · dry run; below, its 422 on 2026-07-20
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":"sso-rung"}'

# 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":"sso-rung"}'

# on
curl -X PATCH https://api.sb/leaseline.app/campaigns/sso-rung \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"endsAt":null}'

# off: asks come to you; active connections keep working
curl -X PATCH https://api.sb/leaseline.app/campaigns/sso-rung \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"endsAt":"now"}'
422Refusedsso-rung can’t start yet: 1 check fails and 2 warn.
CheckFixThen
use-when pass · Not live yet, gaps #8Nothing to fix: 2 or more asks a month, and a plan that has it.POST /{namespace}/metrics/query
billing-connected pass · Not live yet, gaps #8Nothing to fix: every charge reads from Stripe.POST /{namespace}/integrations/connect
approved-pages fail · Not live yet, gaps #8Publish the pricing Page row for the $2,400 plan; answers quote only your own pages.POST /{namespace}/sites/{site}/publish
baseline warn · Not live yet, gaps #8n 6: it reads before-after, not proof, until volume allows a held-back half.POST /{namespace}/metrics/query
role-unstaffed warn · Not live yet, gaps #8Staff the CSM, or leave it: 4 Customers Priya owns get drafts in her queue.POST /{namespace}/roles/{role}/staff
JSON
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "sso-rung can’t start yet: 1 check fails and 2 warn.",
  "checks": [
    {
      "check": "use-when",
      "status": "pass",
      "observed": "6 single sign-on asks in 90 days; the $2,400 plan includes it",
      "doc": "/plays/sso-rung#check-use-when",
      "fix": "Nothing to fix: 2 or more asks a month, and a plan that has it.",
      "then": "Metric.query"
    },
    {
      "check": "billing-connected",
      "status": "pass",
      "observed": "Stripe, connected",
      "doc": "/plays/sso-rung#check-billing-connected",
      "fix": "Nothing to fix: every charge reads from Stripe.",
      "then": "Integration.connect"
    },
    {
      "check": "approved-pages",
      "status": "fail",
      "observed": "no Page lists what the $2,400 plan includes",
      "doc": "/plays/sso-rung#check-approved-pages",
      "fix": "Publish the pricing Page row for the $2,400 plan; answers quote only your own pages.",
      "then": "Site.publish"
    },
    {
      "check": "baseline",
      "status": "warn",
      "observed": "1 upgrade of 6 asks in 90 days",
      "doc": "/plays/sso-rung#check-baseline",
      "fix": "n 6: it reads before-after, not proof, until volume allows a held-back half.",
      "then": "Metric.query"
    },
    {
      "check": "role-unstaffed",
      "status": "warn",
      "roles": [
        "success-manager",
        "sales-engineer"
      ],
      "owned": 4,
      "doc": "/plays/sso-rung#check-role-unstaffed",
      "fix": "Staff the CSM, or leave it: 4 Customers Priya owns get drafts in her queue.",
      "then": "Role.staff"
    }
  ]
}

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

CheckFix (one call)Your timeWait
use-when · billing-connected · pass: 6 asks in 90 days; Stripe connected (gaps #8)POST /{namespace}/metrics/query on tier-upgrade-rate; POST /{namespace}/integrations/connect for Stripe1 minnone
approved-pages · fail (Not live yet): no Page lists the $2,400 plan’s single sign-onPOST /{namespace}/sites/{site}/publish the pricing Page row10 minnone
baseline · warn: 1 of 6 in 90 daysPOST /{namespace}/metrics/query; it fills Before in Your number0 minnone
role-unstaffed · warn: 4 of your Customers have a person owner, PriyaPOST /{namespace}/roles/{role}/staff, or leave it: CSM routes come to you, and Priya’s 4 get drafts in her queue0 minnone

Your number · Before 17 per 100 · Now 63 per 100 asks upgraded · Target 50 by Dec 31 · before-after, not proof · n 8 matured

Each answer costs $0.04 from your Domain (Worker cost); POST /{namespace}/entitlements/check and a test connection cost nothing. That comes to about $0.16 a month at 4 asks and $0.08 at 2.

When it starts

WhenTrigger idStarts onWindowHow it gets in
A Customer or a Deal asks for single sign-on in writingsso-written-askevent on Message.received where intent = 'single-sign-on'answer within 1 business hour; 3dforward support@ to the address inbound-source printed, or POST /{namespace}/integrations/connect your inbox
An admin opens single sign-on setup on a plan without itsso-setup-refusedevent on Entitlement.checked where entitlement = 'single-sign-on' and allowed = false3dyour app calls POST /{namespace}/entitlements/check
A team on Team reaches 20 active membersseat-threshold-crossedthreshold on Tenant.thresholdCrossed where activeMembers >= 20 within 30da threshold; one note per 90 daysPOST /{namespace}/metrics/{metric}/watch on active members
+ 7 more for questionnaires, Quote requests, IT contacts, sign-in Domains, renewals, lost Deals and failing connections (?lanes=all)
One signed delivery · StartupBuilder-Signature
{
  "$id": "https://api.sb/leaseline.app/events/event_1288",
  "$type": "Event",
  "name": "Entitlement.checked",
  "at": "2026-10-19T10:22:31Z",
  "seq": 1288,
  "data": {
    "customer": "customer_33",
    "entitlement": "single-sign-on",
    "allowed": false,
    "offer": "team",
    "activeMembers": 22
  }
}
Reproduce it in test
npx startup-builder trigger Entitlement.checked --like event_1288   # replays the delivery
npx startup-builder clock advance --by 2d   # then runs the follow-up’s tested check
npx startup-builder listen Entitlement.checked --forward-to http://localhost:3000/hook

Who runs it

CSM · your agent (role:success-manager, worker_5) holds the Key Result. It hands questionnaires and Quotes to AE · Priya Shah (person) (role:sales-lead, worker_3), and held Customers to you (Dana Okafor, person, worker_1), because the CSM and Sales Engineer Roles have no person. Your number links to Did it work.

OptionRung todayEvidence (passed of n)Moves up atDrops back whenYou can
Answer with the plan · Set it up before they payIt does it, you can stop it6 of 6 · 3 of 3met on day 16 (the first 5 answers)any answer fails a Check, or the misquote Stop fires → You approve each onePOST /{namespace}/actions/{action}/cancel inside the hold
Note the plan at 20 membersYou approve each one1 of 1at 10 passed—POST /{namespace}/approvals/{approval}/approve · POST /{namespace}/approvals/{approval}/refuse
To the AE · Not nowIt does it1 of 1 · 1 of 1—a held Customer is asked anyway → You approve each onePOST /{namespace}/actions/{action}/redirect
Change the AE lineYou approve each one0 mergednever—POST /{namespace}/changes/{change}/merge · POST /{namespace}/changes/{change}/revert
Never: single sign-on turned on for them, a discount, a plan the Pricing Page lacksTo a person, every time1 asked, 1 handed overnever—POST /{namespace}/approvals/{approval}/approve on the AE’s Quote

What it reads · What it may call. It reads the ask, the Entitlement, the live Price and the active-member count, and quotes only the pricing Page. It opens a test connection; turning single sign-on on for members and POST /{namespace}/subscriptions/{subscription}/switch are the admin’s own presses, never the agent’s. Its tools are POST /{namespace}/entitlements/check, POST /{namespace}/conversations/{conversation}/answer, POST /{namespace}/sso-connections, POST /{namespace}/conversations/{conversation}/escalate, POST /{namespace}/quotes/{quote}/send, POST /{namespace}/tasks/{task}/assign, and any other call becomes an Approval under the Role’s Mandate.

The brief (folded): compiled Agent-register Markdown · play:sso-rung@1 · each line names its record key
You hold the CSM Key Result: 50 upgrades per 100 single sign-on asks by 2026-12-31. ← worker, metric
Answer each ask within 1 business hour with the plan that includes it, its live Price and today’s charge. ← chooses.answer-the-ask, Answer-time stop
At 50 seats, a questionnaire or a Quote on an open Deal, choose To the AE.       ← your file, line 4
Offer a test sign-in before any charge.                                          ← chooses.set-up-first, your file line 5
Never turn single sign-on on for a team; the admin does.                         ← Lockout stop

The slow loop. The weekly Decisions kept 50 seats as the AE line, and no Change was merged in the window, so there is no replay or read-back to print.

What it can do next

OptionPicked whenDecided byRunsHands toIf it’s just you
Answer with the plan answer-the-aska written ask from a Customer under 50 seatsYour rule (line 4)POST /{namespace}/entitlements/check → POST /{namespace}/conversations/{conversation}/answer → sso-ask-follow-upthe admin’s pressthe same
Set it up before they pay set-up-firstan admin opened setup, or asks to try it firstAgent’s call, with its reasonPOST /{namespace}/sso-connections (test only) → on press change-plan → sso-go-livethe admin’s test, then their pressthe same
To the AE to-the-aea questionnaire or Quote on an open Deal, 50 seats or more, or termsAgent’s call, with its reasonPOST /{namespace}/conversations/{conversation}/escalate → POST /{namespace}/quotes/{quote}/sendPOST /{namespace}/tasks/{task}/assign → AE · Priya Shah, due 60 min · Take this oneyou
Note the plan at 20 members note-the-plan20 active members or a verified sign-in Domain, with no askAgent’s call, with its reasonsso-proactive-note, one note in 90 daysnobodythe same
Not now not-nowanother Play holds them, or keep-first appliesYour rule (rule j)nothing; names the holdertheir CSM, so you · Take this oneyou
When they write backFixture replyWhat happensWho answersBy whenCall
Interested“Test passed. Move us to the annual plan.”the one-press link; nothing is charged until they pressthe Customer—POST /{namespace}/subscriptions/{subscription}/switch (theirs)
Send me pricing“What would the SSO plan cost us?”the live $2,400 Price, today’s $2,366.87 charge after the Team creditCSM · your agent5 minPOST /{namespace}/conversations/{conversation}/answer
Not now“Not until next budget year.”the ask closes, and customer-ask-cap frees the Customernobodyat onceGET /{namespace}/decisions
Wrong person“Our IT lead, Sam, sets this up.”asks them to bring Sam in; it never writes to an address from their textCSM · your agent1 business dayPOST /{namespace}/conversations/{conversation}/answer
Out of officean auto-reply until Oct 28the follow-up waits for the return datenobodythe return datePOST /{namespace}/messages/{message}/schedule
Question it can’t answer“Can we add SSO to Team for a fee?”To a person: a plan the Pricing Page lacks is never the agent’s callAE · Priya Shah, or you60 minPOST /{namespace}/conversations/{conversation}/escalate
Stop“Stop emailing us about plans.”notes stop; the test connection keeps workingnobodyat oncePOST /{namespace}/contacts/{contact}/suppress

When it hands to you

Questionnaires and Quotes go to AE · Priya Shah (person); held Customers come to you. One Brief per Role, as captured (brief is Not live yet, gaps #7).

What lands in each queue · sample
[
  {
    "$id": "https://api.sb/leaseline.app/tasks/task_506",
    "$type": "Task",
    "assignee": "worker_3",
    "due": "2026-10-16T16:05:00Z",
    "on": "contact_14",
    "brief": {
      "who": "Northgate Rentals, open Deal on the $2,400 plan",
      "said": "Item 14 of the security questionnaire: SAML single sign-on required.",
      "chose": "to-the-ae",
      "why": "a questionnaire on an open Deal is the AE’s",
      "answer": "the $2,400 plan includes SAML; the trust page link is attached",
      "never": [
        "a discount",
        "single sign-on on Team"
      ]
    }
  },
  {
    "$id": "https://api.sb/leaseline.app/tasks/task_489",
    "$type": "Task",
    "assignee": "worker_1",
    "due": "2026-10-09T17:00:00Z",
    "on": "customer_19",
    "brief": {
      "who": "Harbor Row",
      "said": "Do you have SSO?",
      "chose": "not-now",
      "why": "at risk since Oct 2: 3 support threads on late notices",
      "held": "keep-first"
    }
  }
]

The owner 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 a person claims, the agent’s pending answers to that Customer cancel with claimedByPerson (Not live yet, gaps #7), and every reply goes to the owner. A Task nobody claims by its due time goes up a Role through POST /{namespace}/tasks/{task}/escalate, and person-promise fires.

On time: 2 of 2 claimed within their due time, median 25 min, n 2, ■□□□ Too early to tell beside Other Startups’ 95 % on time. Your queue: in week 1, 4 approvals; after the promotion, about 1 hand-off every 2 weeks.

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)RefusesFixThen
owned-by-a-person (rule j, gaps #8)an answer to a Customer whose open Deal a person owns, or whose Conversation a person claimedLeave it to the person who owns it: the draft waits in their queue.POST /{namespace}/tasks/{task}/assign
keep-first (rule j, gaps #8)an upgrade answer to a Customer who is at risk, past due or has an unsubscribe pendingLet 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 Playsignal-expansion holds them until its seat note closes.GET /{namespace}/decisions
reconcile (the record’s Reconcile stop; Not live yet, gaps #8)a Customer whose Subscription and Stripe disagreeClear the Stripe mismatch first.POST /{namespace}/tasks/next
price (hub guard on POST /{namespace}/quotes/{quote}/send, gaps #1)a plan, Price or discount the pricing Page does not showQuote the plan that includes it, or get the discount approved.POST /{namespace}/approvals/{approval}/approve
Stop (pauses the Play)Pauses whenThen
misquotea Price, charge or Quote total differs from the live PriceYou approve each one
lockoutmembers cannot sign in after a switch, a switch down or a failed renewalsetups pause; POST /{namespace}/tasks/{task}/assign to you within 5 min
answer-timean ask waits past 1 business hour; 3 late in a week drop the answer lane one rungthe proactive lane pauses
test-failureunder half of setups pass a test sign-in within 7 days, after 20set-up-first pauses; failing identity systems are reported to you
spend-limitmonth-to-date model spend reaches its Limitasks get the plan answer by rule; POST /{namespace}/limits/{limit}/raise
kill-switchyou press itevery answer stops; active connections keep working
+ 6 more for the proactive lane (?lanes=all)

The captured refusal, then the Stop that fired as a Campaign.paused reason (Not live yet, gaps #2); the rewrite that sent is the Quarry Lane thread in Example.

422RefusedThe answer to Quarry Lane Homes did not send: it offers single sign-on on Team, which no live Offer shows.
CheckFixThen
price fail · Not live yet, gaps #1Quote the plan that includes it, or get the discount approved.POST /{namespace}/approvals/{approval}/approve
keep-first pass · Not live yet, gaps #8—POST /{namespace}/tasks/next
JSON
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "The answer to Quarry Lane Homes did not send: it offers single sign-on on Team, which no live Offer shows.",
  "checks": [
    {
      "check": "price",
      "status": "fail",
      "doc": "/plays/sso-rung#check-price",
      "fix": "Quote the plan that includes it, or get the discount approved.",
      "then": "Approval.approve"
    },
    {
      "check": "keep-first",
      "status": "pass"
    }
  ]
}

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

The Stops that fired, as Campaign.paused reasons · sample
[
  {
    "reason": {
      "limit": "answer-time",
      "observed": "1h 25m",
      "bound": "1 business hour",
      "window": "1 ask"
    },
    "doc": "/plays/sso-rung#stop-answer-time",
    "task": "task_377"
  }
]

Did it work

At 4 asks a month, no held-back half reads within 90 days, 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).

63 per 100 asks upgraded against 17 before · before-after, not proof · n 8 · path → arr

Chose
set-up-first
Why
Pinecrest’s admin opened single sign-on setup on Team; 22 active members is under the 50-seat line, so they test sign-in before paying
From
answer-the-ask · set-up-first · to-the-ae · note-the-plan · not-now
Expects
Subscription.switched to the annual plan within 60d
Reopens when
no Subscription.switched for customer_33 within 60d
By
worker_5
JSON
{
  "$id": "decisions/decision_347",
  "$type": "Decision",
  "choice": "set-up-first",
  "reason": "Pinecrest’s admin opened single sign-on setup on Team; 22 active members is under the 50-seat line, so they test sign-in before paying",
  "stakes": "low",
  "options": [
    "answer-the-ask",
    "set-up-first",
    "to-the-ae",
    "note-the-plan",
    "not-now"
  ],
  "by": "worker_5",
  "on": "customer_33",
  "expected": "Subscription.switched to the annual plan within 60d",
  "reopensWhen": "no Subscription.switched for customer_33 within 60d"
}
NodeNow (91 days)Before (the 90 days before)AddedConfidenceBasis
tier-upgrade-rate63 per 100: 5 of 8 matured asks upgraded within 60 days · 3 still maturing17 per 100: 1 of 6——before-after, not proof · Other Startups’ results +21 per 100, ■■■□ Likely, n 1,140
expansion-arr ↑$12,947, of it $8,688 from 6 upgrades · Booked: credited, not all caused by this Play$2,644— · Worth about +$1,200 a month—before-after; includes usage-upsell’s $2,392 and signal-expansion’s $1,867
net-new-arr · arrcarried from expansion-arrcarried——carried

Before against after reads the 91 days against the 90 before them; an ask counts once its 60 days have passed. It is not proof, and Other Startups’ results print beside it.

How it moves it: a median first answer of 6m 40s against 2 days 4 hours before, each naming the plan, its live Price and today’s charge, with a test sign-in before any charge.

Guardrails: before against after: contraction-arr, $0 from switches back to Team against $0 before, and logo-churn, 0 of 6 upgraded Customers gone; 6 of 6 upgraded teams had an active connection by day 14.

The Campaign card · sample
{
  "$id": "https://api.sb/leaseline.app/campaigns/sso-rung",
  "$type": "Campaign",
  "play": "play:sso-rung@1",
  "path": [
    "tier-upgrade-rate",
    "expansion-arr",
    "net-new-arr",
    "arr"
  ],
  "experiment": {
    "metric": "tier-upgrade-rate",
    "unit": "per-100",
    "heldBack": 0,
    "decision": null
  },
  "readout": {
    "value": null,
    "n": 8,
    "maturing": 3,
    "interval": null,
    "readability": "inadmissible",
    "basis": "before-after",
    "pooled": true
  },
  "ledger": {
    "spend": 1,
    "workerCost": 1,
    "hours": 0.9,
    "pipelineArr": 2393,
    "wonArr": 8688,
    "projectedArr": 1216,
    "paybackDays": 1
  }
}

Outside benchmark: 3.2 % of Subscriptions on a plan without single sign-on move to one with it in their fourth month (a subscription-analytics firm’s billing data, 2026-09-30).

Before it · After it. Before it: signal-expansion hands it a team that reaches 20 active members, and trust-pack hands it questionnaire items on open Deals. After it: written-references hears the Customers it upgraded, and annual-prepay already holds them on the annual plan; keep-first holds both while a Customer is at risk.

Example

Leaseline ran it from 2026-07-20 to 2026-10-19 (91 days): 11 asks and setups on 10 Customers and 1 Deal, 8 of them matured past their 60-day window. Read every captured thread at ?threads=all; three follow the tables.

What happened, by optionDecisionsUpgradedBooked (credited, not all caused by this Play)
Answer with the plan · Set it up before they pay6 · 33 · 3, with 3 test sign-ins passed$8,688
To the AE · Note the plan · Not now1 · 1 · 11 Quote open · 0 · 0$2,393 in an open Quote
At 2 a month (the Use it when volume)about 6 in 91 daysbefore-after, not proofOther Startups’ results: +21 per 100, ■■■□ Likely, n 1,140
DayEventWhat happenedYour time
0event_088 Campaign.createdthe three steps; dry run fails approved-pages10 min
0event_091 Site.publishedthe pricing Page row for the $2,400 plan10 min
9event_203 Subscription.switchedthe first upgrade paid: Juniper Homes, Team to the annual plan, +$1,448 ARR—
16event_301 Role.updatedpromoted: answers send after a 2-minute hold—
44event_655 Campaign.pausedanswer-time: an ask waited 1h 25m; you answered it and resumed10 min
58event_902 Action.refusedprice refused the Quarry Lane draft; rewritten once and sent5 min
1–91event_097 Approval.created, first of 5you approved 5 answers; weekly reviews, from the POST /{namespace}/tasks/next log20 min · total 55 min measured, 1 h asked

Leaseline → Pinecrest’s admin, Oct 19, 10:29 · Single sign-on comes with the $2,400-a-year plan, which also adds directory sync.¹ Switching today costs $2,366.87, after the $33.13 left on Team this month.² Test sign-in with your own accounts first; nothing is charged until you press Switch.³ *Signed with the Role’s disclosure line.*⁴

Pinecrest, Oct 19, 11:52 · test sign-in passed, then pressed Switch. Subscription.switched, +$1,448 ARR.

Quarry Lane Homes, 2026-09-16 · the draft price refused, then the rewrite that sent
- We can turn on SSO for you on Team at no extra cost for the first 3 months.
+ Single sign-on with your Google accounts comes with the $2,400-a-year plan; you can test sign-in before you pay.

Northgate Rentals, 2026-10-16 15:05 · questionnaire item 14: “SAML single sign-on required.” · Leaseline, 15:06 · *Thanks. Priya, your account lead, replies by 16:05 with the answer and the trust page.*⁵ The Brief went to Priya (task_506); she answered at 15:41.

¹ Only what the pricing Page lists for the plan. ² The live Price and today’s charge, after the Team credit. ³ The test sign-in before any charge. ⁴ The fixed signature line, compiled from the Role’s disclosure Setting. ⁵ The routed line, compiled from the Role’s Settings.

Your settings

plays/sso-rung.mdx
---
holdout: 0        # 4 asks a month is too few to hold any back; it reads before-after
---
Answer every single sign-on ask within the hour with the $2,400 plan. At 50 seats, a questionnaire or a Quote, bring in the AE.
Let the admin test sign-in before any charge.
Text
$ npx startup-builder show plays/sso-rung
holdout 0 · AE line 50 seats · test before charge     your file  plays/sso-rung.mdx:2,4,5 (Ask 2026-07-20)
family expansion · worker role:success-manager, owns never · chooses 5 (2 rule, 3 read) · sequences sso-ask-follow-up, sso-proactive-note, sso-go-live · checks owned-by-a-person, keep-first, customer-ask-cap, reconcile, price · stops 12 · placements gmail, outlook    catalog  play:sso-rung@1 (Not live yet, gaps #5)

Every key from the catalog

Key Id What it is
Tactic deal-requirement-intake Deal requirement intake extracts each stated requirement, with its source, from every buyer record on an open Deal for the Play that answers it. Starts at Sends nothing.
Tactic sso-ask-detect Single sign-on ask detect finds each request in Messages, transcripts, refused setups and Deal requirement rows, and keeps one ask record per Tenant or Deal. Starts at Sends nothing.
Tactic sso-offer-answer Single sign-on offer answer replies within one business hour with the SSO Offer, its live Price, today’s charge or a Quote, and a setup link. Starts at You approve each one.
Tactic sso-configure-first Single sign-on configure first lets an admin connect and test sign-in on a draft SSO Connection before paying, and activates it when the Entitlement arrives. Starts at Sends nothing.
Tactic sso-tier-change Single sign-on offer change moves a Subscription to the SSO Offer with proration, only on the Customer’s own press or signature. Starts at Sends nothing.
Tactic sso-proactive-rung Single sign-on proactive rung shows the SSO Offer to admins whose Tenant records show the need: one note in 90 days, with a holdout. Starts at You approve each one.
Tactic sso-rung-readout Single sign-on rung readout counts upgrades per ask over 60 days, reads the proactive holdout at 90 days, and recalibrates the seat threshold each quarter. Starts at You approve the first wave.
Tactic send-gate-check Send gate check: Checks Suppression, a live reason, the Market, the basis stamp, the Person-month grant, the facts and the labels before any cold Message exists. Starts at Sends nothing.
Tactic reply-matrix Reply matrix: Labels every outreach reply with one of 11 labels, maps it to one of seven reply kinds, and runs that kind’s move by its deadline. Starts at You approve each one.
Trigger sso-written-ask Single sign-on written ask: event on Message.received, window 3d.
Trigger sso-setup-refused Single sign-on setup refused: event on Entitlement.checked, window 3d.
Trigger sso-questionnaire-item Single sign-on questionnaire item: event on Message.received, window 14d.
Trigger sso-quote-request Single sign-on quote request: event on Quote.requested, window 24h.
Trigger it-contact-joined IT contact joined: event on Thread.joined, window 14d.
Trigger seat-threshold-crossed Seat threshold crossed: threshold on Tenant.thresholdCrossed, window 30d.
Trigger sign-in-domain-verified Sign-in domain verified: event on Domain.verified, window 14d.
Trigger sso-renewal-window Single sign-on renewal window: at on Renewal.opened, window 30d.
Trigger sso-objection-lost Single sign-on objection lost: event on Deal.lost, window 180d.
Trigger sso-connection-failing Single sign-on connection failing: state on SSOConnection.failed, window 24h.
Sequence sso-ask-follow-up Single sign-on ask follow-up: 5 steps; it ends on An upgrade to the SSO Offer; A signed Quote; A reply; A not-now; An opt-out; A lost Deal; The last note or the tested nudge sent; 14 days from the answer.
Sequence sso-proactive-note Single sign-on proactive note: 2 steps; it ends on An upgrade to the SSO Offer; An ask, which moves the Tenant to the ask follow-up; An opt-out; 90 days.
Sequence sso-go-live Single sign-on go-live: 3 steps; it ends on 3 people signed in through the connection; The Success Manager’s Task closed.
Benchmark sso-rung-month-one-upgrade Share of subscriptions moving to a higher Offer in their first month: 0.75 % (A subscription-analytics firm’s billing data, published in a pricing newsletter, 2026-09-30).
Benchmark sso-rung-month-four-upgrade Share of subscriptions moving to a higher Offer in their fourth month: 0.16 % (A subscription-analytics firm’s billing data, published in a pricing newsletter, 2026-09-30).
Benchmark sso-rung-renewal-upgrade-share Share of first-year Offer upgrades that land at the month-12 renewal: 40 % (A subscription-analytics firm’s billing data, published in a pricing newsletter, 2026-09-30).

Compiled, not written: edit the Play record sso-rung 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.