Skip to content

Sponsorships

Buys one coded placement in a newsletter, podcast or event your buyers follow, and rebooks a publisher only when its own codes pay back.

Channel
Ads and sponsorships
Run oneMode try
You, to your agent

Hand our latest open sponsor slot to the Marketing Lead agent and show me what it chose and why. Don’t send.

curl "https://api.sb/leaseline.app/events?where=name%20in%20(%22Publication.found%22%2C%20%22Slot.opened%22%2C%20%22Ad.published%22%2C%20%22Transaction.recorded%22%2C%20%22APIKey.activated%22%2C%20%22Schedule.fired%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_1308"}'

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

const { events: [last] } = await $.Event.list({ where: 'name in ("Publication.found", "Slot.opened", "Ad.published", "Transaction.recorded", "APIKey.activated", "Schedule.fired")', 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 (\"Publication.found\", \"Slot.opened\", \"Ad.published\", \"Transaction.recorded\", \"APIKey.activated\", \"Schedule.fired\")","limit":1}'
npx startup-builder do Trigger.fire --json '{"like":"event_1308"}' --try   # Not live yet (gaps #7)
npx startup-builder do Decision.list --json '{"where":"on = \"publisher_6\""}'   # Not live yet (gaps #7)
npx startup-builder do Action.list --json '{"where":"on = \"publisher_6\""}'   # Not live yet (gaps #7)
{
  "name": "do",
  "arguments": {
    "code": "const { events: [last] } = await $.Event.list({ where: 'name in (\"Publication.found\", \"Slot.opened\", \"Ad.published\", \"Transaction.recorded\", \"APIKey.activated\", \"Schedule.fired\")', 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_356",
    "$type": "Decision",
    "choice": "book-the-slot",
    "reason": "a regional landlord association newsletter your signups named 6 times: 9,400 subscribers, grade B audience evidence, a Nov 4 slot at $450, under your $1,000 Limit",
    "stakes": "high",
    "options": [
      "book-the-slot",
      "ask-for-evidence",
      "rebook",
      "retest-once",
      "drop-the-publisher",
      "event-table"
  …
sample · 4 Not live yetPreview

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

action_1 made the code and tested it end to end. action_2 is the $450 booking, which waits for your approval: nothing is spent until you approve.

24.4 incremental ICP visits per $100, against an uncoded 18 a day · before-after, not proof · n 4 placements · path → arr

Try another: the publisherChoiceReason
A regional landlord association newsletter: 9,400 subscribers, Nov 4 slot at $450book-the-slotgrade B evidence, under your Limit
A landlord podcast: a $600 host read, no audience numbersask-for-evidenceno evidence on a slot over $300
The property-manager newsletter’s second run: coded payback 5.3rebookover your 1.0 target
The same newsletter’s first run: coded payback 0.61retest-oncebetween 0.5 and 1.0, no retest yet
A property podcast’s run: 0 coded payments in 60 daysdrop-the-publisherpayback under 0.5
A county landlord meetup: a $150 tableevent-tableyour buyers attend; under your Limit

Where it sits: Stranger → Lead → Trialing → Activated → At risk → Churned → Won back · Placement ICP Visits per $100 → People reached → New Customers ↑ → ARR added each week → ARR

Worth’s formula: about +19 ICP visits per $100 (Other Startups’ results; no lift of your own yet) × $275 a month × 1.5 paid per 100 ICP visits × $876 first order ARR ≈ +$687. Under First signal: At about 1 placement a month, each reads on its own codes at day 60; no random comparison fits, so it reads before-after.

sample · api.sb/leaseline.app · 41 Customers at 2026-10-19 · on Slot.opened · first inquiry 14 min after the shortlist · 8 keys Not live yet

Start it this week

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

# 2 · dry run; below, its 422 on 2026-05-25
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":"sponsorships"}'

# 3 · keep it; every booking waits for your approval
curl -X POST https://api.sb/leaseline.app/campaigns \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"play":"sponsorships"}'

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

# off: no inquiry or booking; booked placements still run
curl -X PATCH https://api.sb/leaseline.app/campaigns/sponsorships \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"endsAt":"now"}'
422Refusedsponsorships can’t start yet: 1 check fails and 2 warn.
CheckFixThen
use-when pass · Not live yet, gaps #8Nothing to fix: $250 or more a month, and publications your buyers name.POST /{namespace}/metrics/query
domain-authenticated passNothing to fix: inquiries send from your Domain.POST /{namespace}/domains/{domain}/authenticate
approved-pages fail · Not live yet, gaps #8Publish the placement landing Page; host reads quote only your approved pages.POST /{namespace}/sites/{site}/publish
baseline warn · Not live yet, gaps #8n 0 placements: each one reads against your uncoded 18 a day, not proof.POST /{namespace}/metrics/query
role-unstaffed warn · Not live yet, gaps #8Staff paid media, or leave it: every booking comes to you to approve.POST /{namespace}/roles/{role}/staff
JSON
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "sponsorships can’t start yet: 1 check fails and 2 warn.",
  "checks": [
    {
      "check": "use-when",
      "status": "pass",
      "observed": "a $1,000 monthly Limit; 3 publications your signups named",
      "doc": "/plays/sponsorships#check-use-when",
      "fix": "Nothing to fix: $250 or more a month, and publications your buyers name.",
      "then": "Metric.query"
    },
    {
      "check": "domain-authenticated",
      "status": "pass",
      "observed": "leaseline.app, 3 records resolve",
      "doc": "/plays/sponsorships#check-domain-authenticated",
      "fix": "Nothing to fix: inquiries send from your Domain.",
      "then": "Domain.authenticate"
    },
    {
      "check": "approved-pages",
      "status": "fail",
      "observed": "no landing Page for a placement code; no approved lines for a host read",
      "doc": "/plays/sponsorships#check-approved-pages",
      "fix": "Publish the placement landing Page; host reads quote only your approved pages.",
      "then": "Site.publish"
    },
    {
      "check": "baseline",
      "status": "warn",
      "observed": "18 ICP visits a day, no placements in 90 days",
      "doc": "/plays/sponsorships#check-baseline",
      "fix": "n 0 placements: each one reads against your uncoded 18 a day, not proof.",
      "then": "Metric.query"
    },
    {
      "check": "role-unstaffed",
      "status": "warn",
      "roles": [
        "paid-media-manager",
        "partner-manager"
      ],
      "owned": 0,
      "doc": "/plays/sponsorships#check-role-unstaffed",
      "fix": "Staff paid media, or leave it: every booking comes to you to approve.",
      "then": "Role.staff"
    }
  ]
}

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

CheckFix (one call)Your timeWait
use-when · domain-authenticated · pass: a $1,000 Limit and 3 named publications; the Domain resolves (gaps #8)POST /{namespace}/metrics/query on placement-icp-visits-per-100; POST /{namespace}/domains/{domain}/authenticate1 minnone
approved-pages · fail (Not live yet): no placement landing PagePOST /{namespace}/sites/{site}/publish the landing Page each code points to20 minnone
baseline · warn: 18 ICP visits a day, no placementsPOST /{namespace}/metrics/query; it fills Before in Your number0 minnone
role-unstaffed · warn: no person runs paid media or partnershipsPOST /{namespace}/roles/{role}/staff, or leave it: every booking comes to you0 minnone

Your number · Before 0 placements · Now 24.4 incremental ICP visits per $100 · Target 20 per $100 and payback 1.0 by Dec 31 · before-after against the uncoded baseline, not proof · n 4 placements

Each placement costs its slot price, $150 to $450 here, under your $1,000 monthly Limit; the shortlist, evidence checks and codes cost about $0.40 a placement (Worker cost). That came to $1,350 over 147 days, about $275 a month.

When it starts

WhenTrigger idStarts onWindowHow it gets in
A shortlisted publisher offers a dated, priced slotplacement-slot-openevent on Slot.opened where publisher on the shortlist and price set14d; one inquiry per slotforward the publisher’s email to the address inbound-source printed
A booked placement goes liveplacement-ranevent on Ad.published where placement code setreads its code for 60 daysthe publisher’s link carries the code; POST /{namespace}/events/capture from your landing Page
A first payment carries a placement’s codecoded-first-transactionevent on Transaction.recorded where code in placement codes and first = true60d after the runPOST /{namespace}/integrations/connect (Stripe)
+ 5 more for found publications, borrowed slots, event packages, event keys and closed read windows (?lanes=all)
One signed delivery · StartupBuilder-Signature
{
  "$id": "https://api.sb/leaseline.app/events/event_1308",
  "$type": "Event",
  "name": "Slot.opened",
  "at": "2026-10-19T11:05:37Z",
  "seq": 1308,
  "data": {
    "publisher": "publisher_6",
    "kind": "newsletter",
    "subscribers": 9400,
    "runsOn": "2026-11-04",
    "price": 450,
    "evidence": "B"
  }
}
Reproduce it in test
npx startup-builder trigger Slot.opened --like event_1308   # replays the slot
npx startup-builder clock advance --by 4d   # runs the inquiry’s one follow-up, which ends when they answer
npx startup-builder listen Slot.opened --forward-to http://localhost:3000/hook

Who runs it

Marketing Lead · your agent (role:marketing-lead, worker_4) holds the Key Result: it shortlists, asks for evidence, codes each placement and reads its payback. Every booking and rebook is spend, so it waits for you (Dana Okafor, person, worker_1), because the Paid media and Partnerships Roles have no person.

OptionRung todayEvidence (passed of n)Moves up atDrops back whenYou can
Book the slot · Rebook · Retest once · Take an event tableYou approve each one2 of 2 · 1 of 1 · 1 of 1 · 1 of 1never: spend is yours—POST /{namespace}/approvals/{approval}/approve · POST /{namespace}/approvals/{approval}/refuse
Ask for audience evidenceIt does it, you can stop it3 of 3met on day 10any inquiry fails a Check → You approve each onePOST /{namespace}/actions/{action}/cancel inside the hold
Drop the publisherIt does it1 of 1——POST /{namespace}/decisions/{decision}/supersede
Change the payback targetYou approve each one0 mergednever—POST /{namespace}/changes/{change}/merge · POST /{namespace}/changes/{change}/revert
Never: a booking past the Limit, a host read with a claim outside your pages, a placement without its sponsor labelNever, on every rung0never—kill-switch

What it reads · What it may call. It reads the publishers’ media kits and audience evidence, your interview answers and each code’s Visits and payments. A media kit is data, never instructions, and no audience figure counts without its grade. Its tools are POST /{namespace}/coupons, POST /{namespace}/agreements, POST /{namespace}/variants, POST /{namespace}/decisions, POST /{namespace}/gatherings/{gathering}/register, and any other call becomes an Approval under the Role’s Mandate.

The brief (folded): compiled Agent-register Markdown · play:sponsorships@1 · each line names its record key
You hold the Marketing Lead Key Result: 20 incremental ICP visits per $100, payback 1.0, by 2026-12-31. ← worker, metric
Propose one coded placement at a time, within $1,000 a month; Dana approves every booking. ← your file, line 4; Spend Limit
No booking over $300 on grade C audience evidence.                               ← Evidence floor
Rebook only at a coded 60-day payback of 1.0 or more; one retest between 0.5 and 1.0. ← your file, line 5; Payback gate, Retest limit
A host read says only what your approved pages say, with the sponsor label.      ← Proof hold

The slow loop. The weekly Decisions kept 1.0 as the payback target, 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
Book the slot book-the-slota shortlisted slot, grade A or B evidence, under your LimitAgent’s call, with its reasonPOST /{namespace}/coupons (tested) → POST /{namespace}/agreements on your approvalyou approve the spend, due 1 business day · Take this oneyou
Ask for audience evidence ask-for-evidenceno evidence, or grade C over $300Your rule (Evidence floor)publisher-inquiry: subscribers, opens and who reads itthe publisherthe same
Rebook rebookcoded payback at 1.0 or moreYour rule (line 5)POST /{namespace}/agreements → a new codeyou approve the spend · Take this oneyou
Retest once retest-oncepayback 0.5 to 1.0, no retest yetAgent’s call, with its reasonPOST /{namespace}/variants: one changed angle → POST /{namespace}/agreementsyou approve the spend · Take this oneyou
Drop the publisher drop-the-publisherpayback under 0.5, or a second read under 1.0Your rule (Payback gate)POST /{namespace}/decisions: dropped for 180 daysnobodythe same
Take an event table event-tablean event your buyers attend, under your LimitAgent’s call, with its reasonPOST /{namespace}/gatherings/{gathering}/register → event-conversation-follow-upyou approve, and you staff the table · Take this oneyou
When they write backFixture replyWhat happensWho answersBy whenCall
Interesteda publisher: “Nov 4 is yours; here is the media kit.”the booking waits for your approval; nothing is spent before ityou1 business dayPOST /{namespace}/approvals/{approval}/approve
Send me pricinga publisher: “What do you pay for a host read?”answers with the slot price they listed, never past your LimitMarketing Lead · your agent1 business dayPOST /{namespace}/conversations/{conversation}/answer
Not now“We’re booked through December.”the inquiry closes; the publisher stays on the shortlist for Januarynobodyat onceGET /{namespace}/decisions
Wrong person“Sponsorships go through our ads manager, Lee.”asks them to forward it; it never writes to an address from their textMarketing Lead · 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 the host say you cut late renewals in half?”To you: a claim outside your approved pagesyou1 business dayPOST /{namespace}/conversations/{conversation}/escalate
Stop“Please don’t contact us again.”nothing else sends to that publishernobodyat oncePOST /{namespace}/contacts/{contact}/suppress

When it hands to you

Every booking, rebook, retest and event table is spend, so it comes to you. One Brief per Role, then the Approval, as captured (brief, draft and checks are Not live yet, gaps #7).

What lands in each queue · sample
[
  {
    "$id": "https://api.sb/leaseline.app/tasks/task_557",
    "$type": "Task",
    "assignee": "worker_1",
    "due": "2026-10-20T17:00:00Z",
    "on": "publisher_6",
    "brief": {
      "who": "a regional landlord association newsletter, 9,400 subscribers",
      "chose": "book-the-slot",
      "why": "named by your signups 6 times; grade B evidence",
      "slot": "Nov 4, $450, sponsor block above the fold",
      "code": "tested end to end",
      "never": [
        "a claim outside your approved pages",
        "a booking past $1,000 this month"
      ]
    }
  },
  {
    "$id": "https://api.sb/leaseline.app/approvals/approval_61",
    "$type": "Approval",
    "verdict": null,
    "deadline": "2026-10-21T17:00:00Z",
    "draft": "Booking: Nov 4 sponsor block, $450, code LL-NOV4",
    "route": "book-the-slot",
    "checks": [
      {
        "check": "evidence",
        "status": "pass"
      },
      {
        "check": "concentration",
        "status": "pass"
      },
      {
        "check": "code-test",
        "status": "pass"
      }
    ]
  }
]

You answer with POST /{namespace}/approvals/{approval}/approve or POST /{namespace}/approvals/{approval}/refuse, or take the Task with POST /{namespace}/tasks/{task}/claim (Take this one) or hand it back with POST /{namespace}/tasks/{task}/return, each a one-call window. An Approval unanswered by its deadline expires, and the slot is released.

On time: you, 5 of 5 bookings answered within 1 business day, median 4 h, n 5, ■□□□ Too early to tell. Your queue: in week 1, the shortlist and 3 evidence asks; then about 1 booking to approve 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 inquiry to a publisher contact 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
evidence (the record’s Evidence floor)a booking over $300 on grade C audience evidenceAsk the publisher for subscriber and open numbers first.POST /{namespace}/messages/{message}/schedule
borrowed-first (the record’s Borrowed-first gate)a paid booking before 2 borrowed placements read, or a recorded noRecord that none of your other Startups reaches these buyers.POST /{namespace}/decisions
concentration (the record’s Concentration cap)one publisher over 50 % of a month’s paid budget before it paid back onceBook another publisher, or wait for its payback read.GET /{namespace}/decisions
code-test (the record’s Code hold)a run whose code fails its end-to-end test 24 hours beforeFix the code; the run date moves.POST /{namespace}/coupons
proof (the record’s Proof hold)copy or a recording with a claim outside your pages, or no sponsor labelCut the claim, or add the label; it holds until corrected.POST /{namespace}/content/draft
Stop (pauses the Play)Pauses whenThen
paybacka placement’s coded 60-day payback under 0.5its publisher drops for 180 days
retesta second read in the 0.5 to 1.0 bandthe publisher drops
paid-arm4 dropped placements in a rowpaid bookings pause until a Decision names a new Offer, angle or buyer
spend-limitcommitted spend reaches the month’s Limitno new booking until the month turns; POST /{namespace}/limits/{limit}/raise
deliverydelivery under 70 % of the Agreementthe make-good is claimed; no rebook until it runs
decay2 rebooks in a row under 60 % of the first paybackthe publisher rests 90 days
kill-switchyou press itevery inquiry and booking stops; unpaid bookings hold
+ 1 more for the event lane (?lanes=all)

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

422RefusedThe host-read brief for the property podcast did not send: it says Leaseline cuts late renewals in half, which no approved page says.
CheckFixThen
proof failCut the claim, or add the label; it holds until corrected.POST /{namespace}/content/draft
code-test pass—POST /{namespace}/events/capture
JSON
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "The host-read brief for the property podcast did not send: it says Leaseline cuts late renewals in half, which no approved page says.",
  "checks": [
    {
      "check": "proof",
      "status": "fail",
      "doc": "/plays/sponsorships#check-proof",
      "fix": "Cut the claim, or add the label; it holds until corrected.",
      "then": "Content.draft"
    },
    {
      "check": "code-test",
      "status": "pass"
    }
  ]
}

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

The Stops that fired, as Campaign.paused reasons · sample
[
  {
    "reason": {
      "limit": "payback",
      "observed": "0 coded payments in 60 days on $300",
      "bound": "0.5",
      "window": "60d"
    },
    "doc": "/plays/sponsorships#stop-payback",
    "task": "task_472"
  }
]

Did it work

Each placement reads against your uncoded baseline, and 2 placements a month cannot hold a random comparison, so the basis is before-after (rule o): 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).

24.4 incremental ICP visits per $100, against an uncoded 18 a day · before-after, not proof · n 4 placements · path → arr

Chose
book-the-slot
Why
a regional landlord association newsletter your signups named 6 times: 9,400 subscribers, grade B audience evidence, a Nov 4 slot at $450, under your $1,000 Limit
From
book-the-slot · ask-for-evidence · rebook · retest-once · drop-the-publisher · event-table
Expects
coded 60-day payback of 1.0 or more by 2027-01-03
Reopens when
the placement’s code shows no Visit within 3d of its run date
By
worker_4
JSON
{
  "$id": "decisions/decision_356",
  "$type": "Decision",
  "choice": "book-the-slot",
  "reason": "a regional landlord association newsletter your signups named 6 times: 9,400 subscribers, grade B audience evidence, a Nov 4 slot at $450, under your $1,000 Limit",
  "stakes": "high",
  "options": [
    "book-the-slot",
    "ask-for-evidence",
    "rebook",
    "retest-once",
    "drop-the-publisher",
    "event-table"
  ],
  "by": "worker_4",
  "on": "publisher_6",
  "expected": "coded 60-day payback of 1.0 or more by 2027-01-03",
  "reopensWhen": "the placement’s code shows no Visit within 3d of its run date"
}
NodeNow (147 days)Before (the 147 days before)AddedConfidenceBasis
placement-icp-visits-per-10024.4 per $100: 330 ICP visits over the uncoded baseline, from 4 placements costing $1,350no placements; 18 ICP visits a day uncoded——before-after against the uncoded baseline, not proof · Other Startups’ results +19 per $100, ■■■□ Likely, n 410 placements
icp-reached2,976 ICP visits2,646——before-after
new-arr ↑$4,379, 5 coded Customers · Booked: credited, not all caused by this Play$0 coded— · Worth about +$690 a month—before-after · 1 coded trial still deciding
net-new-arr · arrcarried from new-arrcarried——carried

The leaf counts ICP visits a coded placement brings over the uncoded daily baseline, per $100 of its full cost, over its 14-day window; payback reads the coded revenue at 60 days. Before against after is not proof, and Other Startups’ results print beside it.

How it moves it: property managers meet Leaseline inside a newsletter they already read, through a code that ties each visit and payment to that one placement.

Guardrails: by placement, coded 60-day payback: 0.61, 0 (dropped), 5.3 and 0.39 against the 0.5 floor; one publisher held 33 % of paid spend against the 50 % cap; $1,350 spent over five months, never past the $1,000 monthly Limit.

The Campaign card · sample
{
  "$id": "https://api.sb/leaseline.app/campaigns/sponsorships",
  "$type": "Campaign",
  "play": "play:sponsorships@1",
  "path": [
    "placement-icp-visits-per-100",
    "icp-reached",
    "new-arr",
    "net-new-arr",
    "arr"
  ],
  "experiment": {
    "metric": "placement-icp-visits-per-100",
    "unit": "per-100-usd",
    "heldBack": 0,
    "decision": null
  },
  "readout": {
    "value": null,
    "n": 4,
    "maturing": 1,
    "interval": null,
    "readability": "inadmissible",
    "basis": "before-after",
    "pooled": true
  },
  "ledger": {
    "spend": 1350,
    "workerCost": 2,
    "hours": 2.6,
    "pipelineArr": 347,
    "wonArr": 4379,
    "projectedArr": 687,
    "paybackDays": 41
  }
}

Outside benchmark: a newsletter sponsor slot to business readers brings a median of 0.6 clicks per 100 subscribers (a newsletter platform’s study of 18,000 sponsored issues, 2026-05-31).

Before it · After it. Before it: signup-interviews names the publications your buyers read. After it: instant-response answers the coded visitors who write in, signup-interviews hears the ones who join the Waitlist, and promote-winners hears a host read that pays back.

Example

Leaseline ran it from 2026-05-25 to 2026-10-19 (147 days), long enough for each placement’s 60-day read: 4 placements ran for $1,350, 3 publishers sent audience evidence, 1 was dropped, and 1 slot waits for your approval. Read every captured thread at ?threads=all; three follow the tables.

What happened, by optionDecisionsRanCoded Customers (credited, not all caused by this Play)
Book the slot2the property-manager newsletter, $450 (payback 0.61) · the property podcast, $300 (payback 0)2 on Pro, 1 on Team (+$1,639 ARR)
Retest once · Rebook1 · 1the newsletter again, $450, a new angle (payback 5.3) · Nov 4 booked1 on the $2,400 plan (+$2,393 ARR)
Take an event table · Ask for audience evidence · Drop the publisher1 · 3 · 1a $150 table, 6 conversations (payback 0.39) · 2 sent grade B, 1 grade C · the podcast, 180 days1 on Pro (+$347 ARR)
At $250 a month (the Use it when volume)about 1 placement a monthbefore-after, not proofOther Startups’ results: +19 per $100, ■■■□ Likely, n 410 placements
DayEventWhat happenedYour time
0event_119 Campaign.createdthe three steps; dry run fails approved-pages10 min
0event_125 Site.publishedthe placement landing Page; a recorded no for borrowed slots20 min
12event_066 Transaction.recordedthe first coded payment: Pro, code LL-JUN2—
20event_081 Action.refusedproof refused the podcast host read; rewritten once and run on Jun 165 min
69event_388 Approval.approvedyou approved the newsletter retest with one changed angle5 min
82event_452 Campaign.pausedpayback: the podcast at 0; dropped for 180 days—
131event_1101 Readout.createdthe retest reads 5.3 at day 60; you approved the rebook5 min
1–147event_031 Approval.created, first of 5you approved 5 bookings; weekly reviews, from the POST /{namespace}/tasks/next log2 h · total 2.6 h measured, 2.8 h asked

The newsletter’s retest, Aug 4 · sponsor block: “Renewal notices for every owner, 60 days out. Leaseline, $29 a month.” with code LL-AUG4 and the sponsor label.¹

Aug 9, 14:10 · Pinehurst Management paid for the $2,400 plan with code LL-AUG4. Transaction.recorded, +$2,393 ARR; the placement’s coded payback read 5.3 at day 60, on Oct 3.²

The property podcast, 2026-06-14 · the host-read brief proof refused, then the rewrite that ran
- Leaseline cuts late renewals in half for property managers.
+ Leaseline sends every renewal notice 60 days out, per owner, for $29 a month. Sponsored.

The Nov 4 slot, 2026-10-19 11:20 · the booking reached you as approval_61, $450, code tested, with its Brief (task_557); it waits for your approval by Oct 21 17:00 (When it hands to you).

¹ Only lines from your approved pages, with the sponsor label. ² Payback reads the coded revenue over the placement’s full cost.

Your settings

plays/sponsorships.mdx
---
holdout: 0        # each placement reads on its own code; it reads before-after
---
Propose one coded placement at a time, up to $1,000 a month. I approve every booking.
Rebook at a coded 60-day payback of 1.0 or more; retest once between 0.5 and 1.0.
Text
$ npx startup-builder show plays/sponsorships
holdout 0 · Limit $1,000 a month · payback target 1.0     your file  plays/sponsorships.mdx:2,4,5 (Ask 2026-05-25)
family demand · worker role:marketing-lead, owns never · chooses 6 (3 rule, 3 read) · sequences publisher-inquiry, hackathon-builder-follow-up, event-conversation-follow-up · checks owned-by-a-person, evidence, borrowed-first, concentration, code-test, proof · stops 8 · placements portfolio-network, gmail, outlook, yahoo-mail, youtube, github    catalog  play:sponsorships@1 (Not live yet, gaps #5)

Every key from the catalog

KeyIdWhat it is
Tacticborrowed-placement-firstBorrowed placement first runs free slots in your other Startups’ publications, split against a random holdout, before the Play books any paid placement. Starts at You approve each one.
Tacticpublication-shortlistPublication shortlist keeps the 15 newsletters, podcasts, channels and events the ICP reads, ranked weekly from the Startup’s own records and public output. Starts at Sends nothing.
Tacticaudience-evidence-checkAudience evidence check grades what a publisher holds about its own audience and turns it into a maximum fee the booking may not exceed. Starts at You approve each one.
Tacticplacement-bookingPlacement booking negotiates a slot to the maximum fee, checks it against the Limit and the concentration cap, and signs the Agreement. Starts at You approve each one.
Tacticplacement-codePlacement code gives each placement a vanity Page, a Stripe promotion code and, for events, an API Key prefix, each tested before it runs. Starts at Sends nothing.
Tactichost-read-briefHost read brief turns the claims source into talking points a host reads in their own words, and proofs the final copy before it runs. Starts at You approve the first wave.
Tacticplacement-payback-gatePlacement payback gate reads each placement’s coded collected revenue against its full cost at 14 and 60 days, and rebooks, retests or drops the publisher. Starts at Sends nothing.
Tacticevent-sponsorshipEvent sponsorship buys a sponsor slot at another host’s event, staffs it with a named Human, and reads Meetings and activated API Keys before payback. Starts at You approve each one.
Triggericp-publication-foundICP publication found: event on Publication.found, window 90d.
Triggerborrowed-slot-openBorrowed slot open: event on Slot.opened, window 21d.
Triggerplacement-slot-openPlacement slot open: event on Slot.opened, window 14d.
Triggerevent-sponsor-openEvent sponsor open: event on Slot.opened, window 21d.
Triggerplacement-ranPlacement ran: event on Ad.published, window 60d.
Triggercoded-first-transactionCoded first transaction: event on Transaction.recorded, window 60d.
Triggerevent-key-activatedEvent key activated: threshold on APIKey.activated, window 14d.
Triggerplacement-window-closedPlacement window closed: at on Schedule.fired, window 14d.
Sequencepublisher-inquiryPublisher inquiry: 2 steps; it ends on A reply.; A decline.; No reply 4 days after the follow-up..
Sequencehackathon-builder-follow-upHackathon builder follow-up: 5 steps; it ends on A reply.; A booked Meeting.; A first paid Transaction.; An opt-out..
Sequenceevent-conversation-follow-upEvent conversation follow-up: 4 steps; it ends on A reply.; A booked Meeting.; An opt-out..

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