Pular para o conteúdo

Quickstart

Em poucos minutos: contato criado, conversa aberta, mensagem enviada e etiqueta aplicada.

  • O token: avatar → Perfil → Token de acesso. Veja autenticação
  • O número da conta: está na URL do painel — /app/accounts/1/...
  • O número da caixa de entrada: Configurações → Caixas de entrada, na URL da caixa
Terminal window
curl -X POST "https://app.smart2.com.br/api/v1/accounts/1/contacts" \
-H "api_access_token: SEU_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Maria Silva",
"email": "[email protected]",
"phone_number": "+5511999990000",
"identifier": "ERP-8842"
}'
{
"payload": {
"contact": {
"id": 4521,
"name": "Maria Silva",
"email": "[email protected]",
"phone_number": "+5511999990000",
"identifier": "ERP-8842"
},
"contact_inbox": { "inbox": null, "source_id": null }
}
}

Guarde o id — 4521 aqui. Repare que o contato vem dois níveis abaixo: payload.contact.id.

O telefone precisa vir no formato internacional, com + e o código do país.

Terminal window
curl -X POST "https://app.smart2.com.br/api/v1/accounts/1/conversations" \
-H "api_access_token: SEU_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"inbox_id": 3,
"contact_id": 4521,
"status": "open"
}'
{
"id": 8821,
"inbox_id": 3,
"status": "open",
"meta": {
"sender": { "id": 4521, "name": "Maria Silva" },
"assignee_type": "User"
},
"created_at": 1758542400
}

O id é 8821 — esse é o número que aparece na URL da conversa no painel, e o que você usa nas chamadas seguintes.

Repare no created_at: número, não texto. Conversa usa segundos desde 1970. Veja convenções.

Terminal window
curl -X POST "https://app.smart2.com.br/api/v1/accounts/1/conversations/8821/messages" \
-H "api_access_token: SEU_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"content": "Oi Maria! Recebi seu pedido e já estou vendo aqui.",
"message_type": "outgoing"
}'

Isso sai de verdade pelo canal da caixa de entrada — chega no WhatsApp, no e-mail, no que for.

CampoPara quê
contentO texto
message_typeoutgoing sai para o cliente; incoming registra algo que ele disse por outro meio
privatetrue grava nota interna — fica na conversa, o cliente não vê

A nota interna é o uso mais comum para integração — avisar o atendente sem falar com o cliente:

Terminal window
curl -X POST "https://app.smart2.com.br/api/v1/accounts/1/conversations/8821/messages" \
-H "api_access_token: SEU_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "content": "Pedido #8842 faturado no ERP.", "private": true }'
Terminal window
curl -X POST "https://app.smart2.com.br/api/v1/accounts/1/contacts/4521/labels" \
-H "api_access_token: SEU_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "labels": ["lead", "site", "interesse-premium"] }'

A lista é substituída, não somada: mande sempre todas as etiquetas que o contato deve ficar tendo. Para etiquetar a conversa em vez do contato, o caminho é /conversations/8821/labels.

Etiqueta serve de base para segmento, campanha e relatório — vale usar um punhado de nomes combinados, não inventar um por integração.

import requests
BASE = "https://app.smart2.com.br/api/v1/accounts/1"
H = {"api_access_token": "SEU_TOKEN", "Content-Type": "application/json"}
# 1. contato
r = requests.post(f"{BASE}/contacts", headers=H, json={
"name": "Maria Silva",
"email": "[email protected]",
"phone_number": "+5511999990000",
"identifier": "ERP-8842",
})
r.raise_for_status()
contato_id = r.json()["payload"]["contact"]["id"]
# 2. conversa
r = requests.post(f"{BASE}/conversations", headers=H, json={
"inbox_id": 3, "contact_id": contato_id, "status": "open",
})
r.raise_for_status()
conversa_id = r.json()["id"]
# 3. mensagem
requests.post(f"{BASE}/conversations/{conversa_id}/messages", headers=H, json={
"content": "Oi Maria! Recebi seu pedido e já estou vendo aqui.",
"message_type": "outgoing",
}).raise_for_status()
# 4. etiquetas
requests.post(f"{BASE}/contacts/{contato_id}/labels", headers=H, json={
"labels": ["lead", "site"],
}).raise_for_status()
print(f"contato {contato_id}, conversa {conversa_id}")

Do lado do servidor — o token nunca vai ao navegador. Veja CORS.

const BASE = 'https://app.smart2.com.br/api/v1/accounts/1';
const H = {
api_access_token: process.env.SMART_TOKEN,
'Content-Type': 'application/json',
};
async function post(caminho, corpo) {
const r = await fetch(`${BASE}${caminho}`, {
method: 'POST', headers: H, body: JSON.stringify(corpo),
});
if (!r.ok) throw new Error(`${r.status} em ${caminho}: ${await r.text()}`);
return r.json();
}
async function quickstart() {
const { payload } = await post('/contacts', {
name: 'Maria Silva',
phone_number: '+5511999990000',
identifier: 'ERP-8842',
});
const contatoId = payload.contact.id;
const conversa = await post('/conversations', {
inbox_id: 3, contact_id: contatoId, status: 'open',
});
await post(`/conversations/${conversa.id}/messages`, {
content: 'Oi Maria! Recebi seu pedido e já estou vendo aqui.',
message_type: 'outgoing',
});
await post(`/contacts/${contatoId}/labels`, { labels: ['lead', 'site'] });
console.log(`contato ${contatoId}, conversa ${conversa.id}`);
}
quickstart().catch(console.error);

Abra Contatos, procure por Maria Silva. A ficha mostra as etiquetas e a conversa; a conversa mostra a mensagem que você enviou.

{
"name": "Maria Silva",
"email": "[email protected]",
"custom_attributes": {
"cnpj": "12.345.678/0001-90",
"plano": "premium"
}
}

A chave precisa ser a de um campo já criado no painel. Chave desconhecida é gravada mas não aparece em lugar nenhum — nem na ficha, nem em filtro, nem em relatório.

É o caminho para lead de site e venda, e o que alimenta a atribuição:

Terminal window
curl -X POST "https://app.smart2.com.br/api/v1/accounts/1/conversion_events" \
-H "api_access_token: SEU_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"conversion_identifier": "orcamento-site",
"email": "[email protected]",
"phone_number": "+5511999990000",
"name": "Maria Silva",
"value": 1200.00,
"utm_source": "google",
"utm_medium": "cpc",
"utm_campaign": "institucional",
"landing_page": "https://seusite.com.br/orcamento"
}'

Veja eventos de conversão.

Terminal window
curl -X POST "https://app.smart2.com.br/api/v1/accounts/1/conversations/8821/assignments" \
-H "api_access_token: SEU_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "assignee_id": 7 }'

Se o seu sistema precisa reagir a mensagem nova ou lead novo, webhook é melhor que consultar de tempos em tempos — lendo antes as três limitações dele, que estão logo na abertura da página.

401 — token ausente, errado, ou com espaço colado junto. Use .strip() no valor que veio da variável de ambiente.

404 na conversa — o número da conta ou da conversa está errado. Lembre que recurso de outra conta também devolve 404, não 403.

422 ao criar contato — a resposta diz o que foi, mas em inglês e tudo numa string:

{ "message": "Email is invalid", "attributes": ["email"] }

Repare na chave: é message, e os campos vêm em attributes. Os outros erros usam error. Veja convenções.

A mensagem não chegou no celular — a chamada pode ter dado certo e o canal ter recusado. No WhatsApp, quase sempre é a janela de 24 horas. Confira a conversa no painel: a mensagem aparece lá com o estado de entrega.