Skip to content

Creator ads

Runs a creator’s winning post, unedited, as a labeled paid Ad under the rights in their Agreement, and measures it against regions held back.

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

Hand Jess’s latest post to the paid media agent and show me what it chose and why. Don’t spend.

curl "https://api.sb/leaseline.app/events?where=name%20in%20(%22Post.published%22%2C%20%22Post.edited%22%2C%20%22Mandate.revoked%22%2C%20%22Monitor.checked%22%2C%20%22Ad.rejected%22%2C%20%22Experiment.matured%22%2C%20%22Offer.repriced%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_1219"}'

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

const { events: [last] } = await $.Event.list({ where: 'name in ("Post.published", "Post.edited", "Mandate.revoked", "Monitor.checked", "Ad.rejected", "Experiment.matured", "Offer.repriced")', 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 (\"Post.published\", \"Post.edited\", \"Mandate.revoked\", \"Monitor.checked\", \"Ad.rejected\", \"Experiment.matured\", \"Offer.repriced\")","limit":1}'
npx startup-builder do Trigger.fire --json '{"like":"event_1219"}' --try   # Not live yet (gaps #7)
npx startup-builder do Decision.list --json '{"where":"on = \"post_377\""}'   # Not live yet (gaps #7)
npx startup-builder do Action.list --json '{"where":"on = \"post_377\""}'   # Not live yet (gaps #7)
{
  "name": "do",
  "arguments": {
    "code": "const { events: [last] } = await $.Event.list({ where: 'name in (\"Post.published\", \"Post.edited\", \"Mandate.revoked\", \"Monitor.checked\", \"Ad.rejected\", \"Experiment.matured\", \"Offer.repriced\")', 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_642",
    "$type": "Decision",
    "choice": "promote-the-post",
    "reason": "Jess’s Oct 10 post on 60-day renewal notices held viewers 2.1 times her median; her Agreement grants 90 days of rights, and the screen passed",
    "stakes": "medium",
    "options": [
      "promote-the-post",
      "ask-for-rights",
      "keep-it-organic"
    ],
    "by": "worker_11",
    "on": "post_377",
  …
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 builds the partnership Ad from the archived post, with enhancements off. action_2 asks you to approve it in the Venue’s ad manager; nothing spends until you do.

+4.0 Leads per $100 · ■■□□ Early sign · 40 regions · path → arr

Try another: the creator postChoiceReason
Jess Moreno, Oct 10: “How I send renewal notices 60 days out,” 2.1× her median holdpromote-the-postbeat her median; rights granted; the screen passed
Jess Moreno, Sep 2: a post that beat her median, under an Agreement with no rights clauseask-for-rightsno rights yet: the Agreement summary goes to her
Jess Moreno, Sep 28: a post at 0.8× her mediankeep-it-organicunder her median: it stays organic

Where it sits: Stranger → Lead → Trialing → Activated → At risk → Churned → Won back · Creator ad lead lift → New Leads → New Customers ↑ → ARR added each week → ARR

Worth’s formula: about +4.0 Leads per $100 × $600 a month ÷ $100 × 0.06 Leads to paid × $348 first order ARR ≈ +$501. Under First signal: A 28-day geo holdout reads once; two windows tell a +3 per $100 lift at $600 a month.

sample · api.sb/leaseline.app · 41 Customers at 2026-10-19 · on Post.published · first screen verdict 72 h after the post · 9 keys Not live yet

Runs inside: Promote winners, as one of its options; this page keeps its own record and URL.

Start it this week

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

# 2 · dry run; below, its 422 on 2026-08-24
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":"creator-ads"}'

# 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":"creator-ads"}'

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

# off: every creator Ad pauses; the posts stay organic
curl -X PATCH https://api.sb/leaseline.app/campaigns/creator-ads \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"endsAt":"now"}'
422Refusedcreator-ads can’t start yet: 1 check fails and 2 warn.
CheckFixThen
use-when pass · Not live yet, gaps #81 creator under Agreement; $600 a month LimitPOST /{namespace}/metrics/query
baseline warn · Not live yet, gaps #8The held-back regions become the comparison; the first window reads at 28 days.POST /{namespace}/metrics/query
approved-pages fail · Not live yet, gaps #8Publish the landing Page the Ad links to, with the live Price.POST /{namespace}/sites/{site}/publish
role-unstaffed warn · Not live yet, gaps #8Leave them: the rights Agreement and each Ad come to you.POST /{namespace}/roles/{role}/staff
JSON
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "creator-ads can’t start yet: 1 check fails and 2 warn.",
  "checks": [
    {
      "check": "use-when",
      "status": "pass",
      "observed": "1 creator under Agreement; $600 a month Limit",
      "doc": "/plays/creator-ads#check-use-when",
      "then": "Metric.query"
    },
    {
      "check": "baseline",
      "status": "warn",
      "observed": "no paid creator Leads in 90 days",
      "doc": "/plays/creator-ads#check-baseline",
      "fix": "The held-back regions become the comparison; the first window reads at 28 days.",
      "then": "Metric.query"
    },
    {
      "check": "approved-pages",
      "status": "fail",
      "doc": "/plays/creator-ads#check-approved-pages",
      "fix": "Publish the landing Page the Ad links to, with the live Price.",
      "then": "Site.publish"
    },
    {
      "check": "role-unstaffed",
      "status": "warn",
      "roles": [
        "contracts-manager",
        "compliance-officer"
      ],
      "owned": 0,
      "doc": "/plays/creator-ads#check-role-unstaffed",
      "fix": "Leave them: the rights Agreement and each Ad come to you.",
      "then": "Role.staff"
    }
  ]
}

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

CheckFix (one call)Your timeWait
use-when · baseline · pass: 1 creator, $600 a month · warn: no history (gaps #8)POST /{namespace}/metrics/query on creator-ad-lead-lift; the held-back regions fill Before1 min28 days
approved-pages · fail (gaps #8)POST /{namespace}/sites/{site}/publish the landing Page20 minnone
role-unstaffed · warn (gaps #8): rights and Ads come to youPOST /{namespace}/roles/{role}/staff, or leave it: you approve each Agreement and Ad0 minnone

Your number · Before no paid creator Leads · Now +4.0 Leads per $100 against held-back regions · Target +5 by Dec 31 · ■■□□ Early sign · 40 regions, 8 held back

Spend is $20 a day ($600 a month, the Venue’s minimum that reads), plus Jess’s $190 post fee and a $95 usage fee per 90 days of rights. Screens and the watch cost about $0.02 a post (Worker cost). That comes to about $630 a month.

When it starts

WhenTrigger idStarts onWindowHow it gets in
A creator under Agreement posts about your Offercreator-post-liveevent on Post.published where a creator under a signed Agreement names or shows the Offer30dPOST /{namespace}/handles/{handle}/connect reads the creator’s posts
A promoted post is edited, deleted or loses its disclosurecreator-post-changedevent on Post.edited where a promoted source post is edited, deleted, made private, or loses its disclosure or partnership toggle1hthe daily watch on every promoted post
A post’s rights end in 14 daysrights-expiringat on Monitor.checked where 14 days before a post’s rights term or permission end14dthe Agreement’s rights term
+ 7 more for revoked rights, safety flags, rejected Ads, Venue ad changes, fatigue, closed holdouts and margin changes (?lanes=all)
One signed delivery · StartupBuilder-Signature
{
  "$id": "https://api.sb/leaseline.app/events/event_1219",
  "$type": "Event",
  "name": "Post.published",
  "at": "2026-10-10T15:00:22Z",
  "seq": 1219,
  "data": {
    "post": "post_377",
    "handle": "handle_9",
    "venue": "instagram",
    "creator": "Jess Moreno",
    "agreement": "agreement_14",
    "disclosure": true,
    "partnershipLabel": true
  }
}
Reproduce it in test
npx startup-builder trigger Post.published --like event_1219   # replays the delivery
npx startup-builder clock advance --by 3d   # runs the 72-hour screen
npx startup-builder listen Post.published --forward-to http://localhost:3000/hook

Who runs it

Paid media · your agent (role:paid-media-manager, worker_11) holds the Key Result. It hands every Ad build, every rights Agreement and every Limit raise to you (Dana Okafor, person, worker_1), because the Contracts Manager Role has no person; the creator, Jess Moreno (person), signs her own Agreement. Your number links to Did it work.

OptionRung todayEvidence (passed of n)Moves up atDrops back whenYou can
Promote the postYou approve each one2 of 2after 19 of 20 screen verdicts you agree with, then It does it, you can stop it; the Venue caps it therea Check fails, or drift fires → You approve each onePOST /{namespace}/approvals/{approval}/approve · POST /{namespace}/approvals/{approval}/refuse
Ask for rights · Keep it organicIt does it1 of 1 · 4 of 4——POST /{namespace}/actions/{action}/redirect
Raise the Limit, add a Venue, cut the held-back regionsYou approve each one0: the scale gate waits for a winning readoutnever—POST /{namespace}/limits/{limit}/raise
Never: an edit to the creator, her voice or the Product; enhancements on; text in her voiceRefused, every time1 build refused (approved-pages), 0 drift pausesnever——

What it reads · What it may call. It reads the creator’s posts, their hold and engagement, the Agreement’s rights and the targeting each Venue offers the Offer’s category; who watched picks Audiences and never appears in Ad text.

The brief (folded): compiled Agent-register Markdown · play:creator-ads@1 · each line names its record key
You hold the Paid media Key Result: +5 Leads per $100 against held-back regions by 2026-12-31. ← worker, metric
Promote a post only as published: captions, crop and a shorter trim, nothing else. ← copyRules 1, drift
Every Ad carries the Venue’s partnership label and the creator’s own disclosure line. ← copyRules 2
Text Leaseline adds speaks as Leaseline, never in the creator’s voice.           ← copyRules 5
Keep the Venue’s automatic enhancements off.                                     ← copyRules 8

The slow loop, as a Change. payback paused the Play on day 14, reading the first payment ($26 margin) against $184 per first Transaction. change_27 set the margin in your file to the first year’s ($290), and you merged it; read back at +28d, $211 per first Transaction, under the line.

What it can do next

OptionPicked whenDecided byRunsHands toIf it’s just you
promote-the-post promote-the-postbeat the creator’s median, rights granted, the screen passedYour rule (line 6, the screen)POST /{namespace}/ads from the archived post → your approval in the Venueyou approve it · Take this onethe same
ask-for-rights ask-for-rightsbeat the median; no rights clause yetYour rule (the screen)creator-rights-ask: the Agreement summary, one reminderthe creator signs, or it stays organicthe same
keep-it-organic keep-it-organicunder the creator’s median, or the screen failedYour rule (the screen)nothing; the post stays organicnobodythe same
When they write backFixture replyWhat happensWho answersBy whenCall
Interested“Happy to. Send the Agreement.”the Agreement with its plain summary; it signs on her pressthe creator—POST /{namespace}/agreements/{agreement}/sign (hers)
Send me pricing“What does the usage fee come to?”the fee in numbers: $95 per 90 days of rightsPaid media · your agent1 business dayPOST /{namespace}/conversations/{conversation}/answer
Not now“Not this month.”the post stays organic; nothing more sends about itnobodyat oncePOST /{namespace}/conversations/{conversation}/close
Wrong person“My manager handles brand deals.”asks her to forward it; it never writes to an address from her textPaid media · your agent1 business dayPOST /{namespace}/conversations/{conversation}/answer
Out of officean auto-reply until Oct 28the reminder waits for the return datenobodythe return datePOST /{namespace}/messages/{message}/schedule
Question it can’t answer“Can you add a 20 % code for my followers?”To a person: a discount is never the agent’s callyou1 business dayPOST /{namespace}/conversations/{conversation}/escalate
Stop“Please stop running my post.”every Ad on her posts pauses within 1 hournobody1 hourPOST /{namespace}/mandates/{mandate}/revoke

When it hands to you

Ad approvals, rights Agreements and Limit raises come to you (Dana Okafor, person). 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_655",
    "$type": "Task",
    "assignee": "worker_1",
    "due": "2026-10-14T17:00:00Z",
    "on": "post_377",
    "brief": {
      "who": "Jess Moreno, a landlord creator; post_377 on Instagram",
      "said": "How I send renewal notices 60 days out",
      "chose": "promote-the-post",
      "why": "2.1× her median hold; 90 days of rights in agreement_14",
      "spend": "$20 a day; 8 of 40 regions held back",
      "never": [
        "an edit to her or her voice",
        "enhancements on",
        "a Price the Offer lacks"
      ]
    }
  }
]

You answer with POST /{namespace}/approvals/{approval}/approve in the Venue’s ad manager, POST /{namespace}/tasks/{task}/return with a reason, or POST /{namespace}/actions/{action}/redirect. Nothing spends until you approve; an approval left past its due time expires and the Ad never builds. A Limit raise is yours alone, through POST /{namespace}/limits/{limit}/raise.

On time: you, 2 of 2 approved within 1 business day, median 3 h 20 min, n 2, ■□□□ Too early to tell beside Other Startups’ 90 % on time. Your queue: counted by kind: 1 Agreement and 1 Ad approval in week 1; since then, about 1 approval a month.

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; Not live yet, gaps #8)a rights email to a creator whose Conversation a person claimedLeave it to the person who owns it: the draft waits in their queue.POST /{namespace}/tasks/{task}/assign
approved-pages (Not live yet, gaps #8)a post that states a Product fact your claims source lacksKeep it off the paid list, or publish the Page that says it.POST /{namespace}/sites/{site}/publish
category (the record’s Category stop)an Audience or post the Venue would reject for the Offer’s categoryDrop the Audience rule the Venue would reject.PATCH /{namespace}/ads/{id}
scale-gate (the record’s Scale gate)a Limit raise, a new Venue or fewer held-back regions before a winning readoutWait for the holdout readout to win.POST /{namespace}/metrics/query
Stop (pauses the Play)Pauses whenThen
disclosurea source post loses its disclosure line, toggle or partnership labelits Ads pause within 1 hour
source-changea source post is edited, deleted or made privateevery Ad on it pauses until the new version passes the screen
rights1 hour before rights end, or within 1 hour of a revocationevery Ad on that post pauses
safetya creator safety flagher Ads pause until you release them
commenthostile or false-claim comments over 10 % of 50+ in 24 hthat Ad pauses
venue-rejectiona rejected or restricted Ad; 2 in 30 daysher Ads pause on that Venue; then the Play there
paybackcost per first Transaction over the margin in your file, at 5+ first Transactionsthe Play pauses
zero-transaction14-day spend over 3× the margin with no first Transactionthe Play pauses
refundrefunds on creator-Ad first Orders over 2× your 30-day baselinethe Play pauses
spend-limitmonth-to-date spend reaches the $600 Limitthe Play pauses until the month turns
conversion-feedno conversion for 72 h while clicks flowbudget changes freeze; at 7 days the Play pauses
drifta live Ad differs from its archived post, or an enhancement switches onthat Ad pauses at once
fence-breach3 refused writes in one daythe Play drops to read-only
kill-switchyou press itevery creator Ad pauses; Jess is told

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

422RefusedThe Ad from post_291 did not build: its added headline states a result no Page of yours backs.
CheckFixThen
approved-pages fail · Not live yet, gaps #8Cut the headline, or publish the Page that says it.POST /{namespace}/sites/{site}/publish
category pass—POST /{namespace}/content/draft
JSON
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "The Ad from post_291 did not build: its added headline states a result no Page of yours backs.",
  "checks": [
    {
      "check": "approved-pages",
      "status": "fail",
      "doc": "/plays/creator-ads#check-approved-pages",
      "fix": "Cut the headline, or publish the Page that says it.",
      "then": "Site.publish"
    },
    {
      "check": "category",
      "status": "pass"
    }
  ]
}

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

The Stops that fired, as Campaign.paused reasons · sample
[
  {
    "reason": {
      "limit": "payback",
      "observed": "$184 per first Transaction",
      "bound": "$26 first-payment margin",
      "window": "14d"
    },
    "doc": "/plays/creator-ads#stop-payback",
    "task": "task_602"
  }
]

Did it work

The 40 regions were drawn at random, 8 held back from every creator Ad for two 28-day windows, so both halves read from the same assignment (rules m–o); the held-back counts are scaled ×4 to the served regions’ size. Each figure’s call is POST /{namespace}/metrics/query by node, and every node above the leaf is Not live yet (gaps #4).

+4.0 Leads per $100 · ■■□□ Early sign · 40 regions · path → arr

Chose
promote-the-post
Why
Jess’s Oct 10 post on 60-day renewal notices held viewers 2.1 times her median; her Agreement grants 90 days of rights, and the screen passed
From
promote-the-post · ask-for-rights · keep-it-organic
Expects
+3 Leads per $100 against held-back regions within 28d
Reopens when
the holdout window closes on Nov 9, or a Stop fires
By
worker_11
JSON
{
  "$id": "decisions/decision_642",
  "$type": "Decision",
  "choice": "promote-the-post",
  "reason": "Jess’s Oct 10 post on 60-day renewal notices held viewers 2.1 times her median; her Agreement grants 90 days of rights, and the screen passed",
  "stakes": "medium",
  "options": [
    "promote-the-post",
    "ask-for-rights",
    "keep-it-organic"
  ],
  "by": "worker_11",
  "on": "post_377",
  "expected": "+3 Leads per $100 against held-back regions within 28d",
  "reopensWhen": "the holdout window closes on Nov 9, or a Stop fires"
}
NodeServed (32 regions)Held back (8 regions, ×4)AddedConfidenceBasis
creator-ad-lead-lift96 new Leads on $1,290 full cost44 expected (11 × 4)+4.0 Leads per $100 [+0.9, +7.1]■■□□ Early signheld back at random · 40 regions · 2 windows of 28 days
new-leads ↑9644+52 [+12, +92]■■□□ Early signthe same assignment
new-arr ↑$2,436, 7 Customers · Booked $2,784: credited, not all caused by this Play$1,392, 4 expected+$1,044 [−$1,400, +$3,500] · Worth about +$500 a month■□□□ Too early to tell (7 vs 4 Customers)the same · 6 trials still deciding
net-new-arr · arr+$2,436+$1,392+$1,044, carried■□□□ Too early to tellcarried from new-arr

The leaf counts new Leads in served regions above the held-back regions’ rate, per $100 of creator Ad spend with usage fees included, over each 28-day window.

How it moves it: the post that held Jess’s own viewers 2.1 times her median ran unedited to property managers like them, with the partnership label on.

Guardrails: treated against held back: cost per first Transaction (play-payback), $211 against your first-year margin of $290, and refunds on first Orders, 0 of 7.

The Campaign card · sample
{
  "$id": "https://api.sb/leaseline.app/campaigns/creator-ads",
  "$type": "Campaign",
  "play": "play:creator-ads@1",
  "path": [
    "creator-ad-lead-lift",
    "new-leads",
    "new-arr",
    "net-new-arr",
    "arr"
  ],
  "experiment": {
    "metric": "creator-ad-lead-lift",
    "unit": "ratio",
    "heldBack": 8,
    "decision": null
  },
  "readout": {
    "value": 4,
    "n": 40,
    "maturing": 0,
    "interval": [
      0.9,
      7.1
    ],
    "readability": "C",
    "basis": "held-back",
    "pooled": false
  },
  "ledger": {
    "spend": 1290,
    "workerCost": 2,
    "hours": 1.6,
    "pipelineArr": 2088,
    "wonArr": 2784,
    "projectedArr": 500,
    "paybackDays": 154
  }
}

Outside benchmark: none recorded for this Play yet; Other Startups’ results print beside every row.

Before it · After it. Before it: creator-probe finds the creator and creator-partnership signs her. After it: promote-winners holds it as one of its winning messages, and instant-response answers the Leads it sends.

Example

Leaseline ran it from 2026-08-24 to 2026-10-19 (56 days) with one creator, Jess Moreno, a landlord with 60 doors: 7 posts screened, 2 promoted at $20 a day, and 8 of 40 regions held back. Read every captured thread at ?threads=all; three follow the tables.

What happened, by routePostsDoneLeads · Customers (Booked: credited, not all caused by this Play)
Promote the post22 Ads, $1,120 spent, 1 build refused first96 · 7, $2,784
Ask for rights · Keep it organic1 · 41 signed · ——
At $600 a month (the Use it when volume)1 window of 28 daysreads onceOther Startups’ results: +3.1 per $100, ■■■□ Likely, n 96
DayEventWhat happenedYour time
0event_118 Campaign.createdthe three steps; the dry run fails approved-pages25 min
3event_160 Agreement.signedJess signs the rights clause: 90 days, $95 usage fee10 min
5event_188 Action.refusedapproved-pages refused an added headline; the rebuild ran with Leaseline’s own line—
8event_221 Ad.createdthe first partnership Ad, approved by you; the first Lead on day 115 min
14event_290 Campaign.pausedpayback at $184 per first Transaction against the $26 first-payment margin—
15event_301 Change.mergedchange_27: the margin in your file becomes the first year’s, $29010 min
47event_655 Ad.createdthe second Ad, from post_3775 min
1–56event_150 Approval.created, first of 3you approved 2 Ads and 1 Agreement; weekly reviews, from the POST /{namespace}/tasks/next log35 min · total 1.6 h measured, 2 h asked

Jess Moreno, Instagram, Oct 10 · “How I send renewal notices 60 days out for 60 doors,” her own words and screen, with her paid-partnership line.¹

The Ad, Oct 14 to Oct 19 · the same post, unedited, labeled as a paid partnership with Leaseline, to property managers in 32 regions.² 41 new Leads in 6 days; Leaseline’s own line under it reads as Leaseline.³

post_291, 2026-08-29 · the headline approved-pages refused, then the one that ran
- Leaseline cuts late renewal notices by 90 %.
+ Leaseline sends each renewal notice 60 days out, per owner.

Jess, 2026-09-03 11:02 · “Can you add a 20 % code for my followers?” · Paid media · your agent, 11:03 · *Thanks, Jess. Dana handles codes and replies by Sep 4.*⁴ The Brief went to you (task_571); you answered on Sep 3 at 16:40.

¹ The creator’s own disclosure line, in the post. ² The Venue’s paid-partnership label; nothing about her or her voice changed. ³ Text Leaseline adds speaks as Leaseline. ⁴ The routed line, compiled from the Role’s Settings.

Your settings

plays/creator-ads.mdx
---
holdout: 0.2      # 8 of 40 regions see no creator Ad
limit: 600        # dollars a month
margin: 290       # first-year margin per first Transaction
---
Run Jess’s posts that beat her median as paid partnership Ads, exactly as she posted them. I approve every Ad.
Text
$ npx startup-builder show plays/creator-ads
holdout 0.2 · limit 600 · margin 290     your file  plays/creator-ads.mdx:2-4,6 (Ask 2026-08-24; margin by change_27, 2026-09-08)
family demand · runs inside promote-winners · worker role:paid-media-manager, owns never · chooses none (D38) · sequences creator-rights-ask, creator-rights-renewal · checks owned-by-a-person, approved-pages, category, scale-gate · stops 14 · placements instagram, facebook, tiktok, gmail    catalog  play:creator-ads@1 (Not live yet, gaps #5)

Every key from the catalog

Key Id What it is
Tactic creator-rights-capture Creator rights capture writes paid-usage rights into every creator Agreement before the post exists, and records the Venue’s partnership permission per post. Starts at You approve each one.
Tactic creator-post-screen Creator post screen qualifies a post for spend when it beats its cell’s median hold rate, shows coded Orders or buyer questions, and passes checks. Starts at Sends nothing.
Tactic category-audience-rules Category audience rules turn the targeting each Venue offers the Offer’s category, and the Startup’s exclusions, into the saved query of every Audience a paid Play syncs. Starts at Sends nothing.
Tactic partnership-ad-build Partnership ad build creates a paused Ad from a creator’s post through the Venue’s partnership path, under the creator’s Mandate, label on. Starts at You approve each one.
Tactic creator-post-watch Creator post watch reads each promoted post and its creator daily, pauses Ads on any change or rights end, and reports spend weekly. Starts at Sends nothing.
Tactic winner-promotion Winner promotion runs a free-placement winner as a paused, fenced Ad against its control, and judges it on counted conversions from Stripe. Starts at You approve each one.
Tactic ad-write-proxy Ad write proxy is the only write path to an ads Venue, holding the token outside the model and forcing every create to paused. Starts at You approve each one.
Tactic creative-drift-monitor Creative drift monitor reads every live Ad each day, diffs it against its approved cut and settings, and pauses any Ad that changed. Starts at Sends nothing.
Tactic incrementality-holdout Incrementality holdout measures the first Transactions a paid arm adds, by a geo holdout or a day switchback, before any scale step. Starts at You approve each one.
Tactic payback-gate Payback gate pauses a paid Play the moment its cost per first Transaction outruns first-transaction margin, with no approval and no wait. Starts at Sends nothing.
Trigger creator-post-live Creator post live: event on Post.published, window 30d.
Trigger creator-post-changed Creator post changed: event on Post.edited, window 1h.
Trigger rights-revoked Rights revoked: event on Mandate.revoked, window 1h.
Trigger rights-expiring Rights expiring: at on Monitor.checked, window 14d.
Trigger creator-safety-flag Creator safety flag: event on Post.published, window 1d.
Trigger ad-rejected Ad rejected: event on Ad.rejected, window 1d.
Trigger venue-rule-change Venue ad change: event on Monitor.checked, window 7d.
Trigger ad-fatigue Ad fatigue: threshold on Monitor.checked, window 3d.
Trigger holdout-closed Holdout closed: event on Experiment.matured, window 7d.
Trigger margin-change Margin change: event on Offer.repriced, window 1d.
Sequence creator-rights-ask Creator rights ask: 3 steps; it ends on The creator signs.; The creator declines.; Day 7 passes with no signature, and the post stays organic..
Sequence creator-rights-renewal Creator rights renewal: 3 steps; it ends on The creator signs the renewal.; The creator declines.; The rights term ends..

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