Skip to content

The funnels/ folder: one file and what it compiles to

What one funnels/ file holds, what each key compiles to, and the checks that read it.

One funnels/ file is one funnel, and the question that asks each new Lead where they heard of you. SalesBuilder compiles it, and show traces every key.

funnels/signup.mdx
---
steps: [visit, signup, trial, paid]
heardFrom: { ask: "How did you hear about Leaseline?", options: [search, ai-answer, newsletter, a-friend, other] }
---
The Pro signup, from the pricing Page to the first paid month.
show
$ npx startup-builder show funnels/signup.mdx
steps      [visit, signup, trial, paid]                                              funnels/signup.mdx:2
heardFrom  { ask: "How did you hear about Leaseline?", options: [search, ai-answer…  funnels/signup.mdx:3
owner      SalesBuilder
leaseline.app
leaseline.app/
├── plays/
│   ├── cold-email.mdx
│   ├── warm-intros.mdx
│   ├── signup-interviews.mdx
│   ├── lead-reactivation.mdx
│   └── events-and-webinars.mdx
├── audiences/
│   ├── small-property-managers.mdx
│   ├── lapsed-leads.mdx
│   └── renewal-season.mdx
├── sequences/
│   └── cold-email-thread-founder.mdx
├── funnels/   ← this folder
│   └── signup.mdx
├── workflows/
│   └── outbound.mdx
├── agents/
│   ├── sales/prospector.mdx
│   └── marketing/content-lead.mdx
├── systems/
│   └── sequences.mdx
├── domains/
│   └── leaseline.app.mdx
├── offers/
│   ├── pro.mdx
│   └── team.mdx
├── content/
│   └── webinars/60-day-notices.mdx
├── metrics/
│   ├── q4.mdx
│   └── positive-reply-rate.mdx
└── startups.lock

The file

KeyOn the pageCompiles toChecked by
stepsStepsthe funnel’s steps, each a conversion with n—
heardFromHow they heardone question on signup; each answer records an Acquisition the credit reads (GET /{namespace}/acquisitions)—

Refusals

CodeFix, then the call that clears it
clusterOffer the plain trial; the account keeps every other term. Then POST /{namespace}/offers/{offer}/trial.

Calls

funnels/ compiledMode try
You, to your agent

Create our signup flow, then show where new people heard of us.

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

curl "https://api.sb/leaseline.app/acquisitions?limit=20" \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"
import { $ } from 'startup-builder'

await $.Funnel.create({ steps: {} }, { mode: 'try' })   // funnels/signup.mdx
return await $.Acquisition.list({ limit: 20 })   // heardFrom writes one per signup
npx startup-builder do Funnel.create --json '{"steps":{}}' --try
npx startup-builder do Acquisition.list --json '{"limit":20}'
{
  "name": "do",
  "arguments": {
    "code": "await $.Funnel.create({ steps: {} }, { mode: 'try' })   // funnels/signup.mdx\nreturn await $.Acquisition.list({ limit: 20 })   // heardFrom writes one per signup",
    "mode": "try"
  }
}
Response200application/json
{
  "$type": "Acquisition",
  "acquisitions": [
    {
      "$id": "https://api.sb/leaseline.app/acquisitions/acquisition_1",
      "$type": "Acquisition",
      "kind": "search",
      "at": "2026-10-22T12:00:00Z"
    }
  ],
  "meta": {
    "limit": 20,
    "after": "cursor_2"
  }
}
samplePreview
CallWhat it does
POST /{namespace}/leads/{lead}/convertConvert ends a qualified Lead’s pursuit as a Lead: it opens a Deal or routes the Lead to self-serve checkout. Emits Lead.converted.
POST /{namespace}/offers/{offer}/trialTrial starts a Customer on an Offer free for a set number of days, with or without a card, converting or ending by its terms. Emits Offer.trialed.
POST /{namespace}/orders/placePlace commits a Customer to buy an Offer once and records the Offer Version and price at that moment. Emits Order.placed.

Compiled, not written: edit the records it reads (compile table; cap), 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