Desenvolvedores

Referência da API

Um endpoint para enviar, um para consultar o status, webhooks assinados com HMAC para os recibos. As chaves são emitidas no momento em que a conta é criada — não há nada para aprovar e ninguém para avisar por e-mail.

v1https://api.worldsms.io/v1

Primeiros passos

Três coisas ficam entre uma conta nova e uma mensagem entregue: um token, algum crédito e uma chave. Nenhuma delas envolve um humano.

  1. Crie uma conta — seu navegador gera o token, e esse token é a conta.
  2. Deposite. Mínimo de $40, em qualquer uma das moedas em a página de pagamentos.
  3. Crie uma chave de API no painel. Ela é exibida uma única vez; armazenamos apenas seu hash, exatamente como o token.

Uma chave com saldo zerado não pode enviar

A criação de chaves é deliberadamente bloqueada até que a conta tenha saldo. Uma credencial não utilizada por aí é um risco sem nenhuma vantagem, então o painel não gera uma até que haja algo para gastar.

Autenticação

Token de portador em cada solicitação. A chave identifica a conta; não há segundo fator, nenhuma assinatura na solicitação e nenhuma lista de IPs permitidos — a chave é toda a credencial, então trate-a como tal.

Authorization
Authorization: Bearer ws_live_9f2c…
TransporteSomente HTTPS. Uma requisição em HTTP simples é recusada, não redirecionada — um redirecionamento já teria vazado a chave.
EscopoUma chave gasta o saldo de uma conta. Crie uma chave por sistema que envia, para que um vazamento seja revogado de forma restrita.
RevogaçãoImediato. Uma chave revogada retorna 401 na próxima requisição; lotes em andamento já aceitos ainda são concluídos.
RecuperaçãoNenhuma. Guardamos um hash. Uma chave perdida é substituída, nunca recuperada.

Enviar mensagens

POST/v1/messages

Uma chamada, um ou vários destinatários, destinos combinados. Cada destinatário é precificado na taxa do seu próprio destino e cobrado por segmento. A chamada é aceita ou recusada por completo; ela nunca cobra você parcialmente.

Corpo da requisição

CampoTipoNotas
tostring[]Obrigatório. E.164, até 5.000 por chamada. Números que não correspondem a um destino precificado são rejeitados antes da cobrança.
textstringObrigatório. UTF-8. A contagem de segmentos segue o GSM 03.38 — veja segmentos.
fromstringID de remetente alfanumérico, com até 11 caracteres. Carregado onde a rota permite; veja IDs de remetente.
varsobject[]Valores de mesclagem opcionais, um objeto por destinatário, substituídos nos marcadores {{name}} antes de os segmentos serem contados.
callback_urlstringSubstituição opcional do webhook da conta, por lote.
referencestringOpcional. Retornado em cada recibo para que você possa vincular aos seus próprios registros.

Exemplo

send.sh
# one call, many recipients, mixed destinations
curl -X POST https://api.worldsms.io/v1/messages \
  -H "Authorization: Bearer $WORLDSMS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "ACME",
    "to":   ["+447700900123", "+33612345678"],
    "text": "Your code is 480913"
  }'
202 Accepted
{
  "batch_id": "b_7Kq2xR9wLm",
  "accepted": 2,
  "rejected": 0,
  "segments": 1,
  "cost_usd": 0.0353
}

0,0137 $ para o Reino Unido mais 0,0216 $ para a França — a tabela de preços aplicada por destino, não uma média combinada.

Agrupamento em lote

Um lote é aceito imediatamente e escoa a 200 mensagens por minuto por conta, então 50.000 destinatários levam cerca de 4 h 10 min. Tráfego sensível ao tempo não deve ficar na fila atrás de um envio de marketing: use uma chave separada para ele.

Status da mensagem

GET/v1/messages/{batch_id}

O polling é suportado e tem limite de taxa; os webhooks são o caminho pretendido. A resposta consolida o lote e lista o estado por destinatário.

200 OK
{
  "batch_id":    "b_7Kq2xR9wLm",
  "status":      "done",
  "sending":     0,
  "delivered":   1,
  "undelivered": 1,
  "refund_usd":  0.0216
}

refund_usd é liquidado uma única vez, quando o lote termina. Já está de volta no seu saldo quando você consegue lê-lo.

Saldo

GET/v1/balance

Verifique antes de um envio grande. Os saldos são mantidos internamente em micro-dólares inteiros — as taxas vão até quatro casas decimais, e um número de ponto flutuante não tem lugar em um extrato — e são retornados aqui arredondados para seis.

200 OK
{ "balance_usd": 412.905400, "currency": "USD" }

Confirmações de entrega

Um recibo é emitido por destinatário conforme a operadora o reporta. Esses são os únicos quatro estados; não existe uma categoria “desconhecido” que silenciosamente signifique “nós o perdemos”.

EstadoSignificadoCobrado
queuedAceito e aguardando sua vez no lote.Sim
sentRepassado à operadora, ainda sem confirmação.Sim
deliveredO aparelho confirmou o recebimento.Sim
undeliveredDesativado, bloqueado, ou o remetente foi recusado.Reembolsado

Números que nunca correspondem a um destino com preço definido são rejeitados no envio e nunca entram nesse ciclo de vida — eles não são cobrados e depois estornados, simplesmente não são cobrados.

Webhooks

Defina um endpoint no painel ou por lote com callback_url. Enviamos JSON via POST e esperamos um 2xx em até 5 segundos. Respostas fora do intervalo 2xx são repetidas seis vezes com backoff exponencial ao longo de aproximadamente uma hora, e então descartadas.

Payload

Envie um POST para seu endpoint
{
  "event":     "message.delivered",
  "batch_id":  "b_7Kq2xR9wLm",
  "to":        "+447700900123",
  "destination": "gb",
  "segments":  1,
  "cost_usd":  0.0137,
  "reference": "order-4471",
  "ts":        1785312041
}

Verificando a assinatura

Toda entrega carrega X-WorldSMS-Signature e X-WorldSMS-Timestamp. A assinatura é HMAC-SHA256(timestamp + "." + body) usando seu segredo de webhook. Compare em tempo constante e rejeite um timestamp com mais de cinco minutos, para que uma entrega capturada não possa ser reproduzida contra você depois.

verify.php
// $secret is the webhook secret from the dashboard
$raw  = file_get_contents('php://input');
$ts   = $_SERVER['HTTP_X_WORLDSMS_TIMESTAMP'] ?? '';
$sig  = $_SERVER['HTTP_X_WORLDSMS_SIGNATURE'] ?? '';

// A stale timestamp is a replay, however well it is signed.
if (abs(time() - (int) $ts) > 300) { http_response_code(408); exit; }

$mine = hash_hmac('sha256', $ts . '.' . $raw, $secret);
if (!hash_equals($mine, $sig)) { http_response_code(401); exit; }

http_response_code(204);

Seja idempotente

Uma nova tentativa depois que seu endpoint expirou parece idêntica a uma primeira entrega. Use como chave batch_id + to + event e trate uma repetição como uma operação nula.

Erros

Toda falha retorna um corpo JSON com um slug estável em error. Faça a correspondência pelo slug, nunca pelo texto — o texto pode ser aprimorado.

HTTPSlugO que fazer
400invalid_bodyJSON malformado ou um campo obrigatório ausente.
401key_rejectedChave ausente, revogada ou digitada errada. Não é possível tentar novamente.
402insufficient_creditO lote custa mais do que o saldo. Nada foi enviado; recarregue e reenvie.
422no_valid_recipientsNenhum número foi resolvido para um destino com preço.
422sender_id_invalidfrom tem mais de 11 caracteres ou contém uma string só de dígitos que seria lida como um número.
429rate_limitedReduza o ritmo. Retry-After traz o número de segundos.
503route_unavailableUm destino está temporariamente sem rota. É possível tentar novamente.
402 Payment Required
{
  "error":       "insufficient_credit",
  "message":     "Batch costs $84.20, balance is $12.05.",
  "required_usd": 84.20,
  "balance_usd":  12.05
}

Limites

Solicitações60 por minuto por chave, com pico de 20. 429 com Retry-After acima disso.
Destinatários por chamada5.000. Divida listas maiores entre chamadas, ou envie o arquivo no painel.
Tamanho do corpo2 MB.
Vazão200 mensagens por minuto por conta, independentemente de quantas chaves enviarem.
ChavesSem limite. Um por sistema de envio é o padrão pretendido.

Os limites de taxa se aplicam às chamadas de API, não às mensagens: uma chamada com 5.000 destinatários custa uma requisição contra o limite.

As chaves são emitidas instantaneamente. Não há etapa de aprovação.

Financie uma conta e o painel cria um na hora.

Pergunte algo específico

Crie sua conta

Um botão. Seu navegador gera um token de 160 bits, e esse token é a conta. Não há mais nada para preencher e ninguém para esperar.

PortuguêsPT · Alterar idioma

Idioma