URL: /plays/events-and-webinars · Id: `play:events-and-webinars`

# Events and webinars

> Events and webinars runs your online sessions as a series, follows up each registrant within a day, and counts the Deals they open.

Events and webinars runs your online sessions as a series, follows up each registrant within a day, and counts the [Deals](https://startupbuilder.dev/business/nouns/deal) they open.

```text title="Set it up · Ask"
Be our Marketing Lead: run a three-session series on 60-day renewal notices, invite our List, follow up every registrant within a day, and send anyone who asks to Priya. I host, and I send the attendee notes. Show me what’s missing; don’t send.
```

```text title="Run one · Ask"
Hand our latest webinar signal to the Marketing Lead agent and show me what it chose and why. Don’t send.
```

```ts title="Run one · SDK"
import { $ } from 'startup-builder'

const { events: [last] } = await $.Event.list({ where: 'name in ("Problem.ranked", "Gathering.registered", "Question.asked", "Registration.attended", "Registration.missed", "Prospect.engaged", "Watch.replayed", "Deal.opened")', 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 }
```

```json title="Run one · Response · sample"
{
  "decision": {
    "$id": "https://api.sb/leaseline.app/decisions/decision_486",
    "$type": "Decision",
    "choice": "to-the-ae",
    "reason": "they picked talk to the team in session 3’s closing poll and manage 180 units, over the 150 your Team plan covers",
    "stakes": "low",
    "options": [
      "plan-a-series",
      "invite-your-list",
      "follow-up-an-attendee",
      "send-the-replay",
      "to-the-ae",
      "cut-the-replay"
    ],
    "by": "worker_6",
    "on": "contact_52",
    "expected": "a Meeting held by day 14",
    "reopensWhen": "no Meeting.booked for contact_52 within 14d"
  },
  "actions": [
    {
      "$id": "https://api.sb/leaseline.app/actions/action_1",
      "$type": "Action",
      "status": "done",
      "mode": "try",
      "by": "worker_6",
      "verb": "Registration.get",
      "checks": []
    },
    {
      "$id": "https://api.sb/leaseline.app/actions/action_2",
      "$type": "Action",
      "status": "done",
      "mode": "try",
      "by": "worker_6",
      "verb": "Contact.enrich",
      "checks": [
        {
          "check": "customer-collision",
          "status": "pass"
        }
      ]
    },
    {
      "$id": "https://api.sb/leaseline.app/actions/action_3",
      "$type": "Action",
      "status": "done",
      "mode": "try",
      "by": "worker_6",
      "verb": "Task.assign",
      "checks": []
    },
    {
      "$id": "https://api.sb/leaseline.app/actions/action_4",
      "$type": "Action",
      "status": "pending",
      "reason": "awaitingPerson",
      "mode": "try",
      "by": "worker_6",
      "verb": "Meeting.book",
      "checks": [
        {
          "check": "owned-by-a-person",
          "status": "pass"
        },
        {
          "check": "consent-stop",
          "status": "pass"
        },
        {
          "check": "claims-resolve",
          "status": "pass"
        }
      ]
    }
  ]
}
```

`action_3` is Priya’s Task with the Brief, due in 60 minutes; `action_4` books once Priya picks a time from her calendar.

`1.7 against 1.2 Deals per 100 Organizations · ■□□□ Too early to tell · held back at random · n 820 · path → arr`

| Try another: the registrant | Choice | Reason |
| --- | --- | --- |
| Tom Becker, Hearthstone Rentals, 180 units: picked “talk to the team” in session 3’s poll | `to-the-ae` | asked for the team; over 150 units |
| Ana Ruiz, 40 units: attended session 3 live and asked about owner reports | `follow-up-an-attendee` | attended; her question gets its answer with the replay |
| Joel Park registered for session 3 and missed it | `send-the-replay` | a no-show: the replay, no apology and no Offer |
| 14 questions on owner reports across Forms and replies in 30 days | `plan-a-series` | over 10 on one problem: a new series goes to you |
| Session 3 closed with the recording notice shown at every join | `cut-the-replay` | the notice showed; 3 cuts with no attendee’s face or voice |

| Worth | Your time | Spend | First signal | Use it when | Instead |
| --- | --- | --- | --- | --- | --- |
| ≈ +$260 ARR a month at 50 registrants | 3 h per session, then 20 min a week | $0.08 per registrant, ~$4 a month at 50 | Day 15: first Meeting from a registrant | 1,000+ reachable Contacts, 10+ questions a month on one problem | Under 1,000 and no co-host: `gatherings` · no problem draws 10 questions: `founder-voice` |

**Where it sits:** **Stranger** → **Lead** → Trialing → Activated → At risk → Churned → Won back · Registrant deals → Deals and trials opened → New Customers ↑ → ARR added each week → ARR

Worth’s formula: about +4 Deals per 100 registrants (Other Startups’ results; no lift of your own yet) × 50 registrants a month × 0.38 paid per Deal × $347 first order ARR ≈ +$264. Under First signal: The leaf reads at day 90 and day 180 after the first session, so the first read is Dec 7; at 820 Organizations held back 1 in 5, day 180 can tell +2.5 Deals per 100 or more.

`sample · api.sb/leaseline.app · 41 Customers at 2026-10-19 · on Prospect.engaged · first hand-off 4m · 9 keys Not live yet`

## Start it this week
```bash
npx startup-builder add play events-and-webinars   # 1 · writes plays/events-and-webinars.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":"events-and-webinars"}'

# 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":"events-and-webinars"}'

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

# off: invitations and Sequences stop; booked sessions stay booked
curl -X PATCH https://api.sb/leaseline.app/campaigns/events-and-webinars \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"endsAt":"now"}'
```


```json title="The dry run’s 422 · 2026-08-24 · sample"
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "events-and-webinars can’t start yet: 1 check fails and 1 warns.",
  "checks": [
    {
      "check": "use-when",
      "status": "pass",
      "observed": "1,640 reachable Contacts at 820 Organizations; 23 questions on renewal notices in 30 days",
      "doc": "/plays/events-and-webinars#check-use-when",
      "fix": "None needed: 1,000 Contacts and 10 questions are enough.",
      "then": "Metric.query"
    },
    {
      "check": "baseline",
      "status": "pass",
      "observed": "no series in 90 days",
      "doc": "/plays/events-and-webinars#check-baseline",
      "fix": "None needed: the held-back fifth is the comparison.",
      "then": "Metric.query"
    },
    {
      "check": "domain-authenticated",
      "status": "pass",
      "observed": "leaseline.app authenticated on 2026-08-02",
      "doc": "/plays/events-and-webinars#check-domain-authenticated",
      "fix": "None needed.",
      "then": "Domain.authenticate"
    },
    {
      "check": "mailbox-warm",
      "status": "fail",
      "observed": "events@leaseline.app has warmed 0 of 14 days",
      "doc": "/plays/events-and-webinars#check-mailbox-warm",
      "fix": "Warm events@ for 14 days; session 1 invitations go out on day 14.",
      "then": "Mailbox.warm"
    },
    {
      "check": "role-unstaffed",
      "status": "warn",
      "roles": [
        "sales-lead"
      ],
      "owned": 31,
      "doc": "/plays/events-and-webinars#check-role-unstaffed",
      "fix": "Staff the AE, or leave it: talk-to-the-team picks come to you.",
      "then": "Role.staff"
    }
  ]
}
```

| Check | Fix (one call) | Your time | Wait |
| --- | --- | --- | --- |
| <a id="check-use-when"></a>`use-when` · <a id="check-baseline"></a>`baseline` · pass: 1,640 Contacts, 23 questions on one problem; no series before (gaps #8) | <Op verb="Metric.query" /> on `registrant-deals`; the held-back fifth fills Before | 1 min | none |
| <a id="check-domain-authenticated"></a>`domain-authenticated` · pass | <Op verb="Domain.authenticate" /> (done Aug 2) | 0 min | none |
| <a id="check-mailbox-warm"></a>`mailbox-warm` · fail (Not live yet, gaps #1) | <Op verb="Mailbox.warm" /> events@leaseline.app | 2 min | 14 days; session 1 is set for Sep 8 |
| <a id="check-role-unstaffed"></a>`role-unstaffed` · warn (gaps #8): 31 of your open Leads have a person owner, you | <Op verb="Role.staff" />, or leave it: talk-to-the-team picks come to you | 0 min | none |

`Your number · Before 0 (no series) · Now 9.3 Deals per 100 registrants so far · Target 6 per 100 at day 180 · ■□□□ Too early to tell · held back at random · first read Dec 7`

Each registrant costs about $0.08: the Sequence sends from your Domain and the tiering (Worker cost); the room costs nothing on your plan, and you set no paid promotion. That comes to about $4 a month at 50 registrants, and $11 for the 140 so far.

## When it starts
| When | Trigger id | Starts on | Window | How it gets in |
| --- | --- | --- | --- | --- |
| Someone registers for a session | `registration-created` | `event` on `Gathering.registered` where gathering.series = this series | tiered within 15 min; 21d | your Form posts to <Op verb="Registration.create" /> |
| A session closes and the room reports who attended | `session-attended` | `event` on `Registration.attended` where status = 'attended' | every registrant enrolled within 24 h; 14d | <Op verb="Integration.connect" /> the room |
| An attendee picks talk to the team, or asks for a demo, a trial or a Price | `in-session-intent` | `event` on `Prospect.engaged` where poll = 'talk to the team', or asks for a demo, a trial or a Price | 3d; the AE within 60 min | the same room connection |
| + 5 more for topic demand, registrant questions, replays, repeat attendees and registrant Deals (`?lanes=all`) | | | | |

```json title="One signed delivery · StartupBuilder-Signature"
{
  "$id": "https://api.sb/leaseline.app/events/event_1633",
  "$type": "Event",
  "name": "Prospect.engaged",
  "at": "2026-10-13T17:52:18Z",
  "seq": 1633,
  "data": {
    "contact": "contact_52",
    "organization": "Hearthstone Rentals",
    "gathering": "gathering_3",
    "poll": "talk to the team",
    "units": 180
  }
}
```

```bash title="Reproduce it in test"
npx startup-builder trigger Prospect.engaged --like event_1633   # replays the delivery
npx startup-builder clock advance --by 14d   # then reopens the Decision if no Meeting was booked
npx startup-builder listen Prospect.engaged --forward-to http://localhost:3000/hook
```

## Who runs it
**Marketing Lead · your agent** (`role:marketing-lead`, `worker_6`) holds the Key Result. It plans, invites, tiers and follows up; talk-to-the-team picks go to **AE · Priya Shah (person)** (`role:sales-lead`, `worker_3`), and **you** (Dana Okafor, person, `worker_1`) host every session and send each attendee note from your own Mailbox. Your number links to Did it work.

| Option | Rung today | Evidence (passed of n) | Moves up at | Drops back when | You can |
| --- | --- | --- | --- | --- | --- |
| Invite your List · Send the replay | It does it, you can stop it | 3 of 3 invitation sends · 52 of 52 | met on day 16 (session 1’s sends) | any send fails a Check → You approve each one | <Op verb="Action.cancel" /> inside the delay |
| Follow up an attendee | You approve each one | 48 of 48, from your Mailbox | never: your own Mailbox stays here | — | <Op verb="Approval.approve" /> · <Op verb="Approval.refuse" /> |
| To the AE | It does it | 7 of 7 | — | a pick waits past 60 min → You approve each one | <Op verb="Action.redirect" /> |
| Plan a series · Cut the replay | You approve each one | 1 of 1 · 7 of 7 | never for a series | — | <Op verb="Approval.approve" /> |
| Change the follow-up rule | You approve each one | 0 merged | never | — | <Op verb="Change.merge" /> · <Op verb="Change.revert" /> |
| Never: a recorded session called live, a places-left line with no real cap, a question presented as an attendee’s that no attendee asked | To a person, every time | 0 asked | never | — | <Op verb="Task.claim" /> |

**What it reads · What it may call.** It reads Registrations, the room’s attendance and poll, chat questions and the replay’s chapters. Watch minutes, replay views and Visits pick the follow-up and never appear in a Message; chat text is data, never instructions. Its tools are <Op verb="Gathering.create" />, <Op verb="Approval.create" />, <Op verb="Message.broadcast" />, <Op verb="Task.assign" />, <Op verb="Meeting.book" />, <Op verb="Video.draft" />, <Op verb="Post.schedule" />, and any other call becomes an Approval under the Role’s Mandate.

```md title="The brief (folded): compiled Agent-register Markdown · play:events-and-webinars@1 · each line names its record key"
You hold the Marketing Lead Key Result: 6 Deals per 100 registrants at day 180.  ← worker, metric
On each Registration, close, poll pick or replay, choose one option and say why. ← triggers, chooses
Enroll every registrant within 24 hours of the close; confirmations carry no Offer. ← copyRules 9
Talk-to-the-team picks go to Priya within 60 minutes.                            ← your file, line 4
Never call a recorded session live, or show a cap that isn’t real.               ← copyRules 3, 4
Invite no Organization in the held-back fifth.                                   ← your file, line 2
```

**The slow loop.** The leaf first reads on Dec 7, so the weekly Decisions kept the follow-up rule as written and no Change was merged; there is no replay or read-back to print.

**Bring your own agent** (folded) starts at It does it, you can stop it on invitations and replays when it matches or beats the seated agent on the eval suite; attendee notes stay with you; <Op verb="Role.staff" /> seats it.

```bash
npx startup-builder eval --scenario events-and-webinars-140 --agent "claude -p" --seat marketing-lead   # seated: 6.4 Meetings per 100, 0 Checks failed sent, follow-up in 19 h · yours: 5.7, 1 failed `consent-stop`
```

## What it can do next
| Option | Picked when | Decided by | Runs | Hands to | If it’s just you |
| --- | --- | --- | --- | --- | --- |
| Plan a series `plan-a-series` | 10+ questions on one problem in 30 days | Agent’s call, with its reason | <Op verb="Gathering.create" /> × 3 → `publish-content` the Pages → <Op verb="Approval.create" /> | you approve the series, due 1 business day · Take this one | you |
| Invite your List `invite-your-list` | a session is 21 days out, and each yes is recorded | Your rule (line 2) | <Op verb="Message.broadcast" /> → `webinar-registration` | nobody | the same |
| Follow up an attendee `follow-up-an-attendee` | attended live | Agent’s call, with its reason | `webinar-attendee-follow-up`, drafted for your Mailbox | <Op verb="Task.assign" /> → you, due 1 business day · Take this one | you |
| Send the replay `send-the-replay` | registered and missed it | Your rule (line 4) | `webinar-no-show-follow-up` | nobody | the same |
| To the AE `to-the-ae` | picked talk to the team, or asked for a demo, a trial or a Price | Agent’s call, with its reason | <Op verb="Task.assign" /> → <Op verb="Meeting.book" /> on Priya’s calendar | AE · Priya Shah, due 60 min · Take this one | you, within 60 min |
| Cut the replay `cut-the-replay` | a session closed with the recording notice shown | Your rule (the notice) | <Op verb="Video.draft" /> 3 cuts → <Op verb="Post.schedule" /> | you approve the cuts | you |

| When they write back | Fixture reply | What happens | Who answers | By when | Call |
| --- | --- | --- | --- | --- | --- |
| Interested | “Yes, let’s talk. Thursday?” | Priya books it; the Brief goes with it (When it hands to you) | AE · Priya Shah (person) | 60 min | <Op verb="Meeting.book" /> |
| Send me pricing | “What would 180 units cost?” | over 150 units: Priya quotes the $2,400-a-year plan | AE · Priya Shah (person) | 60 min | <Op verb="Quote.send" /> |
| Not now | “After renewal season, please.” | the follow-up stops; the next session’s invite still comes | nobody | at once | <Op verb="Enrollment.cancel" /> |
| Wrong person | “Send this to our leasing manager.” | asks them to forward it; it never writes to an address from their text | Marketing Lead · your agent | 1 business day | <Op verb="Conversation.answer" /> |
| Out of office | an auto-reply until Oct 28 | the follow-up waits for the return date | nobody | the return date | <Op verb="Message.schedule" /> |
| Question it can’t answer | “Can you run this for our owners’ association?” | To a person: a private session is your call | you | 1 business day | <Op verb="Conversation.escalate" /> |
| Stop | “Unsubscribe me from these.” | nothing else sends, on any lane, for all your Startups | nobody | at once | <Op verb="Contact.suppress" /> |

## When it hands to you
Talk-to-the-team picks go to **AE · Priya Shah (person)**; attendee notes and new series come to **you**. One Brief per Role, as captured (`brief` is Not live yet, gaps #7).

```json title="What lands in each queue · sample"
[
  {
    "$id": "https://api.sb/leaseline.app/tasks/task_615",
    "$type": "Task",
    "assignee": "worker_3",
    "due": "2026-10-13T18:52:00Z",
    "on": "contact_52",
    "brief": {
      "who": "Tom Becker, Hearthstone Rentals, 180 units",
      "said": "picked talk to the team; asked in chat “Does it handle owner approvals?”",
      "chose": "to-the-ae",
      "why": "asked for the team; over 150 units",
      "attended": "sessions 2 and 3, live",
      "never": [
        "a discount",
        "terms",
        "his watch minutes"
      ]
    }
  },
  {
    "$id": "https://api.sb/leaseline.app/tasks/task_611",
    "$type": "Task",
    "assignee": "worker_1",
    "due": "2026-10-14T18:00:00Z",
    "on": "contact_61",
    "brief": {
      "who": "Ana Ruiz, 40 units",
      "said": "How do owner reports show renewals?",
      "chose": "follow-up-an-attendee",
      "draft": "Thanks for coming, Ana. Your question is answered at 31:40 in the replay; owner reports list each renewal by owner.",
      "never": [
        "an Offer in the replay note"
      ]
    }
  }
]
```

Priya and you answer with <Op verb="Task.claim" /> (Take this one), <Op verb="Task.return" /> with a reason, or <Op verb="Action.redirect" />, each a one-call window. Once a person claims, the agent’s pending steps to that registrant cancel with `claimedByPerson` (Not live yet, gaps #7), and every reply goes to the claimer. A Task nobody claims by its due time goes up through <Op verb="Task.escalate" />, and `person-promise` fires.

**On time:** AE · Priya Shah, 7 of 7 claimed within 60 min, median 14 min, n 7, ■□□□ Too early to tell; you, 48 of 48 attendee notes within 24 h, median 9 h. **Your queue:** counted by kind: about 16 attendee notes per session, 2 or 3 hand-offs to Priya, and 1 series approval each quarter.

**The fixed line:** <Op verb="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) | Refuses | Fix | Then |
| --- | --- | --- | --- |
| <a id="check-owned-by-a-person"></a>`owned-by-a-person` (rule j; Not live yet, gaps #8) | a follow-up to a registrant whose Lead or open Deal a person owns | Leave it to the person who owns it: the draft waits in their queue. | <Op verb="Task.assign" /> |
| <a id="check-consent-stop"></a>`consent-stop` (gaps #3; the record’s Consent stop) | a follow-up to a registrant whose Market needs a recorded yes the Form lacks | Ask once for a yes on the next Form. | <Op verb="Message.schedule" /> |
| <a id="check-claims-resolve"></a>`claims-resolve` (shared) | a sentence in an invite, Page or note that resolves to no record | Cut the claim, or name the record that backs it. | <Op verb="Content.draft" /> |
| <a id="check-import-refusal"></a>`import-refusal` (the record’s Import refusal) | a Contact list loaded into the room; everyone registers through the Form | Invite the list; they register themselves. | <Op verb="Message.broadcast" /> |
| <a id="check-partner-box"></a>`partner-box` | a Registration shared with a co-host whose box was left unticked | It stays yours; the co-host gets only ticked ones. | <Op verb="Registration.update" /> |
| <a id="check-notice-at-join"></a>`notice-at-join` | a recording with no notice shown at every join | Turn the notice on; that session does not record. | <Op verb="Gathering.update" /> |
| <a id="check-face-voice-consent"></a>`face-voice-consent` | a cut with an attendee’s face, voice or full name and no recorded yes | Cut them out, or ask for their yes. | <Op verb="Consent.create" /> |

| Stop (pauses the Play) | Pauses when | Then |
| --- | --- | --- |
| <a id="stop-bounce"></a>`bounce` | hard bounces over 2 % of a day’s invitations | that list source pauses |
| <a id="stop-complaint"></a>`complaint` | complaints near 0.1 % of a send | invitations pause on every Mailbox |
| <a id="stop-invitation-opt-out"></a>`invitation-opt-out` | opt-outs over 1 % of one invitation send | that list source pauses until the Marketing Lead reviews it |
| <a id="stop-show-rate-floor"></a>`show-rate-floor` | live attendance under 15 % of registrants, 2 sessions running | invitations for the series pause |
| <a id="stop-leading-floor"></a>`leading-floor` | under 2 Meetings per 100 registrants at day 14, past 200 registrants | the series ends after its next session |
| <a id="stop-holdout-loser"></a>`holdout-loser` | the 180-day readout marks the series a loser | the next series waits on a Decision |
| <a id="stop-spend-limit"></a>`spend-limit` | month-to-date spend reaches its Limit | paid promotion and guest fees pause until the month turns |
| <a id="stop-kill-switch"></a>`kill-switch` | you press it | every invitation, Sequence and upload pauses |

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

```json title="The captured refusal · sample"
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "The session 2 invitation did not send: “attendees cut vacancy days in half” resolves to no record.",
  "checks": [
    {
      "check": "claims-resolve",
      "status": "fail",
      "doc": "/plays/events-and-webinars#check-claims-resolve",
      "fix": "Cut the claim, or name the record that backs it.",
      "then": "Content.draft"
    },
    {
      "check": "consent-stop",
      "status": "pass"
    }
  ]
}
```


```json title="The Stops that fired, as Campaign.paused reasons · sample"
[
  {
    "reason": {
      "limit": "bounce",
      "observed": "2.6 % of a day’s invitations",
      "bound": "2 %",
      "window": "1 day"
    },
    "doc": "/plays/events-and-webinars#stop-bounce",
    "task": "task_604"
  }
]
```

## Did it work
A hashed 20 % of the 820 reachable Organizations was never invited, so both halves read the same random assignment (rules m–o). The leaf matures at day 90 after the first session, Dec 7, so no unit has matured: the counts print with Other Startups’ results, and Added waits. Every node above the leaf is Not live yet (gaps #4).

`1.7 against 1.2 Deals per 100 Organizations · ■□□□ Too early to tell · held back at random · n 820 · path → arr`

| Node | Invited (656 Organizations) | Held back (164) | Added | Confidence | Basis |
| --- | --- | --- | --- | --- | --- |
| `registrant-deals` | 1.7 Deals per 100 Organizations (11 of 656) | 1.2 (2 of 164) | — · reads Dec 7 | ■□□□ Too early to tell | held back at random · n 820 · all still maturing · Other Startups’ results +2.1 per 100, ■■□□ Early sign, n 9,400 Organizations |
| `opened-deals-and-trials` | 2.1 per 100 (14 of 656) | 1.8 (3 of 164) | — | ■□□□ Too early to tell | the same assignment |
| `new-arr` ↑ | $1,735, 5 Customers · Booked: credited, not all caused by this Play | $347, 1 Customer ($1,388 at the invited half’s size) | — · Worth about +$260 a month | ■□□□ Too early to tell (5 vs 1 Customers) | the same · 4 Deals still deciding |
| `net-new-arr` · `arr` | +$1,735 | +$1,388 scaled | — | ■□□□ Too early to tell | carried from `new-arr` |

The leaf counts Deals opened per 100 Organizations, invited against held back, read at day 90 and day 180 after the first session; only matured Organizations count (rule n), so nothing prints as Added until Dec 7.

**How it moves it:** all 140 registrants got the replay and their own answer within a median 9 hours, and the 7 who asked for the team reached Priya in a median 14 minutes.

**Guardrails:** invited against held back: Deals per Meeting, 1.0 against Other Startups’ 0.9, and unsubscribes, 0.4 % of invitations; 4 Deals are still deciding.

```json title="The Campaign card · sample"
{
  "$id": "https://api.sb/leaseline.app/campaigns/events-and-webinars",
  "$type": "Campaign",
  "play": "play:events-and-webinars@1",
  "path": [
    "registrant-deals",
    "opened-deals-and-trials",
    "new-arr",
    "net-new-arr",
    "arr"
  ],
  "experiment": {
    "metric": "registrant-deals",
    "unit": "per-100",
    "heldBack": 164,
    "decision": null
  },
  "readout": {
    "value": null,
    "n": 820,
    "maturing": 820,
    "interval": null,
    "readability": "inadmissible",
    "basis": "held-back",
    "pooled": false
  },
  "ledger": {
    "spend": 0,
    "workerCost": 11,
    "hours": 11.5,
    "openArr": 4800,
    "wonArr": 1735,
    "projectedArr": 264,
    "paybackDays": 3
  }
}
```

Outside benchmark: 32 % of registrants attended live (a webinar-platform vendor’s 2026 B2B benchmark, its own customers only); Leaseline’s series ran 34 %.

**Before it · After it.** Before it: `founder-voice` and `owned-newsletter` reach the people who register. After it: `archive-repurposing` hears each transcript, `retargeting` hears the no-shows, and `instant-response` answers registrants who write in.

## Example
Leaseline ran it from 2026-08-24 to 2026-10-19 (56 days): one 3-session series, 1,640 Contacts at 820 Organizations, 164 held back; 140 unique registrants, 48 attended live and 61 watched the replay. Read every captured thread at `?threads=all`; three follow the tables.

| What happened, by option | Decisions | Sent | Meetings by day 14 · Deals so far |
| --- | --- | --- | --- |
| Invite your List · Send the replay | 3 sends · 52 | 1,312 invites · 52 replays | — · — |
| Follow up an attendee | 48 | 48, from your Mailbox | 2 · 2 |
| To the AE | 7 | 7 hand-offs | 7 · 6 |
| Plan a series · Cut the replay | 1 · 3 sessions | 1 series · 7 cuts | — · — |
| **All registrants** · held-back Organizations | **140** | **9 Meetings (6.4 per 100)** | **13 Deals, 5 paid ($1,735)** · 2 Deals |

| Day | Event | What happened | Your time |
| --- | --- | --- | --- |
| 0 | `event_1580` Campaign.created | the three steps; the dry run fails `mailbox-warm` | 25 min |
| 1 | `event_1583` Approval.approved | you approved the series: three sessions on 60-day notices | 15 min |
| 14 | `event_1590` <Op verb="Message.broadcast" /> | session 1 invitations, after events@ finished warming | — |
| 15 | `event_1592` Campaign.paused | `bounce`: 2.6 % of the day’s invitations; one old list source paused | 10 min |
| 15 | `event_1594` Gathering.held | session 1: 41 registrants, 15 live; the first Meeting booked that afternoon | 3 h |
| 29 · 50 | `event_1604` · `event_1633` Gathering.held | sessions 2 and 3: 58 and 64 registrants, 17 and 16 live | 6 h |
| 1–56 | `event_1595` Task.assigned, first of 48 | you sent 48 attendee notes, from the <Op verb="Task.next" /> log | 2 h 15 min · **total 11.5 h measured, 10 h asked** |

> **Tom Becker, session 3 chat, Oct 13, 17:41** · “Does it handle owner approvals?” · poll: talk to the team.
>
> **Priya, 17:56** · Hi Tom, thanks for staying to the end. Owner approvals are in the replay at 38:10.¹ For 180 units, our account plan fits: would Thu 10:00 or 14:00 Central work?² *Signed with the Role’s disclosure line.*³
>
> **Tom, 18:20** · “Thu 14:00.” <Op verb="Meeting.book" /> put it on Priya’s calendar; a Deal opened on Oct 16.

```diff title="Session 2 invitation, 2026-09-08 · the draft claims-resolve refused, then the rewrite that sent"
- Our attendees cut vacancy days in half.
+ Across 3,520 renewals, leases noticed 60+ days out renewed at 71 % (n 1,940). Session 2 shows how.
```

> **Ana Ruiz, session 3, Oct 13, 17:30** · “How do owner reports show renewals?” · The note went to you (`task_611`), due 18:00 on Oct 14; **Dana, Oct 14, 09:12** · *sent it from her own Mailbox, with the answer at 31:40 in the replay.*⁴

¹ The answer to their own question, at its minute. ² One next step, with times the calendar shows. ³ The fixed signature line, compiled from the Role’s disclosure Setting. ⁴ The attendee note goes from the host’s own Mailbox.

## Your settings
```mdx title="plays/events-and-webinars.mdx"
---
holdout: 0.2    # a hashed 1 Organization in 5 is never invited
---
Run three sessions on 60-day notices. Send the replay to every registrant within a day; talk-to-the-team picks go to Priya within 60 minutes.
```

```text
$ npx startup-builder show plays/events-and-webinars
holdout 0.2 · 3 sessions · AE within 60 min     your file  plays/events-and-webinars.mdx:2,4 (Ask 2026-08-24)
family demand · process content-marketing · worker role:marketing-lead, owns never · chooses 6 (3 rule, 3 read) · sequences webinar-registration, webinar-attendee-follow-up, webinar-no-show-follow-up, webinar-on-demand-follow-up · checks owned-by-a-person, consent-stop, claims-resolve + 4 · stops 8 · placements gmail, outlook, yahoo-mail, linkedin, x, youtube    catalog  play:events-and-webinars@1 (Not live yet, gaps #5)
```

### Every key from the catalog
| Key | Id | What it is |
| --- | --- | --- |
| Tactic | <a id="tactic-series-plan"></a>`series-plan` | Series plan turns gathered questions on one Problem into a 4-session series with guests, dates, targets and a holdout, for one founder approval. Starts at You approve each one. |
| Tactic | <a id="tactic-registration-build"></a>`registration-build` | Registration build creates the series’ Gatherings, Pages and one Form with Consent and recording notice, and refuses every list import. Starts at You approve each one. |
| Tactic | <a id="tactic-invitation-run"></a>`invitation-run` | Invitation run invites the Startup’s held audience 21 and 7 days out, hands co-hosts and the founder their drafts, and keeps the holdout uninvited. Starts at You approve each one. |
| Tactic | <a id="tactic-registrant-prep"></a>`registrant-prep` | Registrant prep grades each registrant on arrival, offers the host’s post-session slots to the strongest, sends reminders, and briefs the host. Starts at You approve the first wave. |
| Tactic | <a id="tactic-session-desk"></a>`session-desk` | Live room desk runs the live room’s chat beside the human host as a labeled agent, queues questions, records attendance and captures closing-poll intent. Starts at Sends nothing. |
| Tactic | <a id="tactic-follow-up-tiers"></a>`follow-up-tiers` | Follow-up tiers sorts attendees hot, warm and cold at close; the host writes each hot first-day note, and every registrant is enrolled within 24 hours. Starts at You approve each one. |
| Tactic | <a id="tactic-on-demand-cuts"></a>`on-demand-cuts` | On-demand cuts publishes the chaptered replay within 2 hours, cuts at most 3 clips and 2 derivatives per audience, and registers every on-demand viewer. Starts at You approve each one. |
| Tactic | <a id="tactic-registrant-deals-readout"></a>`registrant-deals-readout` | Registrant deals readout counts Meetings at 14 days and Deals at 90 and 180 days per 100 registrants, read against the holdout. Starts at Sends nothing. |
| Tactic | <a id="tactic-send-gate-check"></a>`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 | <a id="tactic-reply-matrix"></a>`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. |
| Tactic | <a id="tactic-sending-stop-loss"></a>`sending-stop-loss` | Sending stop loss: Reads the Play’s own bounces, replies and seed tests on every send, and rests, pauses or retires a Mailbox, Domain, cell or the Play. Starts at Sends nothing. |
| Tactic | <a id="tactic-founder-send-tray"></a>`founder-send-tray` | Founder send tray shows each approved draft with its source trail; the founder presses post by hand or through the Venue’s own posting path. Starts at You approve each one. |
| Tactic | <a id="tactic-synthetic-media-check"></a>`synthetic-media-check` | Synthetic media check classes each render, labels each realistic synthetic person, voice or scene, and refuses invented testimonials and unconsented likenesses. Starts at Sends nothing. |
| Trigger | <a id="trigger-topic-demand"></a>`topic-demand` | Topic demand: `threshold` on `Problem.ranked`, window 60d. |
| Trigger | <a id="trigger-registration-created"></a>`registration-created` | Registration created: `event` on `Gathering.registered`, window 21d. |
| Trigger | <a id="trigger-registrant-question"></a>`registrant-question` | Registrant question: `event` on `Question.asked`, window 14d. |
| Trigger | <a id="trigger-session-attended"></a>`session-attended` | Attended live: `event` on `Registration.attended`, window 14d. |
| Trigger | <a id="trigger-event-no-show"></a>`event-no-show` | Event no-show: `state` on `Registration.missed`, window 30d. |
| Trigger | <a id="trigger-in-session-intent"></a>`in-session-intent` | In-session intent: `event` on `Prospect.engaged`, window 3d. |
| Trigger | <a id="trigger-replay-watched"></a>`replay-watched` | Replay watched: `threshold` on `Watch.replayed`, window 14d. |
| Trigger | <a id="trigger-series-repeat"></a>`series-repeat` | Series repeat: `threshold` on `Registration.attended`, window 30d. |
| Trigger | <a id="trigger-registrant-deal-opened"></a>`registrant-deal-opened` | Registrant deal opened: `event` on `Deal.opened`, window 180d. |
| Sequence | <a id="sequence-webinar-registration"></a>`webinar-registration` | Webinar registration: 4 steps; it ends on The registrant joins the session; The registrant cancels; An opt-out or Suppression. |
| Sequence | <a id="sequence-webinar-attendee-follow-up"></a>`webinar-attendee-follow-up` | Webinar attendee follow-up: 4 steps; it ends on A reply; A booked Meeting; A Deal opens at the Organization; An opt-out or Suppression. |
| Sequence | <a id="sequence-webinar-no-show-follow-up"></a>`webinar-no-show-follow-up` | Webinar no-show follow-up: 3 steps; it ends on The replay is watched past half; A Registration for the next session; A reply; An opt-out or Suppression. |
| Sequence | <a id="sequence-webinar-on-demand-follow-up"></a>`webinar-on-demand-follow-up` | Webinar on-demand follow-up: 4 steps; it ends on A reply; A booked Meeting; An opt-out or Suppression. |
| Benchmark | <a id="benchmark-webinar-show-rate"></a>`webinar-show-rate` | Live attendees per registration across B2B webinars, from stated totals.: 32 % (A webinar-platform vendor’s 2026 B2B webinar benchmark, 2025 data; its own customers only., 2026-10-24). |
| Benchmark | <a id="benchmark-webinar-series-share"></a>`webinar-series-share` | Share of webinars that belong to a series: 25 percent the prior year, under 33 percent in 2025.: 25–33 % (A webinar-platform vendor’s 2026 B2B webinar benchmark, 2025 data; its own customers only., 2026-10-24). |