Send a broadcast
curl -X POST https://api.subscriby.net/v1/projects/$PROJECT_ID/broadcasts \
-H "Authorization: Bearer $SUBSCRIBY_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"message": "<b>New drop is live</b>\nDoors open at 19:00 UTC.",
"audience": "customer"
}'
202, not 200: the send is queued and runs in the background at roughly 28 messages a second to stay inside the platform's rate limit. The response describes what was addressed, not what was delivered.
Audience segments
| Segment | Who it addresses |
|---|---|
| all | Every member reachable on the project's connector, whatever their status. |
| customer | Members holding a paid subscription right now. |
| trialing | Members currently inside a free trial. |
| lead | Members who have used the project's bot but never subscribed. |
| churned | Members who were customers and are not any more. |
| expiring_soon | Members whose subscription genuinely lapses within expiring_within_days. |
| cancelled_still_active | Members who cancelled but have not run out yet: still reachable, still winnable. |
| paused | Members who paused their subscription rather than ending it. |
| trialing_cardless | Members trialing without a card on file, who will not convert on their own. |
| all_pass_holders | Everyone holding a valid pass for any upcoming window. |
| all_pass_holders_not_in_queue | Everyone who has not tapped their invite link, across every upcoming window. |
| pass_holders | Everyone holding a valid pass for one access window you choose (pass_window_id). |
| pass_holders_not_in_queue | Holders of one window you choose who have not tapped their invite link yet. |
A member is a recipient only if they have a linked chat on that project's connector. Members with no chat, or whose chat belongs to a different installation, are excluded silently, which is why recipient_estimate is frequently well below a project's total membership.
An auto-renewing subscription is never expiring_soon. A subscription's ends_at is rewritten to the new period end on every renewal, so a date inside the horizon describes an auto-renewing member's next invoice rather than an expiry. Counting it would place every monthly subscriber in this segment once a month. A member is counted only when their access genuinely lapses: they have cancelled, or the plan is not recurring.
Narrowing a segment to a plan
plan_id composes with audience rather than replacing it:
| Request | Who it addresses |
|---|---|
| audience=customer + plan_id=<gold> | People paying for Gold right now. |
| audience=churned + plan_id=<gold> | People who held Gold and left. |
| audience=paused + plan_id=<gold> | People whose paused plan is Gold. |
| audience=expiring_soon + plan_id=<gold> | Gold members lapsing inside the horizon. |
The plan and the state describe the same subscription, so a member paying for Silver who once trialled Gold is not matched by the first row. churned is the deliberate exception in the other direction: the subscription proving they held the plan is the one that ended, so it is not required to be live.
A plan_id sent with lead or a pass segment is refused with 422 and reason: plan_filter_unsupported, not ignored. Silently dropping it would return a recipient count for a different audience than the request described, and a caller has no way to notice.
Message formatting
The body is reduced to the HTML subset the delivering connector accepts before sending; for the messaging connector that is <b>, <strong>, <i>, <em>, <u>, <ins>, <s>, <strike>, <del>, <a>, <code>, <pre>, <blockquote> and <tg-spoiler>. Anything else is stripped, not escaped: the platform rejects an entire message containing an unknown tag, so removing it is what keeps the message deliverable.
The 4,096-character limit is the platform's own. A longer body is refused here rather than being truncated per recipient.
Refusals
Every 422 is refused before anything is queued. The underlying job re-checks the same conditions and aborts silently, which is correct for a background job and wrong for an API caller, so the endpoint rejects them up front rather than returning 202 for a send that could never leave. A segment that resolves to zero recipients is the send action's own refusal, shared with the dashboard: it is not queued.
Request
- Base URL: https://api.subscriby.net
- URL: https://api.subscriby.net/v1/projects/{project}/broadcasts
- Auth: HTTP bearer
Path parameters
The project, resolved by the route binder.
Headers
A key unique to this operation, such as a fresh UUID. The same key replays the original 2xx response for 24 hours (with Idempotent-Replay: true), so a retry after a timeout never repeats the write; the same key with a different body is refused with 409.
Request body
Response
202 with the segment, the verified filters, the recipient count and the ETA.
Example response
{
"data": {
"project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
"audience": "customer",
"recipient_estimate": 128,
"estimated_seconds": 5,
"status": "queued"
}
}Changes
No recorded changes to this operation across all 1 revision of this API.