Skip to content

SmsSendBulk

POST sms/message/bulk

Queues a campaign: up to 10 000 recipients in one call, either with a shared text or from a template with per-recipient data.

A recipient that cannot be queued — blacklisted, opted out, bad number — does not abort the campaign. It lands in failed with its reason while the rest is queued, because a half-imported list is worse than a list with three known gaps.

Access Control

Allowed roles: admin, leader. Marketing campaigns are not a per-manager action.

Request

POST https://{broker_domain}/sms/message/bulk
{
  "templateId": 4,
  "campaignId": "summer-promo",
  "kind": "MARKETING",
  "recipients": [
    {
      "phone": "+380951234567",
      "sendToParentType": "CUSTOMER",
      "sendToParentId": 140,
      "data": {
        "name": "John"
      }
    },
    {
      "phone": "+380671111111",
      "sendToParentType": "LEAD",
      "sendToParentId": 77,
      "data": {
        "name": "Anna"
      }
    }
  ]
}
{
  "command": "SmsSendBulk",
  "extID": "1",
  "data": {
    "templateId": 4,
    "campaignId": "summer-promo",
    "kind": "MARKETING",
    "recipients": [
      {
        "phone": "+380951234567",
        "sendToParentType": "CUSTOMER",
        "sendToParentId": 140,
        "data": {
          "name": "John"
        }
      },
      {
        "phone": "+380671111111",
        "sendToParentType": "LEAD",
        "sendToParentId": 77,
        "data": {
          "name": "Anna"
        }
      }
    ]
  }
}
const res = await platform.SmsSendBulk({
  templateId: 4,
  campaignId: "summer-promo",
  kind: "MARKETING",
  recipients: [
    {
      phone: "+380951234567",
      sendToParentType: "CUSTOMER",
      sendToParentId: 140,
      data: {
        name: "John"
      }
    },
    {
      phone: "+380671111111",
      sendToParentType: "LEAD",
      sendToParentId: 77,
      data: {
        name: "Anna"
      }
    }
  ]
});

Request Data

Field Type Required Description
recipients array Yes Recipients, 1..10000 items: { phone, sendToParentType?, sendToParentId?, data? }
message string No Shared text; required unless templateId is set
templateId int No Template to render for every recipient
data object No Shared placeholder values; per-recipient data overrides them
profileId int No Explicit provider profile for the whole campaign
senderId string No Sender name or number
kind enum No TRANSACTIONAL or MARKETING
sendAt string No Start the campaign later
truncate bool No Truncate long texts instead of rejecting them
campaignId string No Your own campaign id; generated when omitted

Behavior

  • parts counts segments, not messages: that is the number the operator invoices, and a two-segment text doubles the cost of the campaign.
  • Messages are queued, not sent inside the request. The queue paces them at the provider rate limit, so a 10 000-recipient campaign cannot flood the account.
  • campaignId ties the messages together for SmsGetStats and for cancelling what has not left the queue yet.

Response Data

{
  "campaignId": "summer-promo",
  "queued": 2,
  "parts": 2,
  "failed": [
    { "phone": "380950000000", "error": "Phone 380950000000 is blacklisted: opt-out" }
  ],
  "messages": [
    { "smsId": 814, "phone": "380951234567", "parts": 1 },
    { "smsId": 815, "phone": "380671111111", "parts": 1 }
  ]
}

Errors

Code Error Description
400 VALIDATION_ERROR Empty recipient list, more than 10 000 items, or neither message nor templateId
404 TEMPLATE_NOT_FOUND Template not found in the brand
409 NO_ROUTE_AVAILABLE No profile of the brand can send to these destinations