Broadcasts in live mode count against your plan’s monthly sends: 2,000 on Starter, 15,000 on Growth and 1,00,000 (fair use) on Pro. Test mode is never limited. See Monthly broadcast sends and Plans and limits.
Quick start
LazyApp uses one create call with recipients inline — you can still add more recipients to a draft or scheduled broadcast later.uuid, status, and stats. Poll GET /v1/broadcasts/{uuid} while status is running, or subscribe to campaign.* webhooks.
Create fields
There is no
profileId, accountId, or platform field — the API key already scopes the request to one workspace and mode (live / test).
Template variables
Pass static placeholder values, or personalise per contact:- String /
string[]shorthand still means the same values for every recipient. - Object slots use
source:static,contact_attribute(key), orcontact_field(fieldsuch asphone_number,email,username). - Missing attributes become an empty string so Meta still gets the expected parameter count.
headerfills a text header variable when the template has one.header_mediais the image, video or document for a media header: a public https URL or an uploaded media id. Carousel cards take theirs infeatures.cards[].header_media.bodyis an ordered array matching{{1}},{{2}}, … in the template body.
body entries must match the template’s placeholder count. A mismatch makes Meta reject the send (parameter-count error).
An image-header marketing template, such as an intake announcement:
variable_map is checked when you create the broadcast, so a misspelt source or a header_media that is not a string is a 422 now rather than a failed send for every recipient later.
Add recipients
Onlydraft or scheduled broadcasts. Existing recipient rows are kept; new numbers are merged and compliance-checked.
Recipients
Target either:phone_numbers— explicit E.164 list (+919812345670).contact_segment_uuid— a segment you created over the API or in the console.contact_segment_id(the integer id) also works.
stats.excluded with a reason — they are never sent.
Workflow for a cold list:
uuid as contact_segment_uuid.
Scheduling
Setschedule_at on create and omit start (or pass "start": false):
scheduled until LazyApp’s scheduler starts it at schedule_at, or you call POST /v1/broadcasts/{uuid}/start early.
There is no separate POST …/schedule endpoint — scheduling is a field on create.
Compliance is enforced at send time, not create time
This is deliberate. A broadcast created on Monday and sent on Friday respects the opt-outs that happened on Wednesday.Opt-outs
Suppressed contacts are excluded. There is no override.
Frequency caps
frequency_cap_days skips anyone who already received a marketing message inside that
window.Quiet hours
Sending pauses during quiet hours in the contact’s timezone and resumes after.
Messaging limits
Sends are paced to your number’s Meta messaging tier rather than being rejected in bulk.
Exclusion reasons
When you start a broadcast,stats breaks down the audience:
Excluded recipients are stored with a reason code (visible in the console). Common codes:
Recording consent from your own opt-in flow
Broadcasts refuse recipients without granted marketing consent. Consent collected on your own website — a checkbox, a form, a CRM export — can be recorded with:consent_text, proof_reference and captured_by are stored exactly as given. Granting marketing consent also lifts a matching suppression, so someone who just opted in on your site is not still opted out.
Monthly broadcast sends
Your plan sets how many live-mode broadcast recipients you can send to in a calendar month (UTC):
Every recipient that is queued or sent counts, across all broadcasts in the workspace. The count resets on the 1st of the month. Test mode is never limited, so you can rehearse a broadcast on the test number as often as you like.
- Starting checks the whole audience. If a broadcast has more pending recipients than you have sends left this month, LazyApp refuses to start it, and the message says how many sends remain and when they reset. Send to fewer people or move to a bigger plan in Billing. Over the API, the start call returns
422with that reason inmessage. - A scheduled broadcast that no longer fits fails. It moves to
failedwith the reason, rather than retrying every minute. - A running broadcast pauses when the month is used up. Other broadcasts can use sends after this one started, so LazyApp checks again before each batch. When nothing is left, the broadcast moves to
pausedand your billing contacts get an email. Start it again next month, or after you upgrade, from the console or withPOST /v1/broadcasts/{uuid}/start.
What a broadcast costs
The send limit is what your plan includes. The messages themselves are billed by Meta, at Meta’s rates, to your own Meta payment method. LazyApp adds 0%. See How Meta bills your messages and WhatsApp rates.Status and webhooks
Webhook events:
Per-message delivery still arrives on the usual
message.* events for each recipient.
What we skip (Zernio-style)
Related
- Templates — create and approve marketing templates
- Messages — one-off template sends with per-recipient control
- Webhooks —
campaign.*events - Plans and limits — monthly broadcast sends per plan
- How Meta bills your messages — Meta’s rates, 0% added by LazyApp