Canais e conexões
Um canal é por onde as conversas acontecem. Todo contato, mensagem e grupo pertence a um canal. Antes de enviar a primeira mensagem, a organização precisa de pelo menos um WhatsApp conectado (status: "connected").
Tipos de canal
Seção intitulada “Tipos de canal”type |
O que é | O que dá para fazer pela API |
|---|---|---|
whatsapp |
Um número de WhatsApp conectado lendo um QR Code (ou digitando um código de pareamento) no celular — o mesmo que Configurações → Conexões no painel. | Tudo: criar e conectar, reconectar, renomear, desconectar e remover. |
webchat |
O Chat do site, o widget de conversa instalado no seu site. | Aparece em GET /channels e pode ser renomeado. Criar, configurar e remover é só no painel. |
Status da conexão
Seção intitulada “Status da conexão”status |
Significado | O que fazer |
|---|---|---|
connected |
O celular leu o QR Code (ou digitou o código). Pronto para enviar e receber. | Nada: use o canal normalmente. |
connecting |
Esperando a leitura do QR Code ou do código de pareamento, ou reconectando sozinho. | Mostre o QR Code e consulte GET /channels/{channel_id}/qr a cada 3–5 s. |
disconnected |
Sem sessão do WhatsApp. Envios por este canal respondem 422 channel_unavailable. |
Gere um novo QR Code com POST /channels/{channel_id}/connect. |
POST /channels │ ▼ ┌────────────┐ o celular leu o QR Code ┌───────────┐ │ connecting │ ────────────────────────► │ connected │ └────────────┘ (ou digitou o código) └───────────┘ ▲ │ ▲ │ │ └───┘ QR Code novo a cada ~20–40 s │ POST /channels/{id}/disconnect │ (consulte GET /channels/{id}/qr) │ ou a sessão caiu no celular │ ▼ │ POST /channels/{id}/connect ┌──────────────┐ └─────────────────────────────────────│ disconnected │ └──────────────┘Conectar um WhatsApp por QR Code
Seção intitulada “Conectar um WhatsApp por QR Code”O fluxo é sempre o mesmo: criar o canal → mostrar o QR Code → atualizar a cada poucos segundos → parar quando conectar. Tudo pelo seu backend (a chave de API nunca vai para o navegador).
-
Crie o canal. Chame
POST /channelscom um nome. A resposta201traz o ID do canal emchannel.ide o primeiro QR Code emqr_code.Janela do terminal curl https://platform.toptalking.com.br/v1/channels \-H "Authorization: Bearer $TOPTALKING_API_KEY" \-H "Content-Type: application/json" \-H "Idempotency-Key: conexao-pos-venda-001" \-d '{ "name": "Pós-venda" }'{"object": "channel_connection","channel": {"id": "742539b3-2c69-4acc-988f-fcd836e565a9","object": "channel","type": "whatsapp","name": "Pós-venda","phone": null,"status": "connecting","is_primary": false,"created_at": "2026-11-11T15:20:00Z"},"status": "connecting","qr_code": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAARQAAAEUCAYAAADqcMl5AAAAAklEQVR4AewaftIAAA...","qr_code_generated_at": "2026-11-11T15:20:02Z","pairing_code": null}Guarde o
channel.id: você vai usá-lo nos próximos passos. -
Mostre o QR Code.
qr_codeé uma imagem PNG em data URL (data:image/png;base64,...). Não precisa converter: coloque direto nosrcde uma imagem —<img src={qr_code} />no React ouimg.src = qr_codeem JavaScript puro.No celular que vai ser conectado: WhatsApp → Configurações (no Android, toque em ⋮) → Aparelhos conectados → Conectar um aparelho e aponte a câmera para o QR Code.
-
Atualize a cada 3–5 segundos. O QR Code vale só ~20 a 40 segundos e é renovado automaticamente. Consulte
GET /channels/{channel_id}/qrem intervalos curtos e troque a imagem sempre queqr_codemudar (qr_code_generated_atdiz quando o atual foi gerado).Janela do terminal curl https://platform.toptalking.com.br/v1/channels/742539b3-2c69-4acc-988f-fcd836e565a9/qr \-H "Authorization: Bearer $TOPTALKING_API_KEY"Esta rota só lê o QR Code atual — não gera um pareamento novo. Pode consultar à vontade (respeitando o limite de 120 requisições por minuto).
-
Pare quando
statusforconnected. Assim que o celular lê o código, a consulta devolvestatus: "connected",qr_code: nulle o número emchannel.phone:{"object": "channel_connection","channel": {"id": "742539b3-2c69-4acc-988f-fcd836e565a9","object": "channel","type": "whatsapp","name": "Pós-venda","phone": "5511955554444","status": "connected","is_primary": false,"created_at": "2026-11-11T15:20:00Z"},"status": "connected","qr_code": null,"qr_code_generated_at": null,"pairing_code": null}Prefere não consultar? Assine o webhook
channel.status_updated: ele chega no instante em que o canal conecta. -
Envie uma mensagem de teste. Use o ID do canal em
channel_idpara garantir que a mensagem sai pelo número recém-conectado (mande para o seu próprio celular):Janela do terminal curl https://platform.toptalking.com.br/v1/messages \-H "Authorization: Bearer $TOPTALKING_API_KEY" \-H "Content-Type: application/json" \-H "Idempotency-Key: teste-pos-venda-001" \-d '{"to": "5511999998888","channel_id": "742539b3-2c69-4acc-988f-fcd836e565a9","text": "Teste: o WhatsApp do Pós-venda está conectado ✅"}'
Exemplo completo
Seção intitulada “Exemplo completo”Um backend que cria a conexão e acompanha o QR Code até conectar. Escolha a linguagem:
# Requer curl, jq e base64. Salva o QR Code atual em qr.png até conectar.API=https://platform.toptalking.com.br/v1AUTH="Authorization: Bearer $TOPTALKING_API_KEY"
# 1. Cria o canal e guarda o IDID=$(curl -s "$API/channels" -H "$AUTH" -H "Content-Type: application/json" \ -H "Idempotency-Key: conexao-pos-venda-001" \ -d '{ "name": "Pós-venda" }' | jq -r '.channel.id')echo "Canal criado: $ID"
# 2 a 4. A cada 4 s: salva o QR Code (se houver) e para quando conectarwhile true; do R=$(curl -s "$API/channels/$ID/qr" -H "$AUTH") STATUS=$(echo "$R" | jq -r '.status') [ "$STATUS" = "connected" ] && echo "Conectado: $(echo "$R" | jq -r '.channel.phone')" && break QR=$(echo "$R" | jq -r '.qr_code // empty') [ -n "$QR" ] && echo "${QR#*,}" | base64 -d > qr.png && echo "status: $STATUS (abra qr.png)" sleep 4done// Node 18+ (fetch nativo). Roda no SEU servidor: a chave nunca vai para o navegador.const API = 'https://platform.toptalking.com.br/v1';
export type Conexao = { object: 'channel_connection'; channel: { id: string; name: string; phone: string | null; status: string }; status: 'connected' | 'connecting' | 'disconnected'; qr_code: string | null; // "data:image/png;base64,..." → direto no <img src> qr_code_generated_at: string | null; pairing_code: string | null;};
async function api<T>(path: string, init: RequestInit = {}): Promise<T> { const res = await fetch(`${API}${path}`, { ...init, headers: { Authorization: `Bearer ${process.env.TOPTALKING_API_KEY}`, 'Content-Type': 'application/json', ...init.headers, }, }); const body = await res.json(); if (!res.ok) throw new Error(`${res.status} ${body.error.code}: ${body.error.message}`); return body as T;}
/** Passo 1: cria o canal. O primeiro QR Code pode vir null nos primeiros segundos. */export function criarConexao(nome: string, idempotencyKey = crypto.randomUUID()) { return api<Conexao>('/channels', { method: 'POST', headers: { 'Idempotency-Key': idempotencyKey }, body: JSON.stringify({ name: nome }), });}
/** Passo 3: lê o QR Code atual e o status (não gera um pareamento novo). */export function consultarConexao(channelId: string) { return api<Conexao>(`/channels/${channelId}/qr`);}
/** Gera um QR Code novo para um canal desconectado (ou que parou de parear). */export function gerarNovoQr(channelId: string) { return api<Conexao>(`/channels/${channelId}/connect`, { method: 'POST', body: '{}' });}
/** Passos 2 a 4: repete a consulta a cada 4 s até conectar (desiste depois de 3 min). */export async function aguardarConexao( channelId: string, aoMudarQr: (qrCode: string) => void, { intervaloMs = 4000, limiteMs = 3 * 60_000 } = {},): Promise<Conexao> { const fim = Date.now() + limiteMs; let ultimoQr: string | null = null;
while (Date.now() < fim) { let conexao = await consultarConexao(channelId); if (conexao.status === 'connected') return conexao; // pronto!
if (conexao.status === 'disconnected' && !conexao.qr_code) { conexao = await gerarNovoQr(channelId); // o pareamento parou: gera outro } if (conexao.qr_code && conexao.qr_code !== ultimoQr) { ultimoQr = conexao.qr_code; aoMudarQr(conexao.qr_code); // QR Code novo: atualize a tela } await new Promise((r) => setTimeout(r, intervaloMs)); } throw new Error('O QR Code não foi lido a tempo. Tente de novo.');}
// Uso num script:// const { channel } = await criarConexao('Pós-venda');// const pronto = await aguardarConexao(channel.id, (qr) => console.log('QR novo:', qr.slice(0, 40)));// console.log('Conectado:', pronto.channel.phone);import base64import osimport time
import requests
API = "https://platform.toptalking.com.br/v1"HEADERS = {"Authorization": f"Bearer {os.environ['TOPTALKING_API_KEY']}"}
def salvar_qr(qr_code: str, arquivo: str = "qr.png") -> None: # qr_code = "data:image/png;base64,iVBORw0..." -> grava o PNG with open(arquivo, "wb") as f: f.write(base64.b64decode(qr_code.split(",", 1)[1]))
# Passo 1: cria o canalres = requests.post( f"{API}/channels", headers={**HEADERS, "Idempotency-Key": "conexao-pos-venda-001"}, json={"name": "Pós-venda"}, timeout=30,)res.raise_for_status()conexao = res.json()channel_id = conexao["channel"]["id"]
# Passos 2 a 4: a cada 4 s, atualiza o QR Code até conectar (no máximo 3 min)ultimo_qr = Nonelimite = time.time() + 180while time.time() < limite: if conexao["status"] == "connected": print("Conectado:", conexao["channel"]["phone"]) break if conexao["status"] == "disconnected" and not conexao["qr_code"]: # o pareamento parou: gera outro QR Code conexao = requests.post( f"{API}/channels/{channel_id}/connect", headers=HEADERS, json={}, timeout=30 ).json() if conexao["qr_code"] and conexao["qr_code"] != ultimo_qr: ultimo_qr = conexao["qr_code"] salvar_qr(ultimo_qr) print("QR Code novo salvo em qr.png: leia com o celular.") time.sleep(4) res = requests.get(f"{API}/channels/{channel_id}/qr", headers=HEADERS, timeout=30) res.raise_for_status() conexao = res.json()else: print("O QR Code não foi lido a tempo. Tente de novo.")Mostrando o QR Code numa tela
Seção intitulada “Mostrando o QR Code numa tela”Para o usuário conectar pelo seu sistema, exponha duas rotas no seu backend (que chamam a TopTalking com a chave) e faça a tela consultar essas rotas — nunca a API da TopTalking direto do navegador.
import express from 'express';import { criarConexao, consultarConexao, type Conexao } from './toptalking-conexao';
const app = express();app.use(express.json());
// Devolva ao navegador só o necessário (nunca a chave).const resumo = (c: Conexao) => ({ id: c.channel.id, status: c.status, qrCode: c.qr_code, telefone: c.channel.phone,});
// Proteja estas rotas com o login do seu sistema.app.post('/api/whatsapp/conexoes', async (req, res) => { const conexao = await criarConexao(req.body.nome ?? 'WhatsApp'); res.status(201).json(resumo(conexao));});
app.get('/api/whatsapp/conexoes/:id', async (req, res) => { res.json(resumo(await consultarConexao(req.params.id)));});
app.listen(3000);import { useEffect, useState } from 'react';
type Conexao = { id: string; status: string; qrCode: string | null; telefone: string | null };
export function ConectarWhatsApp() { const [conexao, setConexao] = useState<Conexao | null>(null);
async function iniciar() { const res = await fetch('/api/whatsapp/conexoes', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ nome: 'Pós-venda' }), }); setConexao(await res.json()); }
// Enquanto não conecta, consulta o SEU backend a cada 4 s. useEffect(() => { if (!conexao || conexao.status === 'connected') return; const timer = setInterval(async () => { const res = await fetch(`/api/whatsapp/conexoes/${conexao.id}`); setConexao(await res.json()); }, 4000); return () => clearInterval(timer); }, [conexao?.id, conexao?.status]);
if (!conexao) return <button onClick={iniciar}>Conectar WhatsApp</button>; if (conexao.status === 'connected') return <p>WhatsApp {conexao.telefone} conectado!</p>;
return ( <div> {conexao.qrCode ? ( <img src={conexao.qrCode} alt="QR Code para conectar o WhatsApp" width={264} height={264} /> ) : ( <p>Gerando o QR Code…</p> )} <p>No celular: WhatsApp → Aparelhos conectados → Conectar um aparelho.</p> </div> );}<button id="conectar">Conectar WhatsApp</button><img id="qr" alt="QR Code para conectar o WhatsApp" width="264" height="264" hidden /><p id="aviso"></p>
<script> const aviso = document.getElementById('aviso'); const qr = document.getElementById('qr');
function mostrar(conexao) { if (conexao.status === 'connected') { qr.hidden = true; aviso.textContent = `WhatsApp ${conexao.telefone} conectado!`; return true; } if (conexao.qrCode) { qr.src = conexao.qrCode; // data URL: vai direto no src qr.hidden = false; aviso.textContent = 'No celular: WhatsApp → Aparelhos conectados → Conectar um aparelho.'; } else { aviso.textContent = 'Gerando o QR Code…'; } return false; }
document.getElementById('conectar').onclick = async () => { // Chama o SEU backend, que chama a TopTalking com a chave. const res = await fetch('/api/whatsapp/conexoes', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ nome: 'Pós-venda' }), }); const conexao = await res.json(); if (mostrar(conexao)) return;
const timer = setInterval(async () => { const atual = await (await fetch(`/api/whatsapp/conexoes/${conexao.id}`)).json(); if (mostrar(atual)) clearInterval(timer); }, 4000); };</script>Conectar com código de pareamento
Seção intitulada “Conectar com código de pareamento”Sem câmera à mão (ex.: o celular é o mesmo aparelho que mostra a tela)? Peça um código de pareamento de 8 caracteres em vez do QR Code.
-
Tenha um canal que ainda não está conectado. Crie com
POST /channels(ignore o QR Code da resposta) ou use um canaldisconnected. -
Peça o código com
POST /channels/{channel_id}/connect, enviando emphoneo número do WhatsApp que vai ser conectado (o do celular da empresa, com DDI e DDD — não o de um cliente). A resposta pode levar até ~20 segundos: use um timeout de pelo menos 30 s.Janela do terminal curl https://platform.toptalking.com.br/v1/channels/742539b3-2c69-4acc-988f-fcd836e565a9/connect \-H "Authorization: Bearer $TOPTALKING_API_KEY" \-H "Content-Type: application/json" \-d '{ "phone": "5511955554444" }'{"object": "channel_connection","channel": {"id": "742539b3-2c69-4acc-988f-fcd836e565a9","object": "channel","type": "whatsapp","name": "Pós-venda","phone": null,"status": "connecting","is_primary": false,"created_at": "2026-11-11T15:20:00Z"},"status": "connecting","qr_code": null,"qr_code_generated_at": null,"pairing_code": "WZYE-H1YY"} -
Digite o código no celular: WhatsApp → Aparelhos conectados → Conectar um aparelho → Conectar com número de telefone e digite
WZYE-H1YY. -
Espere o
connected. ConsulteGET /channels/{channel_id}/qra cada 3–5 s (ostatusviraconnected) ou assinechannel.status_updated. Se o código não funcionar, peça outro chamando o/connectde novo.
Reconectar um WhatsApp desconectado
Seção intitulada “Reconectar um WhatsApp desconectado”Quando um canal fica disconnected (o celular saiu de “Aparelhos conectados”, trocou de aparelho, ficou muito tempo sem internet…), não crie um canal novo: gere um novo QR Code para o mesmo canal. Assim as conversas continuam no mesmo lugar.
- Chame
POST /channels/{channel_id}/connectsem corpo (ou com{ "phone": "..." }para receber um código de pareamento). - Mostre o
qr_codee siga os passos 3 e 4 de Conectar um WhatsApp por QR Code.
Se o canal já estiver conectado, a API responde 409 invalid_state: para trocar o número, desconecte antes.
O objeto canal
Seção intitulada “O objeto canal”{ "id": "d781e759-4047-4c35-bfcd-eae8c666369a", "object": "channel", "type": "whatsapp", "name": "Vendas", "phone": "5511988887777", "status": "connected", "is_primary": true, "created_at": "2026-03-02T12:10:44Z"}| Campo | Tipo | Descrição |
|---|---|---|
id |
UUID | ID do canal. Use em channel_id para escolher por qual número enviar. |
object |
string | Sempre channel. |
type |
string | whatsapp (número conectado por QR Code) ou webchat (Chat do site). |
name |
string | Nome do canal no painel (ex.: “Vendas”). |
phone |
string ou null |
Número do WhatsApp, só dígitos com DDI. null no Chat do site e em canais que ainda não conectaram. |
status |
string | connected, connecting ou disconnected. Veja Status da conexão. |
is_primary |
booleano | Se é o WhatsApp principal — o usado por padrão em POST /messages. |
created_at |
data | Quando o canal foi criado. |
O objeto conexão
Seção intitulada “O objeto conexão”Devolvido por POST /channels, POST /channels/{channel_id}/connect e GET /channels/{channel_id}/qr. Mostra o estado do pareamento de um canal de WhatsApp.
{ "object": "channel_connection", "channel": { "id": "742539b3-2c69-4acc-988f-fcd836e565a9", "object": "channel", "type": "whatsapp", "name": "Pós-venda", "phone": null, "status": "connecting", "is_primary": false, "created_at": "2026-11-11T15:20:00Z" }, "status": "connecting", "qr_code": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAARQAAAEUCAYAAADqcMl5AAAAAklEQVR4AewaftIAAA...", "qr_code_generated_at": "2026-11-11T15:20:31Z", "pairing_code": null}| Campo | Tipo | Descrição |
|---|---|---|
object |
string | Sempre channel_connection. |
channel |
objeto | O objeto canal atualizado. |
status |
string | connected (o celular leu o código e o canal já envia mensagens), connecting ou disconnected. |
qr_code |
string ou null |
Imagem PNG em data URL (data:image/png;base64,...), pronta para o src de uma imagem. null quando o canal está conectado, quando não há pareamento em andamento, quando o QR Code ainda está sendo gerado ou quando você pediu código de pareamento. |
qr_code_generated_at |
data ou null |
Quando o QR Code atual foi gerado. Mudou? Troque a imagem. |
pairing_code |
string ou null |
Código de pareamento (8 caracteres, ex.: WZYE-H1YY). Só vem na resposta de POST /channels/{channel_id}/connect com phone. |
Listar canais
Seção intitulada “Listar canais”GET/v1/channels
Devolve todos os canais da organização — WhatsApp e Chat do site, conectados ou não. Use para descobrir o channel_id de cada número e para monitorar se algum WhatsApp caiu.
Não tem parâmetros. A lista vem inteira numa página (has_more: false).
curl https://platform.toptalking.com.br/v1/channels \ -H "Authorization: Bearer $TOPTALKING_API_KEY"const res = await fetch('https://platform.toptalking.com.br/v1/channels', { headers: { Authorization: `Bearer ${process.env.TOPTALKING_API_KEY}` },});const { data: canais } = await res.json();const caidos = canais.filter((c) => c.type === 'whatsapp' && c.status !== 'connected');if (caidos.length) console.warn('WhatsApp sem conexão:', caidos.map((c) => c.name));import osimport requests
res = requests.get( "https://platform.toptalking.com.br/v1/channels", headers={"Authorization": f"Bearer {os.environ['TOPTALKING_API_KEY']}"}, timeout=30,)res.raise_for_status()canais = res.json()["data"]caidos = [c["name"] for c in canais if c["type"] == "whatsapp" and c["status"] != "connected"]Resposta 200
Seção intitulada “Resposta 200”{ "object": "list", "data": [ { "id": "d781e759-4047-4c35-bfcd-eae8c666369a", "object": "channel", "type": "whatsapp", "name": "Vendas", "phone": "5511988887777", "status": "connected", "is_primary": true, "created_at": "2026-03-02T12:10:44Z" }, { "id": "9d8adaf6-a08d-4027-b07c-5df1e89e117b", "object": "channel", "type": "whatsapp", "name": "Suporte", "phone": "5511977776666", "status": "disconnected", "is_primary": false, "created_at": "2026-05-18T09:31:02Z" }, { "id": "742539b3-2c69-4acc-988f-fcd836e565a9", "object": "channel", "type": "whatsapp", "name": "Pós-venda", "phone": null, "status": "connecting", "is_primary": false, "created_at": "2026-11-11T15:20:00Z" }, { "id": "26facac8-3d9a-41b3-bfee-88851aba96ec", "object": "channel", "type": "webchat", "name": "Chat do site", "phone": null, "status": "connected", "is_primary": false, "created_at": "2026-06-20T17:45:10Z" } ], "has_more": false, "next_cursor": null}Só os gerais: 401 (chave) e 429 (limite por minuto). Veja Erros.
Criar canal
Seção intitulada “Criar canal”POST/v1/channels
Cria um canal de WhatsApp e já inicia o pareamento: a resposta traz o primeiro QR Code. É o primeiro passo para conectar um WhatsApp por QR Code. Depois, consulte GET /channels/{channel_id}/qr até status ser connected.
Cada canal criado conta no limite de conexões do plano — veja Limite de conexões do plano.
| Parâmetro | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
name |
corpo | string | não | Nome do canal no painel (até 80 caracteres), ex.: “Pós-venda”. O corpo inteiro é opcional. |
Idempotency-Key |
cabeçalho | string | não (recomendado) | Evita criar dois canais se a requisição for repetida. Veja Idempotência. |
curl https://platform.toptalking.com.br/v1/channels \ -H "Authorization: Bearer $TOPTALKING_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: conexao-pos-venda-001" \ -d '{ "name": "Pós-venda" }'const res = await fetch('https://platform.toptalking.com.br/v1/channels', { method: 'POST', headers: { Authorization: `Bearer ${process.env.TOPTALKING_API_KEY}`, 'Content-Type': 'application/json', 'Idempotency-Key': 'conexao-pos-venda-001', }, body: JSON.stringify({ name: 'Pós-venda' }),});const conexao = await res.json();if (!res.ok) throw new Error(`${conexao.error.code}: ${conexao.error.message}`);console.log(conexao.channel.id, conexao.qr_code ? 'QR Code pronto' : 'gerando QR Code…');import osimport requests
res = requests.post( "https://platform.toptalking.com.br/v1/channels", headers={ "Authorization": f"Bearer {os.environ['TOPTALKING_API_KEY']}", "Idempotency-Key": "conexao-pos-venda-001", }, json={"name": "Pós-venda"}, timeout=30,)conexao = res.json()if not res.ok: raise RuntimeError(f"{conexao['error']['code']}: {conexao['error']['message']}")channel_id = conexao["channel"]["id"]Resposta 201
Seção intitulada “Resposta 201”O objeto conexão, com o canal em connecting:
{ "object": "channel_connection", "channel": { "id": "742539b3-2c69-4acc-988f-fcd836e565a9", "object": "channel", "type": "whatsapp", "name": "Pós-venda", "phone": null, "status": "connecting", "is_primary": false, "created_at": "2026-11-11T15:20:00Z" }, "status": "connecting", "qr_code": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAARQAAAEUCAYAAADqcMl5AAAAAklEQVR4AewaftIAAA...", "qr_code_generated_at": "2026-11-11T15:20:02Z", "pairing_code": null}qr_code pode vir null se o QR Code ainda estiver sendo gerado: continue consultando GET /channels/{channel_id}/qr.
| HTTP | code |
Quando acontece |
|---|---|---|
| 400 | invalid_json, invalid_field |
Corpo inválido, name com mais de 80 caracteres ou campo desconhecido. |
| 403 | read_only_key |
Chave somente leitura. |
| 422 | limit_reached |
O plano já tem o máximo de conexões de WhatsApp. |
| 502 | provider_error, internal_error |
O WhatsApp não respondeu ao criar a conexão. Tente de novo com a mesma Idempotency-Key. |
| 504 | timeout |
O lado do WhatsApp demorou demais. Tente de novo com a mesma Idempotency-Key: se a primeira tiver dado certo, você recebe o canal já criado. |
{ "error": { "type": "invalid_request_error", "code": "limit_reached", "message": "Seu plano permite 3 conexões de WhatsApp. Remova uma ou faça upgrade no painel.", "request_id": "req_6f1d2c3b4a5e" }}Buscar canal
Seção intitulada “Buscar canal”GET/v1/channels/{channel_id}
Um canal pelo ID. Útil para conferir o status de um número específico antes de um envio importante.
| Parâmetro | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
channel_id |
caminho | UUID | sim | ID do canal. |
curl https://platform.toptalking.com.br/v1/channels/d781e759-4047-4c35-bfcd-eae8c666369a \ -H "Authorization: Bearer $TOPTALKING_API_KEY"const channelId = 'd781e759-4047-4c35-bfcd-eae8c666369a';const res = await fetch(`https://platform.toptalking.com.br/v1/channels/${channelId}`, { headers: { Authorization: `Bearer ${process.env.TOPTALKING_API_KEY}` },});const canal = await res.json();if (canal.status !== 'connected') console.warn(`O canal ${canal.name} está ${canal.status}.`);import osimport requests
channel_id = "d781e759-4047-4c35-bfcd-eae8c666369a"res = requests.get( f"https://platform.toptalking.com.br/v1/channels/{channel_id}", headers={"Authorization": f"Bearer {os.environ['TOPTALKING_API_KEY']}"}, timeout=30,)res.raise_for_status()canal = res.json()Resposta 200
Seção intitulada “Resposta 200”{ "id": "d781e759-4047-4c35-bfcd-eae8c666369a", "object": "channel", "type": "whatsapp", "name": "Vendas", "phone": "5511988887777", "status": "connected", "is_primary": true, "created_at": "2026-03-02T12:10:44Z"}| HTTP | code |
Quando acontece |
|---|---|---|
| 404 | resource_not_found |
O canal não existe, foi removido ou é de outra organização. |
Consultar o QR Code
Seção intitulada “Consultar o QR Code”GET/v1/channels/{channel_id}/qr
Devolve o QR Code mais recente do pareamento em andamento e o status da conexão, para você mostrar na tela e saber quando parar. É a rota que você chama a cada 3–5 segundos durante a conexão.
Ela não gera um pareamento novo (para isso, use POST /channels/{channel_id}/connect). Quando o celular lê o código, status vira connected e qr_code volta null. Só funciona para canais whatsapp.
| Parâmetro | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
channel_id |
caminho | UUID | sim | ID do canal. |
curl https://platform.toptalking.com.br/v1/channels/742539b3-2c69-4acc-988f-fcd836e565a9/qr \ -H "Authorization: Bearer $TOPTALKING_API_KEY"const channelId = '742539b3-2c69-4acc-988f-fcd836e565a9';const res = await fetch(`https://platform.toptalking.com.br/v1/channels/${channelId}/qr`, { headers: { Authorization: `Bearer ${process.env.TOPTALKING_API_KEY}` },});const conexao = await res.json();if (conexao.status === 'connected') console.log('Conectado:', conexao.channel.phone);else if (conexao.qr_code) mostrarNaTela(conexao.qr_code); // sua funçãoimport osimport requests
channel_id = "742539b3-2c69-4acc-988f-fcd836e565a9"res = requests.get( f"https://platform.toptalking.com.br/v1/channels/{channel_id}/qr", headers={"Authorization": f"Bearer {os.environ['TOPTALKING_API_KEY']}"}, timeout=30,)res.raise_for_status()conexao = res.json()print(conexao["status"], "QR Code disponível" if conexao["qr_code"] else "sem QR Code")Resposta 200
Seção intitulada “Resposta 200”Enquanto espera a leitura:
{ "object": "channel_connection", "channel": { "id": "742539b3-2c69-4acc-988f-fcd836e565a9", "object": "channel", "type": "whatsapp", "name": "Pós-venda", "phone": null, "status": "connecting", "is_primary": false, "created_at": "2026-11-11T15:20:00Z" }, "status": "connecting", "qr_code": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAARQAAAEUCAYAAADqcMl5AAAAAklEQVR4AewaftIAAA...", "qr_code_generated_at": "2026-11-11T15:20:31Z", "pairing_code": null}Depois que o celular leu o código, a mesma chamada devolve status: "connected", qr_code: null e o número em channel.phone (veja o passo 4 de Conectar um WhatsApp por QR Code).
status |
qr_code |
O que fazer |
|---|---|---|
connecting |
preenchido | Mostre (ou troque) a imagem e consulte de novo em 3–5 s. |
connecting |
null |
O QR Code está sendo gerado (ou você pediu código de pareamento). Consulte de novo. |
connected |
null |
Pronto. Pare de consultar. |
disconnected |
null |
Não há pareamento em andamento. Chame POST /channels/{channel_id}/connect. |
| HTTP | code |
Quando acontece |
|---|---|---|
| 400 | invalid_field |
O canal é o Chat do site (webchat), que não usa QR Code. |
| 404 | resource_not_found |
O canal não existe, foi removido ou é de outra organização. |
Gerar QR Code ou código de pareamento
Seção intitulada “Gerar QR Code ou código de pareamento”POST/v1/channels/{channel_id}/connect
Inicia um novo pareamento num canal de WhatsApp que não está conectado e devolve o QR Code. Use para:
- reconectar um canal
disconnected; - gerar outro QR Code quando o anterior não foi lido a tempo;
- conectar sem câmera: envie
phonee receba umpairing_codepara digitar no celular (veja Conectar com código de pareamento).
O QR Code vale cerca de 20 a 40 segundos e é renovado sozinho: depois desta chamada, consulte GET /channels/{channel_id}/qr a cada poucos segundos até status virar connected. Com phone, a resposta pode demorar até ~20 segundos.
| Parâmetro | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
channel_id |
caminho | UUID | sim | ID do canal de WhatsApp. |
phone |
corpo | string | não | Número do WhatsApp que vai ser conectado, com DDI e DDD (ex.: 5511955554444). Com ele, a resposta traz pairing_code em vez de qr_code. Sem corpo (ou {}), vem o QR Code. |
# QR Codecurl -X POST https://platform.toptalking.com.br/v1/channels/9d8adaf6-a08d-4027-b07c-5df1e89e117b/connect \ -H "Authorization: Bearer $TOPTALKING_API_KEY"
# Código de pareamento (sem câmera)curl https://platform.toptalking.com.br/v1/channels/9d8adaf6-a08d-4027-b07c-5df1e89e117b/connect \ -H "Authorization: Bearer $TOPTALKING_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "phone": "5511977776666" }'async function gerarPareamento(channelId, phone) { const res = await fetch(`https://platform.toptalking.com.br/v1/channels/${channelId}/connect`, { method: 'POST', headers: { Authorization: `Bearer ${process.env.TOPTALKING_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify(phone ? { phone } : {}), signal: AbortSignal.timeout(30_000), // com phone pode levar ~20 s }); const body = await res.json(); if (!res.ok) throw new Error(`${body.error.code}: ${body.error.message}`); return body; // body.qr_code ou body.pairing_code}
const { pairing_code } = await gerarPareamento('9d8adaf6-a08d-4027-b07c-5df1e89e117b', '5511977776666');console.log('Digite no celular:', pairing_code); // "WZYE-H1YY"import osimport requests
channel_id = "9d8adaf6-a08d-4027-b07c-5df1e89e117b"res = requests.post( f"https://platform.toptalking.com.br/v1/channels/{channel_id}/connect", headers={"Authorization": f"Bearer {os.environ['TOPTALKING_API_KEY']}"}, json={"phone": "5511977776666"}, # ou json={} para receber o QR Code timeout=30, # com phone pode levar ~20 s)conexao = res.json()if not res.ok: raise RuntimeError(f"{conexao['error']['code']}: {conexao['error']['message']}")print("Digite no celular:", conexao["pairing_code"])Resposta 200
Seção intitulada “Resposta 200”Sem phone (QR Code):
{ "object": "channel_connection", "channel": { "id": "9d8adaf6-a08d-4027-b07c-5df1e89e117b", "object": "channel", "type": "whatsapp", "name": "Suporte", "phone": "5511977776666", "status": "connecting", "is_primary": false, "created_at": "2026-05-18T09:31:02Z" }, "status": "connecting", "qr_code": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAARQAAAEUCAYAAADqcMl5AAAAAklEQVR4AewaftIAAA...", "qr_code_generated_at": "2026-11-11T15:42:08Z", "pairing_code": null}Com phone (código de pareamento):
{ "object": "channel_connection", "channel": { "id": "9d8adaf6-a08d-4027-b07c-5df1e89e117b", "object": "channel", "type": "whatsapp", "name": "Suporte", "phone": "5511977776666", "status": "connecting", "is_primary": false, "created_at": "2026-05-18T09:31:02Z" }, "status": "connecting", "qr_code": null, "qr_code_generated_at": null, "pairing_code": "WZYE-H1YY"}| HTTP | code |
Quando acontece |
|---|---|---|
| 400 | invalid_field |
O canal é o Chat do site (webchat), que não usa QR Code, ou há campo desconhecido no corpo. |
| 400 | invalid_phone |
phone não parece um número válido. |
| 403 | read_only_key |
Chave somente leitura. |
| 404 | resource_not_found |
O canal não existe ou é de outra organização. |
| 409 | invalid_state |
O canal já está conectado. Para trocar o número, desconecte antes. |
| 502 | provider_error |
O WhatsApp não devolveu o QR Code ou o código de pareamento. Confira o número e tente de novo. |
| 504 | timeout |
O lado do WhatsApp demorou demais para responder. Tente de novo em instantes. |
{ "error": { "type": "conflict_error", "code": "invalid_state", "message": "Este WhatsApp já está conectado. Para trocar o número, desconecte antes.", "request_id": "req_6f1d2c3b4a5e" }}Renomear canal
Seção intitulada “Renomear canal”PATCH/v1/channels/{channel_id}
Muda o nome do canal no painel (ex.: de “WhatsApp” para “Suporte”). Não afeta a conexão nem as conversas.
| Parâmetro | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
channel_id |
caminho | UUID | sim | ID do canal. |
name |
corpo | string | sim | Novo nome (até 80 caracteres). |
curl -X PATCH https://platform.toptalking.com.br/v1/channels/742539b3-2c69-4acc-988f-fcd836e565a9 \ -H "Authorization: Bearer $TOPTALKING_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Pós-venda e trocas" }'const channelId = '742539b3-2c69-4acc-988f-fcd836e565a9';const res = await fetch(`https://platform.toptalking.com.br/v1/channels/${channelId}`, { method: 'PATCH', headers: { Authorization: `Bearer ${process.env.TOPTALKING_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ name: 'Pós-venda e trocas' }),});const canal = await res.json();import osimport requests
channel_id = "742539b3-2c69-4acc-988f-fcd836e565a9"res = requests.patch( f"https://platform.toptalking.com.br/v1/channels/{channel_id}", headers={"Authorization": f"Bearer {os.environ['TOPTALKING_API_KEY']}"}, json={"name": "Pós-venda e trocas"}, timeout=30,)res.raise_for_status()canal = res.json()Resposta 200
Seção intitulada “Resposta 200”{ "id": "742539b3-2c69-4acc-988f-fcd836e565a9", "object": "channel", "type": "whatsapp", "name": "Pós-venda e trocas", "phone": "5511955554444", "status": "connected", "is_primary": false, "created_at": "2026-11-11T15:20:00Z"}| HTTP | code |
Quando acontece |
|---|---|---|
| 400 | missing_field |
Faltou name. |
| 400 | invalid_json, invalid_field |
Corpo inválido, name com mais de 80 caracteres ou campo desconhecido. |
| 403 | read_only_key |
Chave somente leitura. |
| 404 | resource_not_found |
O canal não existe ou é de outra organização. |
Desconectar canal
Seção intitulada “Desconectar canal”POST/v1/channels/{channel_id}/disconnect
Encerra a sessão do WhatsApp neste canal — o mesmo que Desconectar no painel (o aparelho some de “Aparelhos conectados” no celular). O canal continua existindo, com status: "disconnected", e as conversas continuam no painel. Para usar o número de novo (ou conectar outro número no mesmo canal), chame POST /channels/{channel_id}/connect.
| Parâmetro | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
channel_id |
caminho | UUID | sim | ID do canal de WhatsApp. |
curl -X POST https://platform.toptalking.com.br/v1/channels/742539b3-2c69-4acc-988f-fcd836e565a9/disconnect \ -H "Authorization: Bearer $TOPTALKING_API_KEY"const channelId = '742539b3-2c69-4acc-988f-fcd836e565a9';const res = await fetch( `https://platform.toptalking.com.br/v1/channels/${channelId}/disconnect`, { method: 'POST', headers: { Authorization: `Bearer ${process.env.TOPTALKING_API_KEY}` } },);const canal = await res.json(); // canal.status === "disconnected"import osimport requests
channel_id = "742539b3-2c69-4acc-988f-fcd836e565a9"res = requests.post( f"https://platform.toptalking.com.br/v1/channels/{channel_id}/disconnect", headers={"Authorization": f"Bearer {os.environ['TOPTALKING_API_KEY']}"}, timeout=30,)res.raise_for_status()canal = res.json()Resposta 200
Seção intitulada “Resposta 200”O objeto canal, já desconectado:
{ "id": "742539b3-2c69-4acc-988f-fcd836e565a9", "object": "channel", "type": "whatsapp", "name": "Pós-venda e trocas", "phone": "5511955554444", "status": "disconnected", "is_primary": false, "created_at": "2026-11-11T15:20:00Z"}| HTTP | code |
Quando acontece |
|---|---|---|
| 400 | invalid_field |
O canal é o Chat do site (webchat). |
| 403 | read_only_key |
Chave somente leitura. |
| 404 | resource_not_found |
O canal não existe ou é de outra organização. |
Remover canal
Seção intitulada “Remover canal”DELETE/v1/channels/{channel_id}
Desconecta o WhatsApp e remove o canal da organização, liberando uma conexão do plano. As conversas que já existiam continuam no painel. Não dá para desfazer: para usar o número de novo, crie outro canal.
O Chat do site (webchat) só pode ser removido no painel.
| Parâmetro | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
channel_id |
caminho | UUID | sim | ID do canal de WhatsApp. |
curl -X DELETE https://platform.toptalking.com.br/v1/channels/742539b3-2c69-4acc-988f-fcd836e565a9 \ -H "Authorization: Bearer $TOPTALKING_API_KEY"const channelId = '742539b3-2c69-4acc-988f-fcd836e565a9';const res = await fetch(`https://platform.toptalking.com.br/v1/channels/${channelId}`, { method: 'DELETE', headers: { Authorization: `Bearer ${process.env.TOPTALKING_API_KEY}` },});const { deleted } = await res.json(); // trueimport osimport requests
channel_id = "742539b3-2c69-4acc-988f-fcd836e565a9"res = requests.delete( f"https://platform.toptalking.com.br/v1/channels/{channel_id}", headers={"Authorization": f"Bearer {os.environ['TOPTALKING_API_KEY']}"}, timeout=30,)res.raise_for_status()Resposta 200
Seção intitulada “Resposta 200”{ "id": "742539b3-2c69-4acc-988f-fcd836e565a9", "object": "channel", "deleted": true}| HTTP | code |
Quando acontece |
|---|---|---|
| 400 | invalid_field |
O canal é o Chat do site (webchat): remova pelo painel. |
| 403 | read_only_key |
Chave somente leitura. |
| 404 | resource_not_found |
O canal não existe, já foi removido ou é de outra organização. |
{ "error": { "type": "invalid_request_error", "code": "invalid_field", "message": "O Chat do site é gerenciado no painel (Configurações → Conexões).", "param": "channel_id", "request_id": "req_6f1d2c3b4a5e" }}Limite de conexões do plano
Seção intitulada “Limite de conexões do plano”Cada plano da TopTalking permite um número de conexões de WhatsApp (canais whatsapp). Canais disconnected também contam — só remover libera a vaga. O Chat do site não conta.
Ao passar do limite, POST /channels responde 422 limit_reached:
{ "error": { "type": "invalid_request_error", "code": "limit_reached", "message": "Seu plano permite 3 conexões de WhatsApp. Remova uma ou faça upgrade no painel.", "request_id": "req_6f1d2c3b4a5e" }}O que fazer: reconecte um canal existente com POST /channels/{channel_id}/connect em vez de criar outro, remova um canal que não usa mais ou faça upgrade do plano no painel.