Configure the four auto-messages
Turn on/edit the welcome, subscription-expiring, subscription-expired, or fan-online auto-message, and check who it would have reached via the shadow log.
Who this is for: a workspace owner.
There are exactly four auto-message cards — welcome, expiring, expired, online —
and at most one live row of each per account. POST is always an upsert: it edits the one
campaign of that kind if it already exists, so a repeated save can never leave you with two
"Welcome" cards both enabled.
curl https://app.tease.link/api/admin/broadcasts/automessages \
-H "Authorization: Bearer $TEASE_API_KEY"curl -X POST https://app.tease.link/api/admin/broadcasts/automessages \
-H "Authorization: Bearer $TEASE_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "kind": "expiring", "text": "Your subscription ends soon — stick around!",
"enabled": true, "within_days": 3, "resend_after_days": 5 }'What each kind fires on
| Kind | Fires when | Its own timing knob |
|---|---|---|
welcome | A fan subscribes. | — |
expiring | The subscription ends within N days, and auto-renew is off (a renewing fan isn't "leaving" — sending it here would be a coupon you didn't need to give). | within_days (default 3). |
expired | The subscription ended within the last N days, again only for non-renewing fans. | within_days (default 7). |
online | The fan was recently active — real presence data when available, otherwise "wrote recently" as an honest proxy. | within_minutes (default 15), plus a cooldown_hours (default 168 — once a week) so it doesn't re-fire every time they open the app. |
resend_after_days (1–30) is a separate reminder for a fan who never responded — it's available
on welcome, expiring, and expired, but not online, which already has its own
cooldown_hours doing a similar job for a different mechanic (a repeat visit, not a re-send of
the same reminder).
Body fields
| Field | Type | Description |
|---|---|---|
kind | string | One of welcome, expiring, expired, online. |
text | string | Required, non-empty — the message body. Runs through the content firewall on save. |
enabled | boolean | Turns the card on/off. |
ppv_price_cents | integer | Optional — attach a price, turning the send into a PPV. |
media_ids | string[] | Optional vault media to attach. |
within_days / within_minutes / cooldown_hours / resend_after_days | integer | See the table above — only the ones relevant to this kind matter. |
segment_id | integer | Restrict to one audience segment; omitted = everyone eligible. |
Turning enabled: false off doesn't just flip a flag silently going forward — every not-yet-sent
queued send for that campaign is halted immediately, so switching it off mid-run stops what's
already in flight.
Shadow by design — every card, always
Every auto-message campaign is created mode: 'shadow' and stays there: it renders and logs,
it never actually sends. GET /broadcasts/automessages even returns a hardcoded
"live_send_enabled": false for exactly this reason — so a client can't accidentally promise a
real send the backend has no path to deliver yet. The enabled toggle controls whether the
card is being simulated (and logged) at all, not whether it's "really" sending.
Preview who would fire right now
A live dry-run count, with the same gates a real send would check — so the number can't lie by ignoring a reason nothing would actually go out:
curl "https://app.tease.link/api/admin/broadcasts/automessages/42/would-fire?hours=24" \
-H "Authorization: Bearer $TEASE_API_KEY"{ "campaign_id": 42, "kind": "expiring", "count": 84,
"gated": { "optin": false, "kill": false, "firewall": false },
"warnings": [], "online_source": "", "sample": ["fan_1", "fan_2"] }gated reports the same three checks a real send would apply — the owner's opt-in/kill-switch
state and the content firewall's verdict on this card's current text — so count: 84 next to
gated.kill: true reads honestly as "84 would be eligible, but nothing will actually fire while
the kill switch is up," not as a false promise.
Read the shadow log
The historical record of who this auto-message would have reached, with the real rendered text, built up over time while the card runs in shadow:
curl "https://app.tease.link/api/admin/broadcasts/automessages/42/shadow-log?limit=50" \
-H "Authorization: Bearer $TEASE_API_KEY"Use would-fire to answer "if I flip this on right now, roughly how many fans?" and the shadow
log to answer "has this actually been matching real fans over time?"
What's next
Auto-messages sit behind the same account-wide safety rails as every other automated send — see the automation kill-switch and content firewall. For a one-off message instead of a lifecycle trigger, see Create and schedule a broadcast.