The Messenger API sends messages from your Facebook Page to people who have messaged it. You connect the Page once through OAuth, then send through POST /messenger/message/sendbulk, a multipart endpoint shared by every Messenger message type.
Connect your Facebook Page#
- Call
POST /messenger/oauth/generate-linkwith your token. It returns an encrypted onboarding link. - Open the link as an admin of the Page and approve the permissions in Meta's dialog.
- Once connected, messages to your Page arrive in the Omni Inbox and on your webhook, and you can send through the API.
cURL
curl -X POST https://api.broadnet.me/messenger/oauth/generate-link \
-H "Authorization: Bearer $BROADNET_TOKEN"Who you can message, and when#
Messenger identifies people by a page-scoped ID (PSID), not a phone number. You receive the PSID when someone messages your Page, and you pass it as destinationNo.
Meta's messaging policy sets the windows:
| Situation | What to send |
|---|---|
| Within 24 hours of the person's last message | Any message, with messagingType=RESPONSE. |
| A human agent replying later (up to 7 days) | messagingType=MESSAGE_TAG with messageTag=HUMAN_AGENT, where your Page is approved for it. |
| A public comment or post on your Page | A private reply, with commentId or postId. |
Bulk, personalised and scheduled sends still follow these rules. Check Meta's Messenger Platform policy for the current details.
Send a message#
cURL
curl -X POST https://api.broadnet.me/messenger/message/sendbulk \
-H "Authorization: Bearer $BROADNET_TOKEN" \
-F batchId=0 \
-F destinationNo=6543210987654321 \
-F messageType=TEXT \
-F messagingType=RESPONSE \
-F campaignName=support \
-F "content=Thanks for your message. Your order ships tomorrow."Node.js
const form = new FormData();
form.append("batchId", "0");
form.append("destinationNo", "6543210987654321"); // PSID
form.append("messageType", "TEXT");
form.append("messagingType", "RESPONSE");
form.append("campaignName", "support");
form.append("content", "Thanks for your message. Your order ships tomorrow.");
const res = await fetch("https://api.broadnet.me/messenger/message/sendbulk", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.BROADNET_TOKEN}` },
body: form,
});
console.log(res.status, await res.text());Python
import os
import requests
fields = {
"batchId": "0",
"destinationNo": "6543210987654321", # PSID
"messageType": "TEXT",
"messagingType": "RESPONSE",
"campaignName": "support",
"content": "Thanks for your message. Your order ships tomorrow.",
}
r = requests.post(
"https://api.broadnet.me/messenger/message/sendbulk",
headers={"Authorization": f"Bearer {os.environ['BROADNET_TOKEN']}"},
files={k: (None, v) for k, v in fields.items()},
timeout=30,
)
print(r.status_code, r.text)Request fields#
| Field | Type | Required | Description |
|---|---|---|---|
destinationNo |
string | Yes | One or more PSIDs, comma-separated. |
messageType |
string | Yes | TEXT, IMAGE, VIDEO, AUDIO, FILE, TEMPLATE or REACTION. |
content |
string | TEXT |
Message text, up to 2,000 characters. |
messagingType |
string | No | RESPONSE, or MESSAGE_TAG together with messageTag. |
messageTag |
string | With MESSAGE_TAG |
For example HUMAN_AGENT. |
mediaUrl |
string | Media types | Public HTTPS URL of the image, video, audio or file. |
file |
file | Media types | Upload the media instead of linking it. |
caption, fileName |
string | No | Caption for media; file name for FILE. |
templateName |
string | TEMPLATE |
Your label for the template payload. |
templatePayloadJson |
string (JSON) | TEMPLATE |
Meta template payload: button, generic (carousel), media or receipt. |
quickReplyJson |
string (JSON) | No | Quick reply options for a TEXT message. |
replyTo |
string | No | Message ID to reply to in a thread. |
replyToMessageId, emoji |
string | REACTION |
The message to react to, and the emoji. |
notificationType |
string | No | SILENT_PUSH or NO_PUSH. |
commentId, postId |
string | No | Send a private reply to a comment or post. |
personaId |
string | No | Send as a Page persona. |
metadata |
string | No | Your own reference, for tracking. |
batchId |
string | No | 0 starts a new batch. |
campaignName, allowDuplicate, delay |
string | No | Reporting label, de-duplication and throttle. |
scheduled, scheduleTime, gmt, recurrence, repeatCount |
string | No | Schedule one-off or recurring sends. |
Buttons and carousels#
Templates use Meta's template payload format in templatePayloadJson:
cURL
curl -X POST https://api.broadnet.me/messenger/message/sendbulk \
-H "Authorization: Bearer $BROADNET_TOKEN" \
-F batchId=0 \
-F destinationNo=6543210987654321 \
-F messageType=TEMPLATE \
-F templateName=order_actions \
-F 'templatePayloadJson={"template_type":"button","text":"What would you like to do?","buttons":[{"type":"web_url","url":"https://example.com/orders/8842","title":"Track order"},{"type":"postback","title":"Talk to us","payload":"AGENT"}]}'Quick replies#
cURL
curl -X POST https://api.broadnet.me/messenger/message/sendbulk \
-H "Authorization: Bearer $BROADNET_TOKEN" \
-F batchId=0 \
-F destinationNo=6543210987654321 \
-F messageType=TEXT \
-F "content=How can we help?" \
-F 'quickReplyJson=[{"content_type":"text","title":"Orders","payload":"ORDERS"},{"content_type":"text","title":"Returns","payload":"RETURNS"}]'Read receipts and typing#
POST /messenger/message/read marks the conversation as seen, or shows a typing indicator:
cURL
curl -X POST https://api.broadnet.me/messenger/message/read \
-H "Authorization: Bearer $BROADNET_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "recipientId": "6543210987654321", "typing": true }'Templates and batches#
| Method | Path | Description |
|---|---|---|
| POST | /messenger/templates |
Save a reusable template. |
| GET | /messenger/templates |
List saved templates (paginated). |
| GET | /messenger/templates/grouped-by-category |
Templates grouped by category. |
| POST | /messenger/message/all-bulk |
List batches with filters. |
| GET | /messenger/message/edit?batch_Id=… |
Batch details. |
| GET | /messenger/message/pause?batch_Id=… |
Pause a batch. |
| GET | /messenger/message/resume?batch_Id=… |
Resume a batch. |
| DELETE | /messenger/message/abort?batch_Id=… |
Abort a batch. |
| POST | /messenger/profile/set |
Set Page profile settings such as the Get Started button. |
| GET | /messenger/profile |
Read Page profile settings. |
Next steps#
- Instagram: the same pattern for Instagram DMs.
- Webhooks: receive inbound messages and statuses.
- Authentication: how OAuth and your Bearer token fit together.
Ready to send your first message?
Request test credentials. An engineer sets up your account, and test sends go to your own verified numbers.
Request test access