---
title: "Enviar SMS por API: exemplos em Python, Node.js, PHP e cURL"
description: "Envie SMS por API em Python, Node.js, PHP e cURL: envio único e em massa, Unicode e árabe, contagem de segmentos, webhooks de entrega e tratamento de erros."
canonical: "https://omnichannels.ai/pt/blog/send-sms-api-examples/"
language: "pt"
updated: "2026-10-16"
publisher: "BroadNet Technologies"
brand: "OmniChannels.ai"
category: "integration"
primaryQuery: "enviar sms api python"
keywords: ["enviar sms python", "exemplo api de sms node.js", "api de sms php", "api de sms curl", "api de sms unicode árabe", "webhook de relatório de entrega sms", "exemplo api de sms em massa"]
published: "2026-10-16"
author: "OmniChannels.ai Editorial Team"
reviewer: "BroadNet Messaging Solutions Team"
readingMinutes: 10
answer: "Para enviar um SMS com a API da OmniChannels.ai, faça um POST autenticado para https://api.broadnet.me/sms/sendSms com um corpo JSON contendo senderId, destinationNumber, message e messageType. Use TEXT para texto GSM-7 e UNICODE para árabe ou emoji. Uma resposta 200 devolve o ID da mensagem como texto simples, e o status final de entrega chega depois ao seu webhook."
takeaways: ["POST /sms/sendSms exige quatro campos: senderId, destinationNumber, message e messageType; o corpo da resposta é o ID da mensagem como texto simples, não JSON.", "Defina messageType como UNICODE para árabe, emoji ou qualquer caractere fora do GSM-7; um único caractere assim torna a mensagem inteira Unicode e encurta cada segmento.", "POST /sms/identify conta caracteres e segmentos antes do envio, para você prever quantos segmentos uma mensagem usa.", "A entrega é assíncrona: um 200 significa aceita, e DELIVERED, FAILED ou REJECTED chega depois ao seu webhook.", "A API não tem chave de idempotência, então registre cada envio antes de fazê-lo e verifique o status após um timeout em vez de reenviar."]
faq: 
  - q: "Como envio um SMS com Python?"
    a: "Use a biblioteca requests para fazer um POST de JSON para https://api.broadnet.me/sms/sendSms com um cabeçalho Authorization: Bearer e os campos senderId, destinationNumber, message e messageType. Leia o token de uma variável de ambiente. O corpo de uma resposta 200 é o ID da mensagem como texto simples, então use r.text em vez de r.json()."
  - q: "Que formato de número de telefone a API de SMS espera?"
    a: "Código do país mais número nacional, apenas dígitos, sem sinal de mais, prefixo 00, espaços nem zero à esquerda. Por exemplo, 447700900123 é válido, enquanto +44 7700 900123 e 07700900123 não são. Guarde os números em E.164 no seu banco de dados e remova o sinal de mais ao montar a requisição."
  - q: "Como envio SMS em árabe pela API?"
    a: "Defina messageType como UNICODE e envie o texto em árabe no campo message em UTF-8. Mensagens Unicode comportam 70 caracteres em um segmento único e 67 por segmento quando divididas, contra 160 e 153 do GSM-7. Teste em aparelhos reais e chame /sms/identify para ver antes a contagem de segmentos."
  - q: "Como obtenho os relatórios de entrega?"
    a: "Os status são enviados por push para a URL de webhook configurada na sua conta. As mensagens passam por SUBMITTED e SENT até DELIVERED, FAILED ou REJECTED. Seu endpoint deve armazenar o evento bruto, responder 2xx rapidamente e processar de forma assíncrona. Se eventos foram perdidos, POST /sms/resendDlr pode reenviar relatórios de entrega de um intervalo de datas."
  - q: "Como envio SMS para muitos números de uma vez?"
    a: "Use POST /sms/sendbulk, uma requisição multipart com um destinationNumberFile (CSV ou TXT) e uma string JSON bulkRequest contendo senderId, message e messageType. A resposta informa quantos números eram válidos, inválidos ou duplicados e devolve um bulkSessionId que você pode guardar com a sua campanha."
  - q: "Preciso registrar um sender ID?"
    a: "Em muitos países, sim. Alguns exigem um sender ID alfanumérico aprovado, e outros precisam de identificadores do regulador ou de templates, que a API aceita em campos opcionais como peId e templateId. Os requisitos variam por país, então consulte a página de sender ID do seu destino, e nossa equipe pode cuidar do registro com você."
sources: 
  - title: "3GPP TS 23.040: Technical realization of the Short Message Service (SMS)"
    url: "https://www.3gpp.org/dynareport?code=23040"
  - title: "ITU-T E.164: The international public telecommunication numbering plan"
    url: "https://www.itu.int/rec/T-REC-E.164"
  - title: "RFC 9110: HTTP Semantics"
    url: "https://www.rfc-editor.org/rfc/rfc9110"
---

# Enviar SMS por API: exemplos em Python, Node.js, PHP e cURL

Canonical: https://omnichannels.ai/pt/blog/send-sms-api-examples/
Language: pt
Publisher: OmniChannels.ai by BroadNet Technologies

Este guia é para desenvolvedores que precisam enviar SMS a partir de uma aplicação e querem código funcional em Python, Node.js, PHP ou cURL. Ele cobre um envio único, Unicode e árabe, contagem de segmentos, upload em massa, webhooks de status de entrega e tratamento de erros, usando apenas endpoints e campos da nossa [referência da API de SMS](/developers/sms/) e da especificação OpenAPI.

## Como envio um SMS com a API?

Faça um `POST` autenticado para `/sms/sendSms` com um corpo JSON. A resposta é `200 OK` com o ID da mensagem como texto simples.

| Item | Valor |
|---|---|
| URL base | `https://api.broadnet.me` (sem prefixo `/v1`) |
| Endpoint | `POST /sms/sendSms` |
| Autenticação | `Authorization: Bearer $BROADNET_TOKEN` |
| Tipo de conteúdo | `application/json` |
| Campos obrigatórios | `senderId`, `destinationNumber`, `message`, `messageType` |

As credenciais de teste são emitidas após uma breve solicitação de acesso, e os envios de teste vão para os seus próprios números verificados. Não há cadastro self-service instantâneo. Veja o [quickstart](/developers/quickstart/).

```bash
curl -X POST https://api.broadnet.me/sms/sendSms \
  -H "Authorization: Bearer $BROADNET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "senderId": "OmniDemo",
    "destinationNumber": "447700900123",
    "message": "Your OmniDemo code is 482913",
    "messageType": "TEXT"
  }'
```

```js
// Node.js 18+ (fetch nativo)
const res = await fetch("https://api.broadnet.me/sms/sendSms", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.BROADNET_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    senderId: "OmniDemo",
    destinationNumber: "447700900123",
    message: "Your OmniDemo code is 482913",
    messageType: "TEXT",
  }),
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const messageId = await res.text(); // ID da mensagem em texto simples
```

```python
import os
import requests

r = requests.post(
    "https://api.broadnet.me/sms/sendSms",
    headers={"Authorization": f"Bearer {os.environ['BROADNET_TOKEN']}"},
    json={
        "senderId": "OmniDemo",
        "destinationNumber": "447700900123",
        "message": "Your OmniDemo code is 482913",
        "messageType": "TEXT",
    },
    timeout=15,
)
r.raise_for_status()
message_id = r.text  # ID da mensagem em texto simples, não JSON
```

```php
<?php
$payload = json_encode([
    "senderId" => "OmniDemo",
    "destinationNumber" => "447700900123",
    "message" => "Your OmniDemo code is 482913",
    "messageType" => "TEXT",
]);

$ch = curl_init("https://api.broadnet.me/sms/sendSms");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 15,
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer " . getenv("BROADNET_TOKEN"),
        "Content-Type: application/json",
    ],
    CURLOPT_POSTFIELDS => $payload,
]);
$messageId = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $status . " " . $messageId . PHP_EOL;
```

O corpo de uma resposta bem-sucedida tem este aspecto:

```text
2603121407537573731
```

Salve esse ID junto ao seu próprio registro, como um pedido ou uma tentativa de login. É com ele que você associa os status de entrega depois.

## Como formatar os números de telefone?

Use código do país mais número nacional, apenas dígitos. O formato segue o plano internacional de numeração da ITU-T E.164, sem o sinal de mais.

| Entrada | Válido? | Por quê |
|---|---|---|
| `447700900123` | Sim | Código do país 44 mais número nacional |
| `+44 7700 900123` | Não | Remova o sinal de mais e os espaços |
| `07700900123` | Não | Troque o 0 inicial pelo código do país |

Guarde os números em E.164 (`+447700900123`) no banco de dados e remova o `+` ao montar a requisição. Nosso formatador de números de telefone gratuito ajuda em uma conferência rápida.

## Como envio árabe, emoji ou outro texto Unicode?

Defina `messageType` como `UNICODE`. Qualquer caractere fora do alfabeto GSM-7, como uma letra árabe, um emoji, aspas curvas ou um travessão longo, muda a mensagem inteira para Unicode.

```python
r = requests.post(
    "https://api.broadnet.me/sms/sendSms",
    headers={"Authorization": f"Bearer {os.environ['BROADNET_TOKEN']}"},
    json={
        "senderId": "OmniDemo",
        "destinationNumber": "971500000000",
        "message": "رمز التحقق الخاص بك هو 482913",
        "messageType": "UNICODE",
        "campaignName": "login-otp",
    },
    timeout=15,
)
```

Em PHP, use `JSON_UNESCAPED_UNICODE` ao chamar `json_encode`. A codificação define o tamanho do segmento, conforme definido para SMS na 3GPP TS 23.040:

| `messageType` | SMS único | Por segmento quando dividido | Use para |
|---|---|---|---|
| `TEXT` | 160 caracteres | 153 caracteres | Texto que use apenas o alfabeto GSM-7 |
| `UNICODE` | 70 caracteres | 67 caracteres | Árabe, cirílico, chinês, emoji |

A maioria das operadoras cobra por segmento, então uma mensagem longa em árabe custa mais do que uma do mesmo tamanho em alfabeto latino. Leia nosso [guia de SMS em Unicode e árabe](/pt/blog/sms-character-limits-unicode-arabic/) e experimente o contador de caracteres de SMS.

## Como contar segmentos antes de enviar?

Chame `POST /sms/identify` com a mensagem. Ele devolve a codificação detectada, a contagem de caracteres, a contagem de segmentos e o limite por segmento.

```bash
curl -X POST https://api.broadnet.me/sms/identify \
  -H "Authorization: Bearer $BROADNET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "message": "Your OmniDemo code is 482913" }'
```

```json
{
  "message": "Your OmniDemo code is 482913",
  "messageType": "TEXT",
  "smscount": 1,
  "charCount": 28,
  "charLimit": 160
}
```

Você pode passar `smsParts` (de `smscount`), `charCount` e `charLimit` em uma requisição de envio. O texto GSM-7 pode aparecer rotulado como `GSM-7` na resposta; envie-o como `TEXT`.

## Como envio para muitos números?

Use `POST /sms/sendbulk`, uma requisição `multipart/form-data` com um arquivo de destinatários e uma string JSON de configurações.

```bash
curl -X POST https://api.broadnet.me/sms/sendbulk \
  -H "Authorization: Bearer $BROADNET_TOKEN" \
  -F destinationNumberFile=@recipients.csv \
  -F 'bulkRequest={"senderId":"OmniDemo","message":"Your statement is ready in the app.","messageType":"TEXT","campaignName":"oct-statements","allowDuplicate":false}'
```

```python
import json
import os
import requests

bulk_request = {
    "senderId": "OmniDemo",
    "message": "Your statement is ready in the app.",
    "messageType": "TEXT",
    "campaignName": "oct-statements",
    "allowDuplicate": False,
}

with open("recipients.csv", "rb") as f:
    r = requests.post(
        "https://api.broadnet.me/sms/sendbulk",
        headers={"Authorization": f"Bearer {os.environ['BROADNET_TOKEN']}"},
        files={"destinationNumberFile": ("recipients.csv", f, "text/csv")},
        data={"bulkRequest": json.dumps(bulk_request)},
        timeout=60,
    )
print(r.json())
```

A resposta inclui `bulkSessionId` e um objeto `bulkListInfo` com `total`, `validCount`, `invalidCount` e `duplicate`. Guarde o `bulkSessionId` com a campanha. Os jobs podem ser listados, pausados, retomados e abortados com os endpoints da referência. Você também pode verificar números antes de um envio grande com `POST /sms/lookup`; veja nosso [guia de consulta HLR](/pt/blog/hlr-lookup-number-validation/).

## Como recebo o status de entrega?

Os status de entrega são enviados por push para a URL de webhook configurada na sua conta. Uma mensagem passa por `SUBMITTED` e `SENT` até `DELIVERED` ou termina como `FAILED` ou `REJECTED`. Você informa à nossa equipe a URL HTTPS pública, e os revendedores podem ter um webhook por subconta.

Os campos do payload variam por canal, e a especificação da API não define um único esquema de webhook, então registre primeiro o corpo bruto e mapeie os campos a partir de um evento real da sua conta. Um receptor mínimo armazena o evento e confirma rapidamente:

```js
import express from "express";

const app = express();

app.post("/webhooks/omnichannels", express.json(), async (req, res) => {
  await saveStatusEvent(req.body); // seu armazenamento; processe de forma assíncrona
  res.sendStatus(200);             // confirme rápido
});

app.listen(3000);
```

Torne o processamento idempotente, porque o mesmo status pode chegar duas vezes, e nunca deixe um `SENT` tardio sobrescrever um `DELIVERED` já armazenado. Se o seu endpoint estava fora do ar, `POST /sms/resendDlr` reenvia os relatórios de um intervalo de datas:

```bash
curl -X POST https://api.broadnet.me/sms/resendDlr \
  -H "Authorization: Bearer $BROADNET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "startDate": "2026-10-09",
    "endDate": "2026-10-10",
    "senderId": "OmniDemo",
    "messageStatus": "DELIVERED"
  }'
```

Leia mais no [guia de webhooks](/developers/webhooks/) e em status de entrega de mensagens explicados.

## Como tratar erros e evitar duplicatas?

Trate primeiro o status HTTP e depois o corpo do erro. Tente de novo apenas em erros de rede, `429` e `5xx`.

| Código | Significado | Ação |
|---|---|---|
| `200` | Aceita | Guarde o ID |
| `400` | Erro de validação ou campo ausente | Corrija a requisição |
| `401` / `403` | Token inválido ou operação não permitida | Corrija; não tente de novo |
| `429` | Limite de taxa excedido | Aguarde o `Retry-After` |
| `500`, `503`, `504` | Problema no servidor ou a montante | Tente de novo com backoff e jitter |

Os erros gerados pela API usam um corpo JSON de cinco campos, com `status`, `error`, `message`, `errorCode` e `requestUri`. O limite REST padrão documentado é de 200 requisições por segundo de forma sustentada; os limites da sua conta são confirmados junto com as suas credenciais.

A API não aceita chave de idempotência. Uma requisição pode ter sucesso enquanto a resposta se perde, e uma nova tentativa às cegas então envia duas vezes. Grave uma linha pendente, com a sua própria chave de operação, antes de chamar, guarde o ID da mensagem devolvido e, após um timeout, verifique se há um status por webhook antes de enviar de novo. Em envios em massa, defina `allowDuplicate` como `false`. Os detalhes estão em [Erros e limites](/developers/errors-and-limits/).

## Exemplo prático: códigos de login para um app regional

A "Souq Rafiq" (sintética), uma varejista dos Emirados Árabes Unidos, envia códigos de login por SMS.

1. O serviço de autenticação gera um código de seis dígitos, guarda um hash com expiração de cinco minutos e grava uma linha de envio `pending`.
2. Ele chama `/sms/sendSms` com `messageType=UNICODE` para usuários de árabe e `TEXT` para usuários de inglês.
3. Em um `200`, guarda o ID da mensagem.
4. O handler do webhook marca a linha como `DELIVERED`, `FAILED` ou `REJECTED`.
5. Se o status não for `DELIVERED` após uma curta espera, o app oferece um reenvio e, se configurado, outro canal. Veja fallback entre canais.
6. Limites de taxa para solicitações de código por número e por IP protegem contra abusos; veja [prevenção de SMS pumping](/pt/blog/sms-pumping-fraud-prevention/).

## Quais são os erros comuns?

- **Chamar `r.json()` na resposta do envio.** Ela é texto simples.
- **Nomes de campos errados.** Use `senderId`, `destinationNumber` e `message`; campos como `to`, `from` ou `text` não fazem parte deste endpoint.
- **Sinais de mais e zeros à esquerda** nos números.
- **Esquecer o `UNICODE`** no árabe, o que corrompe o texto.
- **Sender IDs não registrados.** Alguns países os bloqueiam ou substituem; confira as regras de sender ID do seu destino e peça que cuidemos do registro.
- **Tratar o `200` como entregue.**
- **Token em um app móvel ou no navegador,** onde qualquer pessoa pode extraí-lo.
- **Limites:** este guia mostra a requisição comum. Campos opcionais, como os formatos de agendamento, devem ser confirmados com a nossa equipe.

## Como a OmniChannels.ai ajuda

A OmniChannels.ai envia SMS A2P pela conectividade direta com operadoras da BroadNet, com SMS bidirecional, sender IDs, Unicode e árabe, consulta HLR e SMPP 3.4 para alto volume. A API REST em `https://api.broadnet.me` usa um token Bearer e também cobre WhatsApp, RCS e outros canais, com status de entrega normalizados em um único formato de webhook. Nossa equipe prepara com você os registros de sender ID. Veja a [referência da API de SMS](/developers/sms/) ou o canal de SMS.
