Procurando pelo Sinch Engage? Você está agora no site principal da Sinch. Voltar para o Sinch Engage

Desenvolvedores

Enviar SMS com a Sinch Conversation API em curl, Node.js e Python

Imagem para Enviar SMS com a Sinch Conversation API em curl, Node.js e Python

A Conversation API é assim que você envia SMS com a Sinch. Toda mensagem passa por um único endpoint, POST https://{region}.conversation.api.sinch.com/v1/projects/{project_id}/messages:send, e o mesmo endpoint abrange RCS, WhatsApp e os outros canais de envio de mensagens. A solicitação que você escreve hoje para uma mensagem de texto tem o mesmo formato que você usará ao adicionar um segundo canal mais tarde. Este post configura um aplicativo da Conversation API com o canal de SMS e envia uma mensagem de três maneiras: com curl, com o SDK do Node.js e com o SDK do Python. Escolha a opção que corresponde à sua stack. Cada um é um script curto que você pode executar no terminal.

Você precisará de

  • Uma conta da Sinch (Cadastre-se). Novas contas incluem um número de teste.
  • Um telefone que possa receber SMS. Contas de teste podem limitar para quais números você pode enviar, portanto, verifique o destinatário nas configurações da conta no painel.
  • Você precisa de curl e jq para a versão shell, Node.js 20 ou posterior para Node.js, ou Python 3.9 ou posterior para Python.

Configurar um aplicativo da Conversation API

A Conversation API envia mensagens de um aplicativo. O aplicativo contém os canais que você conectou, e o canal de SMS vincula o aplicativo ao plano de serviço de SMS ao qual o número pertence.

  1. No painel da Sinch, abra a “Conversation API” no menu à esquerda. Aceite os termos e clique em “OBTER ACESSO” se você não a usou antes.
  2. Vá para “Configurações”, depois “Chaves de acesso” e crie uma chave de acesso. Copie o ID da chave e o segredo da chave. O segredo é exibido apenas uma vez.
  3. Vá para “Conversation API”, depois “Aplicativos” e crie um aplicativo. Escolha a região que corresponde ao plano de serviço de SMS: EUA, UE ou Brasil. Copie o ID do aplicativo.
  4. No aplicativo, clique em “CONFIGURAR CANAL” na linha de “SMS”, escolha o plano de serviço no menu suspenso e confirme.

Veja de onde vem cada valor:

Variável de ambienteOnde encontrar
SINCH_PROJECT_IDConfigurações, Configurações do projeto
SINCH_KEY_ID, SINCH_KEY_SECRETConfigurações, Chaves de acesso
SINCH_APP_IDConversation API, Aplicativos. O ID do aplicativo, não o ID do projeto
SINCH_SMS_SENDERNúmeros, Seus números. O número atribuído ao plano de serviço, no formato E.164
SINCH_REGIONA região onde você criou o aplicativo: us, eu ou br

Exporte-as no shell:

                                

                                    export SINCH_PROJECT_ID="YOUR_PROJECT_ID"
export SINCH_KEY_ID="YOUR_KEY_ID"
export SINCH_KEY_SECRET="YOUR_KEY_SECRET"
export SINCH_APP_ID="YOUR_APP_ID"
export SINCH_SMS_SENDER="+12025550123"
export SINCH_REGION="us"
                                
                            

Mantenha o segredo da chave fora do controle de versão. Na produção, carregue-o de um gerenciador de segredos.

Enviar um SMS com curl

Duas solicitações. A primeira troca a chave de acesso por um token OAuth 2.0 de https://auth.sinch.com/oauth2/token, que dura cerca de uma hora. A segunda envia a mensagem para o endpoint messages:send na região do aplicativo.

Salve isto como send-sms.sh:

                                

                                    #!/usr/bin/env bash
# Send one SMS with the Sinch Conversation API using curl and jq.
# Usage: bash send-sms.sh +15551234567 "Hello from Sinch"
set -euo pipefail

: "${SINCH_PROJECT_ID:?Set SINCH_PROJECT_ID}"
: "${SINCH_KEY_ID:?Set SINCH_KEY_ID}"
: "${SINCH_KEY_SECRET:?Set SINCH_KEY_SECRET}"
: "${SINCH_APP_ID:?Set SINCH_APP_ID}"
: "${SINCH_SMS_SENDER:?Set SINCH_SMS_SENDER}"
region="${SINCH_REGION:-us}"

to="${1:?Usage: send-sms.sh  }"
text="${2:?Usage: send-sms.sh  }"

if [[ ! "$to" =~ ^\+[1-9][0-9]{1,14}$ ]]; then
  echo "Use E.164 format for the number, for example +15551234567. Got: $to" >&2
  exit 1
fi

access_token=$(curl --silent --show-error --fail-with-body \
  https://auth.sinch.com/oauth2/token \
  --user "$SINCH_KEY_ID:$SINCH_KEY_SECRET" \
  --data grant_type=client_credentials | jq -r .access_token)

body=$(jq -n \
  --arg app_id "$SINCH_APP_ID" \
  --arg to "$to" \
  --arg text "$text" \
  --arg sender "$SINCH_SMS_SENDER" \
  '{
    app_id: $app_id,
    recipient: { identified_by: { channel_identities: [{ channel: "SMS", identity: $to }] } },
    message: { text_message: { text: $text } },
    channel_properties: { SMS_SENDER: $sender }
  }')

curl --silent --show-error --fail-with-body \
  "https://$region.conversation.api.sinch.com/v1/projects/$SINCH_PROJECT_ID/messages:send" \
  --header "Authorization: Bearer $access_token" \
  --header "Content-Type: application/json" \
  --data "$body"
echo
                                
                            

Construir o corpo com jq evita que as aspas e as quebras de linha na mensagem quebrem o JSON. Execute-o com o próprio número:

                                

                                    bash send-sms.sh +15551234567 "Hello from the Sinch Conversation API"
                                
                            
                                

                                    {"message_id":"01M613QSW2Q112R8FYHW29E5K9","accepted_time":"2026-10-28T11:18:46.402Z"}
                                
                            

O corpo da solicitação tem três partes que você usará em todos os envios:

  • recipient.identified_by.channel_identities define quem recebe a mensagem e em qual canal. Para SMS, a identidade é o número de telefone.
  • message.text_message.text é a mensagem. O mesmo objeto message transporta mídia, cartões e outros tipos em canais que têm suporte a eles.
  • channel_properties.SMS_SENDER é o número de onde a mensagem se origina. Você pode omiti-lo se o plano de serviço tiver um originador padrão. Defina-o de qualquer forma enquanto estiver no número de teste.

Envie um SMS com Node.js

A SDK do Node.js da Sinch gerencia o token para você. Instale-o com TypeScript e tsx:

                                

                                    npm init -y
npm pkg set type=module
npm install @sinch/sdk-core@1.7.0
npm install --save-dev typescript@5.9 tsx @types/node@24
mkdir -p src
                                
                            

Salve isto como src/send-sms.ts:

                                

                                    import { SinchClient } from "@sinch/sdk-core";

function requireEnv(name: string): string {
  const value = process.env[name];
  if (!value) {
    throw new Error(`Set the ${name} environment variable`);
  }
  return value;
}

const [to, text] = process.argv.slice(2);
if (!to || !text) {
  throw new Error('Usage: npm run send --  ""');
}
if (!/^\+[1-9]\d{1,14}$/.test(to)) {
  throw new Error(`Use E.164 format for the number, for example +15551234567. Got: ${to}`);
}

const sinchClient = new SinchClient({
  projectId: requireEnv("SINCH_PROJECT_ID"),
  keyId: requireEnv("SINCH_KEY_ID"),
  keySecret: requireEnv("SINCH_KEY_SECRET"),
  conversationRegion: process.env.SINCH_REGION ?? "us",
});

const response = await sinchClient.conversation.messages.sendTextMessage({
  sendMessageRequestBody: {
    app_id: requireEnv("SINCH_APP_ID"),
    recipient: {
      identified_by: {
        channel_identities: [{ channel: "SMS", identity: to }],
      },
    },
    message: { text_message: { text } },
    channel_properties: { SMS_SENDER: requireEnv("SINCH_SMS_SENDER") },
  },
});

console.log(`Accepted message ${response.message_id} at ${response.accepted_time?.toISOString()}`);
                                
                            

Adicione um script ao package.json e execute-o:

                                

                                    npm pkg set scripts.send="tsx src/send-sms.ts"
npm run send -- +15551234567 "Hello from the Sinch Node.js SDK"
                                
                            
                                

                                    Accepted message 01M613R541V5R0CMSY5BNP4DSA at 2026-10-28T11:18:57.921Z
                                
                            

O corpo da solicitação é o mesmo JSON da versão curl, com os mesmos nomes de campo em snake_case. sendTextMessage é o atalho tipado para uma mensagem de texto. conversationRegion tem us como padrão, portanto, defina-o se o aplicativo estiver em eu ou br.

Envie um SMS com Python

A SDK do Python da Sinch oferece suporte à Conversation API a partir da versão 2.0. Instale-o em um ambiente virtual:

                                

                                    python3 -m venv .venv
source .venv/bin/activate
pip install sinch==2.3.0
                                
                            

Salve isto como send_sms.py:

                                

                                    import os
import re
import sys

from sinch import SinchClient
from sinch.core.exceptions import SinchException


def require_env(name: str) -> str:
    value = os.environ.get(name)
    if not value:
        sys.exit(f"Set the {name} environment variable")
    return value


if len(sys.argv) != 3:
    sys.exit('Usage: python send_sms.py  ""')

to, text = sys.argv[1], sys.argv[2]
if not re.fullmatch(r"\+[1-9]\d{1,14}", to):
    sys.exit(f"Use E.164 format for the number, for example +15551234567. Got: {to}")

sinch_client = SinchClient(
    project_id=require_env("SINCH_PROJECT_ID"),
    key_id=require_env("SINCH_KEY_ID"),
    key_secret=require_env("SINCH_KEY_SECRET"),
    conversation_region=os.environ.get("SINCH_REGION", "us"),
)

try:
    response = sinch_client.conversation.messages.send_text_message(
        app_id=require_env("SINCH_APP_ID"),
        text=text,
        recipient_identities=[{"channel": "SMS", "identity": to}],
        channel_properties={"SMS_SENDER": require_env("SINCH_SMS_SENDER")},
    )
except SinchException as error:
    sys.exit(f"Sinch API error: {error}")

print(f"Accepted message {response.message_id} at {response.accepted_time}")
                                
                            
                                

                                    python send_sms.py +15551234567 "Hello from the Sinch Python SDK"
                                
                            
                                

                                    Accepted message 01M613R7AK2SST6VXH24HVF278 at 2026-10-28 11:19:00.179000+00:00
                                
                            

O SDK do Python aceita argumentos de palavra-chave em vez de um corpo de solicitação. Defina conversation_region todas as vezes: o cliente Python não tem uma região padrão para a Conversation API.

Aceito não é entregue

Uma resposta 200 com um message_id significa que a Sinch aceitou a mensagem. Saber se o telefone a recebeu vem depois, como um relatório de entrega enviado a um webhook no aplicativo. Para SMS, o relatório muda de QUEUED_ON_CHANNEL para DELIVERED ou FAILED. O número de telefone no relatório retorna sem o + inicial, portanto, normalize os números antes de corresponder os relatórios aos destinatários.

Para obter relatórios, adicione um webhook ao aplicativo com o gatilho MESSAGE_DELIVERY. No painel, abra o aplicativo e adicione-o em Webhooks. Com a API, obtenha um token e faça uma solicitação:

                                

                                    SINCH_ACCESS_TOKEN=$(curl --silent --show-error --fail-with-body \
  https://auth.sinch.com/oauth2/token \
  --user "$SINCH_KEY_ID:$SINCH_KEY_SECRET" \
  --data grant_type=client_credentials | jq -r .access_token)

curl --silent --show-error --fail-with-body \
  "https://$SINCH_REGION.conversation.api.sinch.com/v1/projects/$SINCH_PROJECT_ID/webhooks" \
  --header "Authorization: Bearer $SINCH_ACCESS_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "app_id": "YOUR_APP_ID",
    "target": "https://example.com/sinch/callbacks",
    "target_type": "HTTP",
    "triggers": ["MESSAGE_DELIVERY", "MESSAGE_INBOUND"]
  }'
                                
                            

MESSAGE_INBOUND também envia as respostas. Um relatório de falha inclui um reason com um código que informa o motivo. É aí que um número de remetente rejeitado ou um destinatário para o qual a conta não pode enviar aparece. A Sinch tenta novamente um webhook que não responde com um 2xx, então o manipulador precisa lidar com a possibilidade de receber o mesmo relatório duas vezes.

Por que a solicitação tem este formato

Vale a pena explicar algumas escolhas nestes scripts, pois a documentação mostra outras opções.

OAuth 2.0 em vez de Basic auth

A Conversation API também aceita o ID da chave e o segredo como Basic auth diretamente em messages:send, e o guia de introdução o utiliza para a primeira chamada. O Basic auth tem um limite de taxa severo e destina-se a testes. A solicitação de token é uma chamada extra, os SDKs fazem isso para você e é o que será executado na produção, portanto, o script curl o utiliza desde o início.

identified_by em vez de contact_id

Você pode endereçar uma mensagem para um número de telefone com identified_by, ou para um contato que a API armazenou anteriormente com contact_id. Aplicativos criados após 16 de abril de 2025 usam o modo Dispatch por padrão, que não armazena contatos, de modo que contact_id não tem para onde apontar. identified_by funciona em ambos os modos. Mude o aplicativo para o modo Conversation se quiser que os contatos e o histórico da conversa sejam armazenados.

Definir SMS_SENDER todas as vezes

Sem SMS_SENDER, a mensagem é enviada do originador padrão do plano de serviço, se houver um. O número de teste em uma nova conta precisa que ele seja definido. Um remetente que a rede rejeita não causa falha na solicitação HTTP: ele aparece depois como um relatório de entrega FAILED. Defini-lo explicitamente torna o remetente visível no código, em vez de em uma configuração no painel.

Aponte o agente de programação para a API correta

Agentes de programação aprenderam com anos de exemplos na web, e muitos deles usam a API de SMS independente e mais antiga (XMS). Essa API chegou ao fim das vendas em 15 de abril de 2026, e continua disponível apenas para integrações já criadas nela. Qualquer coisa nova deve usar a Conversation API, mesmo em uma conta que já tenha usado a API de SMS antes. Se você tem código na API de SMS, Migrar da API de SMS da Sinch para a Conversation API o mapeia campo por campo.

Se você pedir a um agente para “enviar um SMS com a Sinch” e ele escrever um código para /xms/v1/, diga a ele qual API você deseja. Uma linha no AGENTS.md ou CLAUDE.md do projeto faz isso para todas as sessões:

                                

                                    ## Sinch
- Send SMS with the Sinch Conversation API (`/v1/projects/{project_id}/messages:send`), not the SMS API (`/xms/v1/`).
- Use `@sinch/sdk-core` (Node.js) or `sinch` (Python), with project ID, key ID, and key secret.
                                
                            

A Skills de agente da Sinch vão além. Elas fornecem ao agente os formatos de solicitação da Conversation API, as regras do canal de SMS e as etapas de configuração. A Os plugins da Sinch para Claude Code, Cursor e Gemini CLI agrupam essas skills com o Servidor MCP da Sinch, que também envia SMS por meio da Conversation API.

Solução de problemas

  • 404 em messages:send. A região no URL não corresponde à região do aplicativo. Um aplicativo criado na UE só pode ser acessado em eu.conversation.api.sinch.com. Verifique a região nas configurações do aplicativo e defina SINCH_REGION para corresponder.
  • 401 no endpoint de token. O ID da chave ou o segredo está incorreto, ou você usou um ID de projeto onde o ID da chave deveria estar. As chaves de acesso estão em Configurações, Chaves de acesso. Se perdeu o segredo, crie uma nova chave.
  • 400 mencionando o canal. O aplicativo não tem o canal de SMS configurado ou o canal não está vinculado a um plano de serviço. Abra o aplicativo e verifique a linha de SMS.
  • A API aceitou a mensagem, mas nada chegou. Verifique o relatório de entrega do message_id. Em uma conta de teste, verifique se o destinatário é um número para o qual a conta pode enviar. Para números dos EUA, o tráfego de um código longo de 10 dígitos precisa do registro de 10DLC marca e campanha.
  • O aplicativo está em uma região diferente do número. O aplicativo deve estar na mesma região do plano de serviço de SMS. Se não corresponderem, crie um novo aplicativo na região certa e configure o canal de SMS nele.

Próximas etapas

A partir daqui, a mesma solicitação envia para outros canais. Adicione RCS ou WhatsApp ao aplicativo, dê ao destinatário uma identidade para cada canal em channel_identities e defina channel_priority_order na solicitação, por exemplo ["RCS", "SMS"]. A página de conceitos-chave explica quando a Conversation API faz o fallback para o próximo canal. Se você tem código na API de SMS independente, Migrar da API de SMS da Sinch para a Conversation API abrange lotes, relatórios de entrega e mensagens de entrada.

Recursos adicionais