Documentação pública

API de SMS e RCS

Dois endpoints REST cobrem a integração inteira: POST /messages dispara SMS ou RCS, POST /conversions amarra o R$ da venda à mensagem que a originou. Os status de entrega chegam por webhook no seu servidor. Autenticação por header, JSON nos dois sentidos, respostas e mensagens de erro em português.

Esta página é a mesma documentação que o cliente vê dentro do portal — nada aqui está resumido para a vitrine. Leia, copie os exemplos e decida antes de falar com a gente.

Como funciona, na prática

  1. 1Gere a chave em API & Chaves e mande tudo para a base https://www.rcsinc.com.br/api/v1.
  2. 2Dispare com POST /api/v1/messages (SMS ou RCS) — copie o cURL ou o trecho JavaScript abaixo.
  3. 3Receba os status apontando seu notifyUrl/webhook para captar entregue, lida, clicada e falhou.
  4. 4Feche o ROI chamando POST /api/v1/conversions quando o cliente compra.

Detalhes que pesam na decisão

  • Autentique toda requisição com o header x-api-key (formato rcsk_live_…) — sem ela, retorna 401.
  • Envie o header `Idempotency-Key` (UUID por operação) para que um retry de rede não dispare duas vezes.
  • O canal RCS cai automaticamente em SMS quando o número não recebe RCS — você não perde o contato.
  • O notifyUrl precisa ser público (http/https); endereços internos são bloqueados e o webhook tem timeout curto (best-effort).
REST · JSONv1

Base da API

Todas as chamadas usam HTTPS e trocam JSON. A base de todos os endpoints é:

Base URL
https://www.rcsinc.com.br/api/v1

Cada chave pertence a uma única conta. A API só envia e atribui receita dentro da sua conta.

Especificação OpenAPI 3.1: openapi.json — importe no Postman, no Insomnia ou em um gerador de cliente.

Autenticação

Autentique cada requisição com o header x-api-key. A chave tem o formato rcsk_live_… e é exibida uma única vez, no momento da criação.

Header
x-api-key: rcsk_live_SUA_CHAVE
Pedir acesso de teste

Guarde a chave em segredo (variável de ambiente). Vazou? Revogue e gere outra.

POST/api/v1/messages

Enviar mensagem

Dispara SMS ou RCS para um ou mais números. O canal RCS cai automaticamente em SMS quando o número não recebe RCS.

  • tostring | string[]obrigatório

    Destinatário(s) em formato E.164 (ex.: +5511999999999).

  • channel"SMS" | "RCS"

    Canal de envio. Padrão: SMS.

  • textstring

    Conteúdo de texto da mensagem.

  • mediaUrlstring

    URL pública de imagem/vídeo (RCS).

  • cardsCard[]

    Cards RCS ricos (title, description, mediaUrl, suggestions).

  • notifyUrlstring

    URL pública (http/https) que recebe os webhooks de status.

Envie ao menos um entre text, mediaUrl ou cards.

cURL
curl -X POST https://www.rcsinc.com.br/api/v1/messages \
  -H "x-api-key: rcsk_live_SUA_CHAVE" \
  -H "Content-Type: application/json" \
  -d '{
    "channel": "RCS",
    "to": ["+5511999999999"],
    "text": "Olá! Seu pedido foi confirmado.",
    "notifyUrl": "https://seusistema.com.br/webhooks/rcs"
  }'
JavaScript (fetch)
const res = await fetch("https://www.rcsinc.com.br/api/v1/messages", {
  method: "POST",
  headers: {
    "x-api-key": "rcsk_live_SUA_CHAVE",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    channel: "RCS",                 // "SMS" ou "RCS" (padrão: SMS)
    to: ["+5511999999999"],         // string ou array, sempre E.164
    text: "Olá! Seu pedido foi confirmado.",
    // mediaUrl: "https://.../imagem.jpg",   // opcional (imagem/vídeo)
    // cards: [ ... ],                        // opcional (RCS rico — title/description/mediaUrl/suggestions)
    notifyUrl: "https://seusistema.com.br/webhooks/rcs", // opcional: recebe status
  }),
});

const data = await res.json();
// { ok: true, sent: 1, failed: 0, suppressed: 0, cost: 0.18 }

Resposta

200 OK
{
  "ok": true,
  "sent": 1,
  "failed": 0,
  "suppressed": 0,
  "cost": 0.18
}

RCS rico (cards)

body de exemplo
{
  "channel": "RCS",
  "to": "+5511999999999",
  "cards": [
    {
      "title": "Black Friday",
      "description": "50% OFF só hoje",
      "mediaUrl": "https://cdn.seusite.com.br/promo.jpg",
      "suggestions": [
        { "type": "OPEN_URL", "text": "Comprar", "url": "https://loja.com.br/bf" },
        { "type": "REPLY", "text": "Quero saber mais", "postbackData": "INFO" }
      ]
    }
  ]
}
ConfiabilidadePOST /api/v1/messages

Idempotência

Redes falham e clientes fazem retry. Envie o header Idempotency-Key em cada POST /api/v1/messages para garantir que um reenvio acidental não dispare a mensagem duas vezes.

Mesma key + mesmo payload

Devolve a resposta original (mesmo status e corpo), sem disparar um novo envio. A resposta vem com o header Idempotent-Replayed: true.

Mesma key + payload diferente

Retorna 409 Conflict — a chave já foi usada para outro corpo. Use uma key nova para um envio diferente.

Key nova

Processa normalmente como um envio inédito. Gere um UUID por operação que você quer tornar segura para retry.

  • Idempotency-Keyvocê envia

    UUID único por operação (ex.: 550e8400-e29b-41d4-a716-446655440000).

  • Idempotent-Replayednós devolvemos

    Presente e true quando a resposta é uma repetição da original (nada novo foi enviado).

cURL — envio idempotente
curl -X POST https://www.rcsinc.com.br/api/v1/messages \
  -H "x-api-key: rcsk_live_SUA_CHAVE" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
  -d '{
    "channel": "RCS",
    "to": ["+5511999999999"],
    "text": "Olá! Seu pedido foi confirmado."
  }'

Dica: gere a key no seu lado (um UUID v4 por pedido/evento) e reaproveite a mesma key em todos os retries daquele mesmo envio. Assim, mesmo que a resposta se perca na rede, o reenvio é seguro — você nunca cobra ou notifica o cliente duas vezes.

POST/api/v1/conversions

Registrar conversão / receita

Amarre o R$ de cada venda à mensagem que a originou. É o que alimenta o ROI real na receita atribuída dos seus relatórios.

  • valuenumberobrigatório

    Valor da venda em R$ (≥ 0).

  • codestring

    Code do short-link que gerou o clique/venda.

  • campaignIdstring

    Atribui direto a uma campanha.

  • recipientstring

    Atribui ao número (E.164) que recebeu a mensagem.

  • orderIdstring

    Id do pedido — usado para evitar contagem duplicada.

Informe ao menos um entre code, campaignId ou recipient para a atribuição.

cURL
curl -X POST https://www.rcsinc.com.br/api/v1/conversions \
  -H "x-api-key: rcsk_live_SUA_CHAVE" \
  -H "Content-Type: application/json" \
  -d '{
    "value": 149.90,
    "code": "aB9xK2",
    "orderId": "PED-10482"
  }'
JavaScript (fetch)
await fetch("https://www.rcsinc.com.br/api/v1/conversions", {
  method: "POST",
  headers: {
    "x-api-key": "rcsk_live_SUA_CHAVE",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    value: 149.90,        // R$ da venda (obrigatório, >= 0)
    code: "aB9xK2",       // code do short-link que originou a venda
    // campaignId: "cmp_123",   // OU amarre direto à campanha
    // recipient: "+5511999999999", // OU ao número que recebeu
    orderId: "PED-10482", // opcional: id do pedido (evita duplicidade)
  }),
});
// { ok: true, duplicate: false }

Sem servidor: pixel na página de obrigado

Uma linha na página de compra concluída. O CODIGO chega ao seu site no parâmetro ?rcsc= quando o contato toca no link da mensagem; v é o valor da venda em reais.

HTML: pixel de conversão
<img src="https://www.rcsinc.com.br/c/CODIGO?v=99.90&order=123" width="1" height="1" alt="">

Mande sempre order com o id do pedido: com ele, cada pedido conta uma vez e recarregar a página de obrigado não soma a venda de novo. Sem ele, o mesmo link conta no máximo uma venda por dia.

POSTnotifyUrl (seu endpoint)

Webhook de status de saída

Quando você passa notifyUrl no envio, a plataforma faz um POST para essa URL a cada mudança de status. Responda com 2xx para confirmar.

Payload que enviamos

POST para o seu notifyUrl
{
  "event": "DELIVERED",
  "messageId": "msg_a1b2c3",
  "providerMessageId": "prov_998877",
  "recipient": "+5511999999999",
  "at": "2026-06-20T14:32:10.000Z"
}

Evento de clique

event: CLICKED
{
  "event": "CLICKED",
  "messageId": "msg_a1b2c3",
  "providerMessageId": "prov_998877",
  "recipient": "+5511999999999",
  "url": "https://loja.com.br/bf",
  "at": "2026-06-20T14:33:02.000Z"
}

Recebendo no seu servidor

Node / Express
// Endpoint no SEU sistema (a URL que você passa em notifyUrl).
// Recebe um POST a cada mudança de status da mensagem.
app.post("/webhooks/rcs", (req, res) => {
  const { event, messageId, recipient, at } = req.body;
  // event: SENT | DELIVERED | READ | CLICKED | FAILED
  console.log(`[${event}] ${recipient} — ${messageId} em ${at}`);
  res.sendStatus(200); // responda 2xx para confirmar o recebimento
});

Por segurança, a URL precisa ser pública (http/https) — endereços internos/privados são bloqueados. As chamadas têm timeout curto e são best-effort: se o seu servidor estiver fora do ar, o envio não é afetado.

Status de mensagem

Valores possíveis no campo event dos webhooks.

  • SENTEnviada

    Aceita no canal e a caminho da operadora móvel/RBM.

  • DELIVEREDEntregue

    Chegou ao aparelho do destinatário.

  • READLida

    O destinatário abriu a mensagem (disponível no canal RCS).

  • CLICKEDClicada

    Tocou em um link rastreável ou em um botão/sugestão do card.

  • FAILEDFalhou

    Não foi possível entregar (número inválido, bloqueio ou recusa no canal). O motivo detalhado fica em Saúde de Entregabilidade.

Códigos de resposta

Erros vêm com status HTTP e um corpo { "error": "..." } em português.

200OK — requisição processada. Com partial: true, os números em pending ainda não saíram (sem custo): reenvie só eles depois de retryAfterSeconds.
400Corpo inválido ou campos faltando.
401Chave ausente, inválida ou revogada.
402Saldo insuficiente para o envio.
403API não habilitada para esta conta — fale com o suporte.
409Idempotency-Key já usada com outro payload (ou envio em processamento).
429Limite de requisições excedido, ou o canal pediu para esperar. Nada foi enviado nem cobrado: tente de novo após o header Retry-After (segundos).
500Falha ao processar o envio.

Pronto para integrar?

Cada pedido de acesso é analisado por uma pessoa do time. Aprovado o teste, a conta já nasce com crédito para experimentar, e a chave é gerada dentro do portal — ela aparece uma única vez. A base de todos os endpoints é https://www.rcsinc.com.br/api/v1.

Dúvidas técnicas: vendas@rcsinc.com.br · Termos de Uso · DPA

Documentação da API · RCS Inc.