Broadcasts

One message, sent into every conversation you already have with a segment of your contacts.

A broadcast is written once and delivered into the direct-message threads your contacts already opened with you. It is not a post, and it is not a cold DM: every message lands in a conversation that person started.

Who it goes to is an audience filter over your contacts — networks, labels, source, custom fields — resolved when you send, not when you write. Reading a broadcast needs the inbox scope; sending or cancelling one also needs publish.

The messaging window

This is the rule that shapes everything here.

Messenger and Instagram allow a business-initiated message only within 24 hours of that person's last message to you. Outside that window, FoPost does not attempt the send. The recipient is recorded as skipped with the reason window_closed, and nothing reaches the platform.

NetworkWindow
Facebook (Messenger)24 hours since their last message
Instagram24 hours since their last message
Telegram, Slack, Bluesky, RedditNone — the thread only has to exist

So the number of messages sent is often lower than the size of the audience, and that is the API working correctly rather than failing. Check the recipients list to see who was skipped and why.

A contact who has never written to the sending account is skipped as no_conversation, on every network.

List broadcasts

GET /v1/broadcasts
curl "https://api.fopost.com/v1/broadcasts?workspace_id=7d2b8c11-4e5a-4a8f-b0d9-3c5e6f7a8b90" \
  -H "X-API-Key: $FOPOST_API_KEY"
ParameterDescription
workspace_idOne workspace. Omit it to span every workspace the key can reach; each broadcast then carries workspace_id
statusdraft, scheduled, sending, sent, or cancelled
page, per_pagePagination, per_page up to 100

Newest first.

{
  "data": [
    {
      "id": "3f8a1d92-6c40-4b7e-a15d-90b2c4e6f8a1",
      "name": "September check-in",
      "text": "New colours just landed. Want a look?",
      "account_id": "b41e7c05-9d38-4a2f-8e60-1c7d5b3a9f24",
      "audience": { "platforms": ["instagram"], "label_ids": ["..."] },
      "status": "sent",
      "scheduled_at": null,
      "sent_at": "2026-09-19T10:04:00.000Z",
      "created_at": "2026-09-19T09:58:00.000Z",
      "counts": { "total": 412, "sent": 268, "skipped": 141, "failed": 3, "pending": 0 }
    }
  ],
  "pagination": { "page": 1, "per_page": 25, "total": 1 }
}

counts.skipped is usually the messaging window doing its job.

Create a broadcast

POST /v1/broadcasts
curl -X POST "https://api.fopost.com/v1/broadcasts" \
  -H "X-API-Key: $FOPOST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "workspace_id": "7d2b8c11-4e5a-4a8f-b0d9-3c5e6f7a8b90",
    "account_id": "b41e7c05-9d38-4a2f-8e60-1c7d5b3a9f24",
    "name": "September check-in",
    "text": "New colours just landed. Want a look?",
    "audience": { "platforms": ["instagram"] }
  }'
FieldDescription
workspace_idRequired
account_idRequired. The connected account the messages go out from
nameRequired. What you call it; never sent to anyone
textRequired. The message itself
media_idAn asset from your media library to attach
audienceWho it goes to (below). Omitted means every contact in the workspace
scheduled_atSend it at this time instead of on demand

Creating never sends. With scheduled_at the broadcast goes out on its own at that time; without it, call send.

The audience filter

Every clause narrows: a contact has to match all of them.

{
  "platforms": ["instagram", "facebook"],
  "label_ids": ["0a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d"],
  "source": "inbox",
  "fields": [
    { "key": "plan", "op": "is", "value": "pro" },
    { "key": "churn_risk", "op": "is_not_set" }
  ]
}
ClauseDescription
platformsContacts with a handle on at least one of these networks
label_idsLabels the contact carries
sourceinbox, radar, or import
fieldsCustom field clauses, by field key. op is is, is_not, contains, is_set or is_not_set

Update a broadcast

PATCH /v1/broadcasts/{id}

Only a draft or scheduled broadcast can be edited. Once it is sending, the text is fixed.

Send a broadcast

POST /v1/broadcasts/{id}/send
curl -X POST "https://api.fopost.com/v1/broadcasts/3f8a1d92-6c40-4b7e-a15d-90b2c4e6f8a1/send" \
  -H "X-API-Key: $FOPOST_API_KEY"
{ "data": { "id": "3f8a1d92-...", "status": "sending", "recipients": 412 } }

The audience is resolved and frozen into a recipient list, then messages go out in the background on a queue of their own, so a large broadcast never delays your scheduled posts. recipients is how many contacts matched, not how many will be messaged — the window decides that.

Sending is idempotent per contact: a retried job resumes the list rather than messaging anyone twice.

Needs the publish scope as well as inbox.

Cancel a broadcast

POST /v1/broadcasts/{id}/cancel

Stops it where it stands. Anyone not yet written to stays unsent. Messages already delivered are not recalled — nothing can recall them.

Needs the publish scope as well as inbox.

List recipients

GET /v1/broadcasts/{id}/recipients
curl "https://api.fopost.com/v1/broadcasts/3f8a1d92-6c40-4b7e-a15d-90b2c4e6f8a1/recipients?status=skipped" \
  -H "X-API-Key: $FOPOST_API_KEY"
ParameterDescription
statuspending, sent, skipped, or failed
page, per_pagePagination, per_page up to 200
{
  "data": [
    {
      "contact_id": "6b0e9a4c-2d71-4f3a-9c18-5e7d0a1b2c34",
      "display_name": "Ada Okafor",
      "status": "sent",
      "skip_reason": null,
      "sent_at": "2026-09-19T10:04:12.000Z",
      "error": null
    },
    {
      "contact_id": "9c2f7b31-5a08-4d16-b7e3-42c9a0d8e1f5",
      "display_name": "Sam Rivera",
      "status": "skipped",
      "skip_reason": "window_closed",
      "sent_at": null,
      "error": null
    }
  ],
  "pagination": { "page": 1, "per_page": 50, "total": 2 }
}
skip_reasonWhat happened
window_closedThe network's messaging window had shut. Nothing was attempted
no_conversationThis contact has never written to the sending account
unsupported_platformThe account's network takes no messages

Delete a broadcast

DELETE /v1/broadcasts/{id}

Removes the broadcast and its recipient records. Messages already sent stay in the conversations they went to. Cancel it first if it is still sending. This cannot be undone.

Billing

Each delivered message is metered as one message. A monthly allowance is included, and messages past it are billed on your usual invoice. Skipped recipients cost nothing — no message, no charge.

Related documentation
  • API Overview

    Base URL, envelopes, pagination, and errors for the FoPost REST API.

  • Authentication

    API keys, scopes, and workspace binding.

  • Publishing

    Create a post, target accounts, publish it, and read the per-account result.

  • Scheduling

    Schedule a post, repeat it, and import a batch from a spreadsheet.

  • Media

    Upload files, list the media library, and attach media to a post.

  • Validation

    Check content, text length, and media against platform rules before a post exists.

  • Accounts

    List connected social accounts, check their health, and refresh credentials.

  • Workspaces

    Workspaces, labels, and how isolation works across them.

Was this helpful?

On this page