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
- 1Gere a chave em API & Chaves e mande tudo para a base
https://www.rcsinc.com.br/api/v1. - 2Dispare com
POST /api/v1/messages(SMS ou RCS) — copie o cURL ou o trecho JavaScript abaixo. - 3Receba os status apontando seu
notifyUrl/webhook para captar entregue, lida, clicada e falhou. - 4Feche o ROI chamando
POST /api/v1/conversionsquando o cliente compra.
Detalhes que pesam na decisão
- Autentique toda requisição com o header
x-api-key(formatorcsk_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
notifyUrlprecisa ser público (http/https); endereços internos são bloqueados e o webhook tem timeout curto (best-effort).
Base da API
Todas as chamadas usam HTTPS e trocam JSON. A base de todos os endpoints é:
https://www.rcsinc.com.br/api/v1Cada 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.
x-api-key: rcsk_live_SUA_CHAVEGuarde a chave em segredo (variável de ambiente). Vazou? Revogue e gere outra.
/api/v1/messagesEnviar 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órioDestinatário(s) em formato E.164 (ex.:
+5511999999999).channel"SMS" | "RCS"Canal de envio. Padrão:
SMS.textstringConteúdo de texto da mensagem.
mediaUrlstringURL pública de imagem/vídeo (RCS).
cardsCard[]Cards RCS ricos (title, description, mediaUrl, suggestions).
notifyUrlstringURL pública (http/https) que recebe os webhooks de status.
| Campo | Tipo | Descrição |
|---|---|---|
| to obrigatório | string | string[] | Destinatário(s) em formato E.164 (ex.: +5511999999999). |
| channel | "SMS" | "RCS" | Canal de envio. Padrão: SMS. |
| text | string | Conteúdo de texto da mensagem. |
| mediaUrl | string | URL pública de imagem/vídeo (RCS). |
| cards | Card[] | Cards RCS ricos (title, description, mediaUrl, suggestions). |
| notifyUrl | string | URL pública (http/https) que recebe os webhooks de status. |
Envie ao menos um entre text, mediaUrl ou cards.
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"
}'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
{
"ok": true,
"sent": 1,
"failed": 0,
"suppressed": 0,
"cost": 0.18
}RCS rico (cards)
{
"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" }
]
}
]
}POST /api/v1/messagesIdempotê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.
Devolve a resposta original (mesmo status e corpo), sem disparar um novo envio. A resposta vem com o header Idempotent-Replayed: true.
Retorna 409 Conflict — a chave já foi usada para outro corpo. Use uma key nova para um envio diferente.
Processa normalmente como um envio inédito. Gere um UUID por operação que você quer tornar segura para retry.
Idempotency-Keyvocê enviaUUID único por operação (ex.:
550e8400-e29b-41d4-a716-446655440000).Idempotent-Replayednós devolvemosPresente e
truequando a resposta é uma repetição da original (nada novo foi enviado).
| Header | Direção | Descrição |
|---|---|---|
| Idempotency-Key | você envia | UUID único por operação (ex.: 550e8400-e29b-41d4-a716-446655440000). |
| Idempotent-Replayed | nós devolvemos | Presente e true quando a resposta é uma repetição da original (nada novo foi enviado). |
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.
/api/v1/conversionsRegistrar 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órioValor da venda em R$ (≥ 0).
codestringCode do short-link que gerou o clique/venda.
campaignIdstringAtribui direto a uma campanha.
recipientstringAtribui ao número (E.164) que recebeu a mensagem.
orderIdstringId do pedido — usado para evitar contagem duplicada.
| Campo | Tipo | Descrição |
|---|---|---|
| value obrigatório | number | Valor da venda em R$ (≥ 0). |
| code | string | Code do short-link que gerou o clique/venda. |
| campaignId | string | Atribui direto a uma campanha. |
| recipient | string | Atribui ao número (E.164) que recebeu a mensagem. |
| orderId | string | Id do pedido — usado para evitar contagem duplicada. |
Informe ao menos um entre code, campaignId ou recipient para a atribuição.
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"
}'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.
<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.
notifyUrl (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
{
"event": "DELIVERED",
"messageId": "msg_a1b2c3",
"providerMessageId": "prov_998877",
"recipient": "+5511999999999",
"at": "2026-06-20T14:32:10.000Z"
}Evento de clique
{
"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
// 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.
| Status | Rótulo | Significado |
|---|---|---|
| SENT | Enviada | Aceita no canal e a caminho da operadora móvel/RBM. |
| DELIVERED | Entregue | Chegou ao aparelho do destinatário. |
| READ | Lida | O destinatário abriu a mensagem (disponível no canal RCS). |
| CLICKED | Clicada | Tocou em um link rastreável ou em um botão/sugestão do card. |
| FAILED | Falhou | 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.
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