Skip to content

Broadcasts

A broadcast sends one campaign to many recipients. You name it, we resolve the recipients, and a worker fans the messages out and bills them one by one.

POST /ng/v1/rcs/broadcasts/estimate — price it, no send, no charge
POST /ng/v1/rcs/broadcasts — send it

The estimate resolves exactly the same recipients the real send would, prices each against your RCS tariff for that operator, and compares the total to your balance.

Terminal window
curl -X POST https://api.9bits.net/ng/v1/rcs/broadcasts/estimate \
-H "Authorization: Bearer $NINEBITS_RCS_KEY" \
-H "Content-Type: application/json" \
-d '{
"broadcastType": "multi",
"broadcastName": "march-promo",
"senderId": "FirstDigits",
"content": "Half price this weekend only.",
"destination": "lagos-customers"
}'
{
"status": 200,
"validMsisdns": 1840,
"inValidMsisdns": 12,
"balance": 250000,
"cost": 18400,
"currency": "NGN",
"numberOfMessages": 1840,
"isThereEnoughBalance": true
}

isThereEnoughBalance: false is a warning, not a block — the send will still be accepted and will simply start failing partway through with status: 51. Check it and top up first.

broadcastType decides how destination is read:

Typedestination isMessage
singleComma-separated numberscontent — the same for everyone
multiA contact group namecontent — the same for everyone
variableA dynamic contact group nameEach contact carries its own text

variable is how you personalise: the message lives on the contact row, not in the request, so content is ignored. Upload a dynamic group in the dashboard, then reference it by name.

Terminal window
curl -X POST https://api.9bits.net/ng/v1/rcs/broadcasts \
-H "Authorization: Bearer $NINEBITS_RCS_KEY" \
-H "Content-Type: application/json" \
-d '{
"broadcastType": "multi",
"broadcastName": "march-promo",
"senderId": "FirstDigits",
"content": "Half price this weekend only.",
"destination": "lagos-customers",
"callback_url": "https://example.com/hooks/rcs"
}'
{
"status": 200,
"message": "Your request is being processed",
"broadcastId": "4c1f9a72be0d5836a7e1",
"targetBase": 1840,
"scheduledFor": null
}

Set scheduled: true and a defer_until of YYYY-MM-DD HH:MM, in your account’s local time:

{
"broadcastType": "single",
"broadcastName": "friday-reminder",
"senderId": "FirstDigits",
"content": "Your appointment is tomorrow at 10am.",
"destination": "2348020000000,2348030000000",
"scheduled": true,
"defer_until": "2026-09-12 09:30"
}
{
"status": 200,
"message": "Your broadcast has been scheduled",
"broadcastId": "4c1f9a72be0d5836a7e1",
"targetBase": 2,
"scheduledFor": "2026-09-12 09:30"
}

Two behaviours to know:

  • A defer_until in the past falls through to an immediate send. It is not an error, so a timezone mistake sends now rather than telling you.
  • An unparseable defer_until is an error: invalid defer_until (expected 'YYYY-MM-DD HH:MM'). Note the space — this is not ISO 8601.
FieldTypeRequiredDescription
broadcastTypestringsingle, multi or variable.
broadcastNamestringYour name for the campaign. This is how you find it in the reports, so make it unique.
senderIdstringAn approved RCS sender.
destinationstringNumbers or a group name, per broadcastType.
contentstringRequired for single and multi. Ignored for variable.
callback_urlstringDelivery reports for every message in the campaign.
scheduledbooleanDefaults to false.
defer_untilstringYYYY-MM-DD HH:MM. Only read when scheduled is true.

All of these come back as 400 with a description:

DescriptionCause
invalid broadcastType (expected single|multi|variable)Typo, or an empty broadcastType.
senderId and broadcastName are requiredOne of the two is missing.
content is requiredA single or multi send with no text.
group not foundThe group name does not match one of yours. Names are per-user.
no valid recipientsThe group is empty, or the number list parsed to nothing.
invalid defer_until (expected 'YYYY-MM-DD HH:MM')Wrong timestamp format.

Use broadcastName against the report endpoints:

Terminal window
curl -X POST https://api.9bits.net/ng/v1/rcs/reports/broadcasts/messages \
-H "Authorization: Bearer $NINEBITS_RCS_KEY" \
-H "Content-Type: application/json" \
-d '{ "broadcastName": "march-promo" }'

The campaign list, per-message drill-down and CSV export are all in the API reference.