Referência da API de SMS em massa

A API REST da BulkSMSOnline envia mensagens de texto para 227 países a partir do seu próprio software, com os mesmos preços, regras de segmentos, agendamento e reembolsos do console. As requisições e respostas são JSON sobre HTTPS, e cada status final de entrega pode ser enviado ao seu servidor como um webhook assinado.

URL basehttps://bulksmsonline.cc/api/v1

Visão geral

Use a API quando as mensagens forem disparadas pelos seus próprios sistemas: atualizações de pedidos de uma loja, códigos de um formulário de login, lembretes de uma ferramenta de reservas. Uma requisição a POST /v1/messages com até 10,000 números cria uma campanha, desconta o saldo e coloca todas as mensagens na fila. As campanhas criadas pela API também aparecem no console com seus relatórios de entrega.

  • Todos os valores são em dólares americanos, como strings com cinco casas decimais, por exemplo "0.00534".
  • Os números de telefone são internacionais, com ou sem o + inicial; espaços e traços são removidos.
  • Os horários seguem ISO 8601 em UTC, por exemplo 2026-12-01T09:00:00Z.
  • Os ids de mensagens e campanhas têm a forma MSG-XXXX-XXXX-XXXX e CMP-XXXX-XXXX-XXXX.

Autenticação

Crie uma chave de API em API no console (as chaves são liberadas depois que a sua primeira recarga é adicionada). Envie-a no cabeçalho Authorization de cada requisição. Uma chave começa com bso_api_ seguido de 36 caracteres; ela é exibida uma única vez, então guarde-a como segredo no seu servidor. Criar uma nova chave substitui a anterior imediatamente.

Authorization: Bearer bso_api_0123456789abcdef0123456789abcdef0123
Content-Type: application/json

Limites

Requisições300 por minuto por chave; acima disso, resposta 429 rate_limited
Números por requisição10,000
Texto da mensagem2,000 caracteres como escritos, até 10 segmentos
Agendamentosend_at de 5 minutos a 60 dias à frente
Ritmo de envio400 mensagens por minuto por fila
Novas tentativas do webhook9 tentativas em cerca de 22 horas

Enviar mensagens

POST/v1/messages

Envia um texto para um ou mais números. O custo total é descontado do saldo quando a requisição é aceita; cada mensagem que não pode ser entregue é reembolsada depois. A resposta tem status 201 e traz a campanha com todas as mensagens.

CampoDescrição
toobrigatórioUm número ou uma lista de até 10,000 números em formato internacional. Números repetidos são enviados uma vez; os ilegíveis são listados em skipped.
textobrigatórioA mensagem, com até 2,000 caracteres e 10 segmentos. O texto GSM-7 comporta 160 caracteres por SMS, o Unicode 70.
send_atopcionalHorário ISO 8601 para agendar o envio, de 5 minutos a 60 dias à frente. Omita para enviar agora.
opt_outopcionaltrue adiciona a sua linha de cancelamento das configurações do console em uma nova linha no final.
client_refopcionalSua própria referência, com até 64 letras, dígitos e _ . : -. Ela é retornada em relatórios e webhooks.
curl -X POST https://bulksmsonline.cc/api/v1/messages \
  -H "Authorization: Bearer $BSO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"to":["+447700900412","+33612345678"],"text":"Order 4521 has shipped. Track it at shop.example/t/4521","client_ref":"order-4521"}'
HTTP/1.1 201 Created
{
  "id": "CMP-7KQ2-M9XA-4HTD",
  "status": "sending",
  "channel": "api",
  "recipients": 2,
  "segments": 1,
  "encoding": "GSM-7",
  "cost": "0.02158",
  "refunded": "0.00000",
  "client_ref": "order-4521",
  "send_at": null,
  "counts": { "queued": 2, "submitted": 0, "delivered": 0, "failed": 0, "canceled": 0 },
  "skipped": [],
  "balance": "118.43120",
  "messages": [
    { "id": "MSG-3RTW-81KD-ZQ0P", "to": "+447700900412", "country": "GB", "segments": 1, "price": "0.00834", "status": "queued" },
    { "id": "MSG-5HNA-4C2E-7YVB", "to": "+33612345678", "country": "FR", "segments": 1, "price": "0.01324", "status": "queued" }
  ]
}

Cotar um envio

POST/v1/quote

Recebe o mesmo corpo de /v1/messages e retorna o custo exato, os segmentos e a codificação sem enviar nem cobrar nada. Use para mostrar um preço aos seus próprios usuários antes de confirmarem.

{
  "recipients": 2,
  "skipped": [],
  "segments": 1,
  "encoding": "GSM-7",
  "cost": "0.02158",
  "balance": "118.45278",
  "countries": [ { "country": "GB", "recipients": 1, "cost": "0.00834" }, { "country": "FR", "recipients": 1, "cost": "0.01324" } ]
}

Saldo

GET/v1/balance

{ "balance": "118.43120", "currency": "USD" }

Tarifas

GET/v1/rates

GET/v1/rates/{country}

O preço de um segmento de SMS para cada destino, ou para um código de país ISO de duas letras. Estes dois endpoints são públicos e não precisam de chave.

{ "country": "DE", "name": "Germany", "calling_code": "+49", "price": "0.01544", "currency": "USD", "per": "segment" }

Status da mensagem

GET/v1/messages/{id}

{
  "id": "MSG-3RTW-81KD-ZQ0P",
  "campaign_id": "CMP-7KQ2-M9XA-4HTD",
  "to": "+447700900412",
  "country": "GB",
  "segments": 1,
  "price": "0.00834",
  "status": "delivered",
  "error": null,
  "created_at": "2026-11-07T09:00:02Z",
  "submitted_at": "2026-11-07T09:00:03Z",
  "final_at": "2026-11-07T09:00:08Z"
}

Campanhas

GET/v1/campaigns/{id}

GET/v1/campaigns/{id}/messages?offset=0&limit=100

O primeiro retorna a campanha com suas contagens por status; o segundo percorre suas mensagens, com até 1.000 por página. As campanhas enviadas pelo console podem ser lidas da mesma forma com o id mostrado na página delas.

Cancelar um envio agendado

POST/v1/campaigns/{id}/cancel

Interrompe uma campanha criada com send_at que ainda não começou. Todas as mensagens são canceladas e o custo total volta para o saldo. Uma campanha que já está sendo enviada responde 409 not_scheduled.

Webhooks de entrega

Adicione uma URL HTTPS em API no console para receber cada status final (delivered ou failed) como uma requisição POST. Responda com qualquer status 2xx em até 8 segundos. Outras respostas e timeouts são repetidos após 20 segundos, 1, 5 e 15 minutos, depois 1, 3, 6 e 12 horas, no total de 9 tentativas. O mesmo evento pode chegar duas vezes, então use event_id para processá-lo uma só vez.

POST https://your-server.example/sms-status
Content-Type: application/json
X-BulkSMSOnline-Signature: t=1794042008,v1=5f0c2a...e91b

{
  "type": "message.status",
  "event_id": "ev_8f1c22d0a4b97e63c1f0",
  "sent_at": "2026-11-07T09:00:09Z",
  "data": {
    "message_id": "MSG-3RTW-81KD-ZQ0P",
    "campaign_id": "CMP-7KQ2-M9XA-4HTD",
    "to": "+447700900412",
    "country": "GB",
    "status": "delivered",
    "error": null,
    "segments": 1,
    "price": "0.00834",
    "currency": "USD",
    "client_ref": "order-4521",
    "final_at": "2026-11-07T09:00:08Z"
  }
}

Verifique a assinatura

O cabeçalho contém o horário Unix t e a assinatura v1 = HMAC-SHA256 da string "t.raw_body" com o segredo do seu webhook, em hexadecimal. Calcule-a sobre o corpo bruto antes de interpretar o JSON, compare em tempo constante e rejeite eventos com mais de cinco minutos.

import crypto from "node:crypto";

export function verify(rawBody, header, secret) {
  const m = /^t=(\d+),v1=([0-9a-f]{64})$/.exec(header || "");
  if (!m || Math.abs(Date.now() / 1000 - Number(m[1])) > 300) return false;
  const want = crypto.createHmac("sha256", secret).update(m[1] + "." + rawBody).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(want), Buffer.from(m[2]));
}

Status

queuedAceita e aguardando para sair da fila
submittedEntregue à rede de destino
deliveredConfirmada pelo aparelho (final)
failedNão foi possível entregar; o valor é reembolsado (final)
canceledParte de uma campanha agendada cancelada antes do envio (final)

O status da campanha é scheduled, sending, complete ou canceled.

Erros

Os erros respondem com um status HTTP e um corpo JSON: { "error": { "code": "insufficient_balance", "message": "..." } }. Nada é cobrado quando uma requisição responde com erro.

HTTPCódigoSignificado
400invalid_requestUm campo está ausente ou não é válido; a mensagem indica qual.
400invalid_jsonO corpo não é JSON.
400no_valid_numbersNenhum dos números pôde ser lido.
401unauthorizedA chave está ausente, malformada ou foi substituída.
402insufficient_balanceO saldo não cobre o custo; recarregue e envie novamente.
404not_foundId ou endpoint desconhecido.
409not_scheduledSomente uma campanha agendada que ainda não começou pode ser cancelada.
413too_many_recipientsMais de 10,000 números em uma só requisição.
429rate_limitedMais de 300 requisições em um minuto.
500server_errorRepita a requisição; nada foi cobrado.

Obtenha uma chave de API no console

Crie uma conta, adicione a sua primeira recarga e gere uma chave em API. Sua primeira requisição pode sair um minuto depois.

Criar conta
Referência da API de SMS em massa: endpoints REST e webhooks | BulkSMSOnline