Documentação da API de SMS para envio a partir do seu próprio código

Uma pequena API REST na mesma conta, preços e saldo do espaço de trabalho: envie uma mensagem ou um lote de até 5,000 números, estime o custo primeiro, acompanhe cada mensagem e receba eventos de entrega na sua URL de webhook.

URL base: https://sendsmsonline.cc/api/v1

Início rápido

  1. 1. Crie uma chave. No espaço de trabalho, abra API e webhooks. As chaves são liberadas após sua primeira recarga creditada; cada chave é exibida uma vez, então copie-a ou salve-a como um arquivo de texto.
  2. 2. Verifique o custo. Envie o mesmo corpo para /costs para ver destinatários, segmentos e o total sem enviar.
  3. 3. Envie. Envie para /sends. A resposta contém o ID do envio; as mensagens são enviadas imediatamente ou em send_at.
curl https://sendsmsonline.cc/api/v1/sends \
  -H "Authorization: Bearer $SSO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "recipients": [ { "to": "+447700900461", "fields": { "first_name": "Tom" } }, { "to": "+12015550142", "fields": { "first_name": "Ava" } } ], "text": "Hi {{first_name}}, your table is ready at 7:30.", "name": "Friday bookings", "client_ref": "bookings-1107" }'

Autenticação

Envie sua chave no cabeçalho Authorization: Authorization: Bearer sso_live_.... As chaves têm 49 caracteres e começam com sso_live_. Até 5 chaves por conta; revogue uma no espaço de trabalho e ela para de funcionar imediatamente. A lista de preços é pública e não precisa de chave.

Erros

Os erros usam códigos de status HTTP e um corpo JSON com um código estável e uma frase que você pode mostrar a uma pessoa. Nada é cobrado quando uma solicitação falha.

HTTP/1.1 402 Payment Required
{ "error": { "code": "insufficient_credit", "message": "Short by $3.20. Add funds to send.", "total": "8.62480", "credit": "5.42000" } }
CampoSignificado
400A solicitação precisa de uma alteração.
401Chave ausente, incorreta ou revogada.
402Saldo insuficiente para o total.
404Nenhum envio, mensagem, país ou endpoint encontrado.
409O envio já começou.
429Mais de 240 solicitações em um minuto.

Limites

  • 240 solicitações por minuto por chave, mostradas em X-RateLimit-Limit, X-RateLimit-Remaining e X-RateLimit-Reset (segundos unix).
  • 5,000 números por solicitação, 2,000 caracteres por texto, 10 segmentos por mensagem.
  • As mensagens são enviadas a até 300 por minuto por conta.
  • send_at de 10 minutos a 30 dias à frente.

Preços

GET/api/v1/prices

GET/api/v1/prices/{country}

O preço por mensagem (um segmento) para cada país, em USD com 5 decimais. Nenhuma chave necessária.

{ "price": { "country": "GB", "name": "United Kingdom", "dial_code": "+44", "price_usd": "0.00868" }, "updated": "2026-11-07" }

Saldo da conta

GET/api/v1/account

{ "account": "SO8K2M4Q7X9TBA", "credit_usd": "41.27660", "currency": "USD" }

Estimar um custo

POST/api/v1/costs

Recebe o mesmo corpo de um envio e retorna o custo, sem enviar ou cobrar. O texto mesclado de cada destinatário decide seus segmentos, então o total é exato.

{
  "recipients": 2, "segments_min": 1, "segments_max": 1, "encoding": "gsm7", "messages_billed": 2,
  "total_usd": "0.01426", "credit_usd": "41.27660", "enough_credit": true,
  "countries": [ { "country": "GB", "recipients": 1, "price_usd": "0.00868", "subtotal_usd": "0.00868" },
                 { "country": "US", "recipients": 1, "price_usd": "0.00558", "subtotal_usd": "0.00558" } ],
  "dropped": [], "too_long": null
}

Criar um envio

POST/api/v1/sends

Um texto para um ou vários números. O crédito para todo o envio é debitado quando ele é aceito; mensagens falhas são reembolsadas uma por uma.

CampoSignificado
toNúmeros no formato internacional (+447700900461). Use isso ou destinatários.
recipientsObjetos com to e fields, para campos de mesclagem: { "to": "+1...", "fields": { "first_name": "Ava" } }.
textA mensagem, até 2,000 caracteres. {{field}} é substituído por destinatário; valores ausentes ficam vazios.
send_atTempo ISO 8601 opcional com offset ou Z. Sem isso, o envio começa imediatamente.
nameRótulo opcional mostrado no espaço de trabalho (80 caracteres).
client_refReferência opcional retornada em webhooks (64 caracteres).
opt_outAdiciona a linha de opt-out salva em Configurações ao final do texto.
default_countryCódigo ISO usado para números escritos sem um código de país.
HTTP/1.1 201 Created
{
  "send": { "id": "CA7Q29XMAB4DFK", "status": "queued", "source": "api", "recipients": 2, "segments_max": 1,
            "encoding": "gsm7", "cost_usd": "0.01426", "refunded_usd": "0.00000", "client_ref": "bookings-1107",
            "send_at": null, "created_at": "2026-11-07T10:12:03.120Z", "started_at": null, "finished_at": null },
  "dropped": [ { "value": "+4412", "code": "too_short", "message": "Too short" } ]
}

Números que não podem ser enviados são listados em dropped e nunca cobrados. Códigos: no_country_code, too_short, too_long, not_a_number, wrong_length, not_covered, duplicate e suppressed (na sua lista de não enviar).

Obter ou listar envios

GET/api/v1/sends/{id}

GET/api/v1/sends?limit=25&before={id}

Um único envio inclui counts por status de mensagem. As listas são as mais recentes primeiro; passe next_before como before para a próxima página. Envios do espaço de trabalho também aparecem aqui, com source: "web".

Mensagens

GET/api/v1/sends/{id}/messages?status=failed&limit=100

GET/api/v1/messages/{id}

{ "message": { "id": "MS3D8RW0K2QJ7N", "send_id": "CA7Q29XMAB4DFK", "to": "+447700900461", "country": "GB",
  "segments": 1, "price_usd": "0.00868", "status": "delivered", "reason": null, "reason_text": null,
  "created_at": "2026-11-07T10:12:03.120Z", "sent_at": "2026-11-07T10:12:04.010Z", "done_at": "2026-11-07T10:12:09.400Z" } }

Cancelar um envio

POST/api/v1/sends/{id}/cancel

Apenas envios agendados que não começaram podem ser cancelados. O custo total retorna ao seu saldo e a resposta inclui refunded_usd.

Webhooks

Defina uma URL https no espaço de trabalho (API e webhooks). Enviamos um evento POST quando uma mensagem é entregue ou falha, para envios da API e do espaço de trabalho. Responda com qualquer status 2xx dentro de 10 segundos. Entregas falhas são tentadas novamente até 7 vezes no total: imediatamente, depois de 1 minuto, 5 minutos, 30 minutos, 1 hora, 2 horas e 3 horas. O espaço de trabalho mostra cada tentativa com seu status e resposta.

POST https://your-server.example/sms-events
X-SSO-Event: message.delivered
X-SSO-Delivery: evt_5a0c9e31d2b7f4a68c
X-SSO-Timestamp: 1794132729
X-SSO-Signature: sha256=8f1c...e42a

{ "id": "evt_5a0c9e31d2b7f4a68c", "event": "message.delivered", "created": "2026-11-07T10:12:09.000Z",
  "data": { "message": { "id": "MS3D8RW0K2QJ7N", "send_id": "CA7Q29XMAB4DFK", "to": "+447700900461", "country": "GB",
  "segments": 1, "price_usd": "0.00868", "status": "delivered", "reason": null, "reason_text": null,
  "client_ref": "bookings-1107", "created_at": "...", "sent_at": "...", "done_at": "..." } } }

A assinatura é HMAC-SHA256 de timestamp + "." + raw body com seu segredo de assinatura (começa com sso_whk_). Verifique no corpo bruto antes de analisar, rejeite timestamps mais antigos que 5 minutos e use o id de entrega para ignorar repetições.

import crypto from "node:crypto";

// rawBody: the request body exactly as received (a string), before JSON.parse
export function verify(rawBody, headers, secret) {
  const ts = headers["x-sso-timestamp"];
  const sig = headers["x-sso-signature"] || "";
  const want = "sha256=" + crypto.createHmac("sha256", secret).update(`${ts}.${rawBody}`).digest("hex");
  const fresh = Math.abs(Date.now() / 1000 - Number(ts)) < 300;
  return fresh && sig.length === want.length && crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(want));
}

Eventos: message.delivered, message.failed e test do botão Enviar evento de teste.

Statuses e motivos

CampoSignificado
queuedAguardando para sair da nossa fila.
sentEntregue à rede, aguardando o relatório de entrega. A maioria dos relatórios chega em minutos; algumas redes podem levar até 24 horas.
deliveredA rede confirmou que o telefone recebeu a mensagem.
failedNão entregue. O valor foi reembolsado ao seu saldo.
canceledNão enviado porque você cancelou. Reembolsado.

Motivos de falha (o campo reason):

CampoSignificado
network_errorErro de rede
absentTelefone desligado ou fora de cobertura
not_in_serviceNúmero não está em serviço
blockedBloqueado pela rede ou pelo destinatário
landlineLinha fixa ou número que não pode receber SMS
content_filterRejeitado pelo filtro de conteúdo da rede
expiredExpirado: nenhum relatório antes do limite de tempo da rede
canceledCancelado antes do envio
unknownResposta desconhecida da rede

Verificações de serviço estão na página de status e mudanças na API no changelog.

Obtenha sua chave API

Crie uma conta, adicione fundos uma vez e abra API e webhooks no espaço de trabalho. A mesma chave funciona para todos os países.

Crie uma conta gratuita
Documentação da API de SMS: Envie SMS em massa a partir do seu código | SendSMSOnline