API REST do WhatsApp da FlashConnect
A API REST da FlashConnect envia e lê mensagens do WhatsApp oficial (Cloud API da Meta) com uma chave ck_live_ no header Authorization. São 8 rotas que aceitam chave de API (envio, histórico, mídia, conversa, contato, agente, agenda e tarefas), controladas por 14 escopos. Fora da janela de 24 horas só passa template aprovado, e listar conversas, contatos e números é feito pelo servidor MCP com a mesma chave.
Atualizado em
Qual é a URL base da API do WhatsApp da FlashConnect?
Todas as rotas ficam sob uma única base e respondem JSON:
https://qqyphyubrxyouaqicdbo.supabase.co/functions/v1
- Corpo e respostas em JSON (
content-type: application/json). Datas em ISO 8601. - Tudo é por conta (tenant): a chave só enxerga os números, conversas e configurações da própria empresa. Recurso de outra conta responde
404, nunca403. - Erros têm sempre o formato
{ "erro": "mensagem", "codigo": "CODIGO" }. A lista completa está em códigos de erro da API. - A FlashConnect usa a API oficial do WhatsApp (Cloud API da Meta): as regras de janela de 24 h e de templates são da Meta e valem aqui também.
Como autenticar na API?
Toda chamada leva o header Authorization: Bearer <chave>. A chave de API começa com ck_live_.
Authorization: Bearer ck_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- Onde gerar: no painel, em Integrações → Nova chave (você escolhe os escopos) ou em Conectar IA (a chave já sai com todos os escopos). Só dono ou admin da conta gera chave, e a conta precisa ter cartão cadastrado.
- Uma vez só: o segredo aparece apenas na criação. Guardamos só o hash SHA-256 dele; se perder, gere outra.
- Revogar: pelo painel, em Integrações. Chave revogada responde
401 CHAVE_REVOGADAna hora. - Escopo: chave sem o escopo da rota responde
403 ESCOPO_INSUFICIENTE. - O prefixo
ck_test_é reservado e ainda não é emitido.
O painel chama as mesmas rotas com o login do usuário (JWT). Usuário logado tem todos os escopos; a diferença de comportamento aparece no envio (veja abaixo).
Quais são os escopos da chave de API?
São 14 escopos. Oito liberam rotas REST; seis valem só para as ferramentas do servidor MCP, que usa a mesma chave. Sem escolher nada, a chave nasce com messages:send, messages:read e agent:read.
| Escopo | Libera na API REST | Libera no MCP |
|---|---|---|
messages:send | POST /whatsapp-send | enviar_mensagem |
messages:read | GET /messages-list, POST /media-download | listar_conversas, ler_conversa |
conversations:write | POST /conversation-update | atualizar_conversa |
contacts:write | POST /contato-update | atualizar_contato |
contacts:read | nenhuma | buscar_contatos |
agent:read | GET /agent-config | ver_agente, listar_agentes, listar_catalogo |
agent:write | nenhuma | salvar_agente, salvar_produto, remover_produto, salvar_conhecimento, remover_conhecimento |
agenda:read | GET /agenda | listar_agendas, horarios_livres, listar_agendamentos |
agenda:write | POST /agenda, PATCH /agenda | marcar_agendamento, alterar_agendamento |
tasks:write | GET, POST e PATCH /tarefas | listar_tarefas, criar_tarefa, alterar_tarefa |
templates:read | nenhuma | listar_templates |
templates:write | nenhuma | criar_template |
webhooks:read | nenhuma | listar_webhooks |
webhooks:write | nenhuma | criar_webhook, alterar_webhook, remover_webhook |
Atenção: GET /tarefas (listar) também exige tasks:write; não existe tasks:read. As ferramentas status_setup e listar_numeros do MCP não exigem escopo.
Quais endpoints aceitam chave de API?
| Rota | O que faz | Escopo |
|---|---|---|
POST /whatsapp-send | Envia texto, template, imagem, vídeo, documento, áudio, figurinha ou mensagem interativa | messages:send |
GET /messages-list | Histórico de uma conversa, paginado | messages:read |
POST /media-download | Link temporário da mídia de uma mensagem (áudio para transcrever, imagem para analisar) | messages:read |
POST /conversation-update | Modo IA/humano, estado, etiquetas, atendente, agente e equipe | conversations:write |
POST /contato-update | Nome, e-mail, tags, notas e opt-out do contato | contacts:write |
GET /agent-config | Configuração do agente de IA, produtos, conhecimento, agenda, regras e equipes | agent:read |
GET · POST · PATCH /agenda | Agendas, horários livres, criar, remarcar e cancelar agendamentos | agenda:read / agenda:write |
GET · POST · PATCH /tarefas | Listar, criar e alterar cartões do quadro de tarefas | tasks:write |
Não aceitam chave de API (só o login do painel): api-key-create (criar chave) e a criação de templates. Para criar template ou webhook por máquina, use as ferramentas criar_template e criar_webhook do MCP.
Subir arquivo para enviar (media-upload)
Para enviar um arquivo que não está num link público, suba antes em POST /media-upload (multipart, campo arquivo) com a chave de API (escopo messages:send) e use o caminho devolvido em midia_caminho. Limites da Meta: imagem JPEG/PNG até 5 MB, figurinha WebP até 500 KB, vídeo MP4 e áudio até 16 MB, documento até 50 MB.
curl -X POST https://qqyphyubrxyouaqicdbo.supabase.co/functions/v1/media-upload \
-H "Authorization: Bearer ck_live_SUA_CHAVE" \
-F "arquivo=@catalogo.pdf"
# → {"caminho": "<tenant>/<uuid>.pdf", "mime": "application/pdf", "url": "…", "tamanho": 123456}
Como enviar mensagem no WhatsApp pela API?
POST /whatsapp-send · escopo messages:send.
| Campo | Tipo | Obrigatório | Notas |
|---|---|---|---|
phone_number_id | string | sim | Número de origem: o phone_number_id da Meta (veja listar_numeros no MCP ou o campo numero.phone_number_id dos eventos) |
para | string | sim | Telefone do contato no formato internacional, só dígitos, 8 a 15 (ex.: 5511999990000) |
tipo | string | não | text (padrão), template, image, video, document, audio, sticker ou interactive |
texto | string | se text | Conteúdo da mensagem |
template | objeto | se template | { "nome", "idioma"?, "componentes"? }. idioma padrão pt_BR; componentes no formato da Cloud API (parâmetros das variáveis) |
midia_url | string | se mídia* | URL https:// pública; a Meta baixa o arquivo de lá |
midia_caminho | string | se mídia* | Alternativa a midia_url: o caminho de um arquivo já guardado na FlashConnect (devolvido por media-upload ou media-download). Precisa ser da sua conta |
midia_mime | string | não | Tipo do arquivo, gravado no histórico |
legenda | string | não | Legenda de imagem, vídeo ou documento. Figurinha não aceita |
nome_arquivo | string | não | Nome exibido do documento |
voz | boolean | não | Em audio OGG/Opus, true envia como nota de voz |
interativo | objeto | se interactive | Objeto interactive da Cloud API (botões, lista), repassado como está |
autor | string | não | ia ou humano. Padrão: ia com chave de API, humano com login |
* Tipos de mídia (image, video, document, audio, sticker) exigem midia_url ou midia_caminho.
Regras do envio
- Janela de 24 h. Texto livre, mídia e interativas só passam se o contato escreveu nas últimas 24 h. Fora disso (ou sem conversa) a API responde
409 JANELA_EXPIRADAantes de chamar a Meta. Só template aprovado passa sempre. - Primeira mensagem. Template para um número que nunca falou com você cria o contato e a conversa na hora.
- Opt-out. Contato marcado com
opt_outnão recebe template (409 OPT_OUT). - Número pronto. O número precisa estar registrado na Cloud API (
409 NUMERO_NAO_REGISTRADO) e com a conexão válida (409 SEM_CREDENCIAL). - Modo da conversa. Envio por chave de API não muda o modo. Envio por login numa conversa em modo
iafaz a pessoa assumir a conversa (modohumano) e emiteconversation.handoff. - Assinatura. Com a assinatura pausada, cancelada ou aguardando cartão, o envio por chave responde
402(ASSINATURA_PAUSADAouASSINATURA_PENDENTE). - Status. A mensagem é gravada com status
sent; entregue, lida e falha chegam depois pelo webhookmessage.status.
Resposta 200
{
"ok": true,
"wa_message_id": "wamid.HBgNNTUxMTk5OTk5MDAwMBUCABEYEjQ1...",
"message_id": "9b2f1c7e-5d0a-4c1e-8f3b-2a6d4e8c1f90",
"conversation_id": "4e7a2b91-3c5d-4f6e-9a8b-1c2d3e4f5a6b",
"autor": "ia"
}
Erros possíveis: 400 (campo inválido), 402, 404 NUMERO_NAO_ENCONTRADO, 409 (JANELA_EXPIRADA, OPT_OUT, NUMERO_NAO_REGISTRADO, SEM_CREDENCIAL) e 502 quando a Meta recusa, com o codigo_meta original. Detalhes em códigos de erro.
curl: texto dentro da janela
BASE=https://qqyphyubrxyouaqicdbo.supabase.co/functions/v1
KEY=ck_live_...
curl -s -X POST "$BASE/whatsapp-send" \
-H "Authorization: Bearer $KEY" \
-H "content-type: application/json" \
-d '{"phone_number_id":"123456789012345","para":"5511999990000","texto":"Olá! Posso ajudar?"}'
curl: template com variável (funciona fora da janela)
curl -s -X POST "$BASE/whatsapp-send" \
-H "Authorization: Bearer $KEY" \
-H "content-type: application/json" \
-d '{
"phone_number_id": "123456789012345",
"para": "5511999990000",
"tipo": "template",
"template": {
"nome": "lembrete_consulta",
"idioma": "pt_BR",
"componentes": [
{ "type": "body", "parameters": [ { "type": "text", "text": "Ana" }, { "type": "text", "text": "14h" } ] }
]
}
}'
curl: imagem com legenda
curl -s -X POST "$BASE/whatsapp-send" \
-H "Authorization: Bearer $KEY" \
-H "content-type: application/json" \
-d '{"phone_number_id":"123456789012345","para":"5511999990000","tipo":"image","midia_url":"https://exemplo.com/cardapio.jpg","legenda":"Cardápio de hoje"}'
JavaScript (fetch)
const BASE = "https://qqyphyubrxyouaqicdbo.supabase.co/functions/v1";
const KEY = process.env.FLASHCONNECT_API_KEY; // ck_live_...
async function enviar(phoneNumberId, para, texto) {
const res = await fetch(`${BASE}/whatsapp-send`, {
method: "POST",
headers: { Authorization: `Bearer ${KEY}`, "content-type": "application/json" },
body: JSON.stringify({ phone_number_id: phoneNumberId, para, texto }),
});
const corpo = await res.json();
if (!res.ok) {
// ex.: 409 JANELA_EXPIRADA -> mande um template
throw new Error(`${res.status} ${corpo.codigo ?? ""}: ${corpo.erro}`);
}
return corpo; // { ok, wa_message_id, message_id, conversation_id, autor }
}
Como ler o histórico de uma conversa?
GET /messages-list?conversation_id=<uuid>&limite=50[&antes_de=<ISO>] · escopo messages:read.
limitede 1 a 200 (padrão 50). As mensagens vêm em ordem cronológica, a mais antiga primeiro.- Paginação por cursor: enquanto
tem_maisfortrue, repita a chamada comantes_de=proximo_antes_de. autor:contato,humano,iaousistema.sistemasão envios automáticos (lembrete de agenda, automação, mensagem de transferência ou encerramento): trate como contexto, não como fala do agente.direcao:inbound(do contato) ououtbound(enviada).
curl -s "$BASE/messages-list?conversation_id=4e7a2b91-3c5d-4f6e-9a8b-1c2d3e4f5a6b&limite=20" \
-H "Authorization: Bearer $KEY"
{
"conversation": {
"id": "4e7a2b91-3c5d-4f6e-9a8b-1c2d3e4f5a6b",
"contact_id": "7c1d2e3f-4a5b-4c6d-8e9f-0a1b2c3d4e5f",
"phone_number_id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"modo": "ia",
"estado": "aberta",
"etiquetas": ["orcamento"],
"janela_expira_em": "2026-10-24T13:05:00.000Z",
"ultima_msg_em": "2026-10-23T13:05:00.000Z",
"contacts": { "wa_id": "5511999990000", "nome": "Ana Souza", "nome_perfil": "Ana" }
},
"mensagens": [
{
"id": "0f1e2d3c-4b5a-4968-8776-655443322110",
"wa_message_id": "wamid.HBgN...",
"direcao": "inbound",
"autor": "contato",
"tipo": "text",
"conteudo": "Oi, vocês abrem sábado?",
"midia_url": null, "midia_mime": null, "midia_caminho": null, "midia_nome": null, "midia_erro": null,
"status": "delivered",
"erro_codigo": null, "erro_detalhe": null,
"template_nome": null,
"criado_em": "2026-10-23T13:05:00.000Z"
}
],
"tem_mais": false,
"proximo_antes_de": null
}
O phone_number_id da conversa é o id interno do número na FlashConnect, não o da Meta. Erros: 400 e 404 CONVERSA_NAO_ENCONTRADA.
Como baixar áudio, imagem e documento recebidos?
POST /media-download · escopo messages:read · corpo { "message_id": "<uuid>" }.
A FlashConnect baixa da Meta toda mídia recebida para o próprio armazenamento. Esta rota devolve um link assinado, válido por 1 hora, e baixa na hora se ainda não tiver baixado. O media_id que vem no webhook não abre sem o token da Meta: use sempre o message.id nesta rota.
curl -s -X POST "$BASE/media-download" \
-H "Authorization: Bearer $KEY" \
-H "content-type: application/json" \
-d '{"message_id":"0f1e2d3c-4b5a-4968-8776-655443322110"}'
{
"url": "https://qqyphyubrxyouaqicdbo.supabase.co/storage/v1/object/sign/...",
"expira_em": "2026-10-23T14:05:00.000Z",
"mime": "audio/ogg",
"nome": null,
"caminho": "…/recebidas/0f1e2d3c-4b5a-4968-8776-655443322110.ogg"
}
Erros: 404 MENSAGEM_NAO_ENCONTRADA; 410 quando não há como obter o arquivo (mensagem sem mídia, mídia expirada na Meta antes de ser salva); 503 em falha passageira, que vale tentar de novo.
Como passar a conversa para um humano (ou devolver para a IA)?
POST /conversation-update · escopo conversations:write.
| Campo | Tipo | Notas |
|---|---|---|
conversation_id | uuid | Obrigatório |
modo | ia | humano | humano pausa o agente de IA e registra assumida_em |
estado | aberta | pendente | resolvida | resolvida registra resolvida_em |
etiquetas | string[] | Substitui a lista (máximo 20) |
atribuido_a | uuid | null | Atendente da mesma conta |
agente_id | uuid | null | Agente de IA especialista que passa a conduzir; null volta ao agente do número ou ao padrão |
equipe_id | uuid | null | Equipe responsável. Com modo: "humano" e sem atribuido_a, a regra de distribuição da conta escolhe o atendente dentro da equipe |
motivo | string até 200 | Livre; vai no evento de handoff |
Envie ao menos um campo além de conversation_id (motivo sozinho não conta). Mudança de modo emite conversation.handoff; estado que vira resolvida emite conversation.resolved. Trocar só agente ou equipe não emite evento.
curl -s -X POST "$BASE/conversation-update" \
-H "Authorization: Bearer $KEY" \
-H "content-type: application/json" \
-d '{"conversation_id":"4e7a2b91-3c5d-4f6e-9a8b-1c2d3e4f5a6b","modo":"humano","motivo":"cliente pediu atendente"}'
Resposta 200: { "ok": true, "conversation": { id, contact_id, phone_number_id, modo, estado, etiquetas, atribuido_a, agente_id, equipe_id, assumida_em, resolvida_em } }. Erros: 400, 404 (CONVERSA_NAO_ENCONTRADA, USUARIO_NAO_ENCONTRADO, AGENTE_NAO_ENCONTRADO, EQUIPE_NAO_ENCONTRADA).
Como o meu backend lê a configuração do agente de IA?
GET /agent-config?phone_number_id=<id da Meta>[&conversation_id=<uuid>] · escopo agent:read · resposta com Cache-Control: private, max-age=60.
O agente devolvido é, nesta ordem: o especialista definido na conversa (com conversation_id), o agente ligado ao número, ou o agente padrão da conta. Passe sempre o conversation_id do evento: sem ele, o especialista da conversa é ignorado. Veja como montar o agente em agentes de IA.
{
"agente": { "id", "nome", "descricao", "ativo", "padrao", "persona", "objetivo", "instrucoes", "tom",
"idioma", "saudacao", "mensagem_ausencia", "horario", "handoff_palavras", "handoff_automatico",
"coleta_dados", "modelo", "temperatura", "max_mensagens_dia", "phone_number_id", "agenda_id",
"pode_agendar", "pode_criar_tarefa", "criado_em", "atualizado_em" },
"agenda": { "id", "nome", "duracao_min", "antecedencia_min_horas", "janela_dias", "disponibilidade" },
"produtos": [ { "id", "nome", "descricao", "categoria", "preco", "moeda", "unidade", "sku", "imagem_url", "destaque", "atributos" } ],
"conhecimento": [ { "id", "titulo", "conteudo", "tags" } ],
"regras": { "distribuicao", "somente_disponiveis", "devolver_ia_ao_resolver", "resolver_apos_horas",
"sla_primeira_resposta_min", "mensagem_transferencia", "mensagem_encerramento" },
"equipes": [ { "id", "nome", "descricao" } ],
"tenant": { "nome", "segmento", "timezone" },
"numero": { "id", "phone_number_id", "numero", "nome_verificado", "quality_rating", "messaging_limit", "registrado" }
}
- Só produtos e conhecimento ativos; produtos em destaque primeiro.
agendavem preenchida só se o agente pode agendar e tem uma agenda ativa; senãonull, e o agente não deve oferecer horários.agente.pode_criar_tarefadiz se o agente pode usarPOST /tarefas. A plataforma não bloqueia: quem respeita a flag é o seu backend.- Se
regras.mensagem_transferenciaestiver preenchida, a plataforma já envia essa mensagem ao contato quando a conversa vai para humano. Não envie de novo.
Erros: 400, 404 NUMERO_NAO_ENCONTRADO, 404 CONVERSA_NAO_ENCONTRADA, 404 AGENTE_NAO_CONFIGURADO.
Como atualizar os dados de um contato?
POST /contato-update · escopo contacts:write. Identifique o contato por contato (telefone, só dígitos) ou contact_id (uuid), nunca os dois.
| Campo | Tipo | Notas |
|---|---|---|
nome | string até 120 | null | Nome dado pelo atendimento. O nome do perfil do WhatsApp fica em nome_perfil |
email | string | null | Gravado em minúsculas |
tags | string[] | Substitui a lista |
adicionar_tags / remover_tags | string[] | Aplicadas sobre as tags atuais (ou sobre tags, se vier junto). Até 50 tags por contato, 50 caracteres cada |
notas | string até 4.000 | null | Anotações livres |
opt_out | boolean | true bloqueia envio de template para o contato |
curl -s -X POST "$BASE/contato-update" \
-H "Authorization: Bearer $KEY" \
-H "content-type: application/json" \
-d '{"contato":"5511999990000","nome":"Ana Souza","email":"ana@exemplo.com","adicionar_tags":["cliente"]}'
Resposta 200: { "ok": true, "contato": { id, wa_id, nome, nome_perfil, email, tags, notas, opt_out, atualizado_em } }. Erros: 400, 404 CONTATO_NAO_ENCONTRADO.
Como consultar horários e marcar agendamentos pela API?
Rota /agenda, para contas com o módulo de agenda. Datas com hora sempre em ISO 8601 com fuso (Z ou -03:00); sem fuso a API responde 400.
| Chamada | Escopo | O que faz |
|---|---|---|
GET /agenda?acao=agendas | agenda:read | Agendas ativas: id, nome, descricao, duracao_min, disponibilidade, antecedencia_min_horas, janela_dias |
GET /agenda?acao=horarios&agenda_id=&dia=YYYY-MM-DD[&dias=N] | agenda:read | Horários livres de 1 a 14 dias a partir de dia (data no fuso da conta). Já descontam disponibilidade, antecedência mínima, janela máxima e horários ocupados |
GET /agenda?acao=agendamentos&contato= ou &conversation_id= [&futuros=true] | agenda:read | Até 100 agendamentos do contato, por data de início. futuros=true traz só os que ainda vão acontecer (inclui cancelados: confira status) |
POST /agenda | agenda:write | Cria agendamento. Resposta 201 |
PATCH /agenda | agenda:write | Muda status, remarca ou altera observações |
Campos do POST /agenda
| Campo | Tipo | Obrigatório | Notas |
|---|---|---|---|
agenda_id | uuid | sim | Agenda ativa da conta |
inicio | ISO com fuso | sim | Precisa ser exatamente um inicio devolvido por acao=horarios. O fim é calculado pela duração da agenda |
titulo | string até 200 | sim | Ex.: "Avaliação" |
contato | telefone | não | Liga o agendamento ao contato e à conversa mais recente dele |
conversation_id | uuid | não | Liga à conversa e ao contato dela. Com contato junto, os dois precisam combinar |
observacoes | string até 2.000 | não | |
product_id | uuid | não | Produto ou serviço da conta |
PATCH /agenda recebe agendamento_id e ao menos um de: status (marcado, confirmado, concluido, cancelado, faltou), inicio (remarca, com a mesma checagem de horário livre) ou observacoes. O lembrete automático só funciona quando o agendamento está ligado a uma conversa. Agendamento criado por chave de API fica com origem: "ia".
curl -s "$BASE/agenda?acao=horarios&agenda_id=2d4f6a8c-0e1b-4c3d-9e5f-7a9b1c3d5e7f&dia=2026-10-26&dias=7" \
-H "Authorization: Bearer $KEY"
curl -s -X POST "$BASE/agenda" \
-H "Authorization: Bearer $KEY" \
-H "content-type: application/json" \
-d '{"agenda_id":"2d4f6a8c-0e1b-4c3d-9e5f-7a9b1c3d5e7f","inicio":"2026-10-26T09:00:00-03:00","titulo":"Avaliação","conversation_id":"4e7a2b91-3c5d-4f6e-9a8b-1c2d3e4f5a6b"}'
curl -s -X PATCH "$BASE/agenda" \
-H "Authorization: Bearer $KEY" \
-H "content-type: application/json" \
-d '{"agendamento_id":"6b8d0f2a-4c6e-4a1b-9d3f-5e7a9c1b3d5f","status":"cancelado"}'
Erros: 400 (incluindo CONVERSA_DE_OUTRO_CONTATO), 404 (AGENDA_NAO_ENCONTRADA, AGENDAMENTO_NAO_ENCONTRADO, CONTATO_NAO_ENCONTRADO, CONVERSA_NAO_ENCONTRADA, PRODUTO_NAO_ENCONTRADO), 409 AGENDA_INATIVA e 409 HORARIO_INDISPONIVEL: o horário não está entre os livres ou foi ocupado entre a consulta e a gravação. Consulte de novo e ofereça outro.
Como criar e concluir tarefas pela API?
Rota /tarefas, escopo tasks:write nos três métodos. Funciona com o quadro de tarefas da conta.
| Campo do POST | Tipo | Notas |
|---|---|---|
titulo | string até 200 | Obrigatório |
descricao | string até 4.000 | |
prioridade | baixa | media | alta | urgente | Padrão media |
prazo | ISO com fuso | |
responsavel_id | uuid | Atendente da conta |
conversation_id / contato | uuid / telefone | Mesma regra da agenda |
etiquetas | string[] | Máximo 20 |
- POST cria a tarefa na primeira coluna do quadro que não é de conclusão. Resposta
201com{ "ok": true, "tarefa": { ... } }. - PATCH recebe
tarefa_ide ao menos um decoluna_id,concluir: true,prioridade,prazo,responsavel_id,descricao.concluirmove para a primeira coluna de conclusão; não combine comcoluna_id. - GET
?conversation_id=ou?contato=[&abertas=true]: até 100 tarefas, mais recentes primeiro.
curl -s -X POST "$BASE/tarefas" \
-H "Authorization: Bearer $KEY" \
-H "content-type: application/json" \
-d '{"titulo":"Ligar para a Ana sobre o orçamento","prioridade":"alta","prazo":"2026-10-27T18:00:00-03:00","conversation_id":"4e7a2b91-3c5d-4f6e-9a8b-1c2d3e4f5a6b"}'
curl -s -X PATCH "$BASE/tarefas" \
-H "Authorization: Bearer $KEY" \
-H "content-type: application/json" \
-d '{"tarefa_id":"8a0c2e4f-6b8d-4f1a-9c3e-5b7d9f1a3c5e","concluir":true}'
Erros: 400, 404 (TAREFA_NAO_ENCONTRADA, COLUNA_NAO_ENCONTRADA, USUARIO_NAO_ENCONTRADO, CONVERSA_NAO_ENCONTRADA, CONTATO_NAO_ENCONTRADO, SEM_COLUNA).
Como listar conversas, contatos e números?
Não existe rota REST para listas. Elas saem pelo servidor MCP, com a mesma chave, por uma chamada JSON-RPC tools/call:
| Ferramenta MCP | Devolve | Escopo |
|---|---|---|
listar_conversas | Conversas mais recentes, com filtros estado, modo, nao_lidas, busca e limite (padrão 20, máximo 100) | messages:read |
buscar_contatos | Contatos por nome, telefone, e-mail ou tag (padrão 20, máximo 100) | contacts:read |
listar_numeros | Números conectados com o phone_number_id da Meta, qualidade e limite de envio | nenhum |
curl -s -X POST "$BASE/mcp" \
-H "Authorization: Bearer $KEY" \
-H "content-type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"listar_conversas","arguments":{"modo":"ia","limite":10}}}'
A resposta traz o resultado em result.structuredContent (objeto) e o mesmo JSON como texto em result.content[0].text. Erro de negócio volta com result.isError: true.
Como é o fluxo típico de um backend de IA?
- Recebe
message.receivedPelo webhook de saída. Reaja só quandodados.conversation.modoforia: emhumano, uma pessoa está conduzindo. - Lê o agente
GET /agent-config?phone_number_id=…&conversation_id=…com os valores do evento (pode guardar em cache por 60 s). - Lê o contexto
GET /messages-list?conversation_id=…&limite=30. Se a mensagem tem mídia,POST /media-download. - Responde
POST /whatsapp-sendcompara = dados.contact.wa_id. Se precisar, agenda (/agenda), cria tarefa (/tarefas) e grava o que coletou (/contato-update). - Passa para humano quando precisar
POST /conversation-updatecommodo: "humano", omotivoe, se quiser, aequipe_id. Depois disso, pare de responder. - Acompanha a entregaPelo evento
message.status(entregue, lida, falhou).
Perguntas frequentes
Como consigo uma chave de API da FlashConnect?
No painel, em Integrações (Nova chave) ou em Conectar IA. Só o dono ou um admin da conta pode gerar, e a conta precisa ter cartão cadastrado. O segredo começa com ck_live_ e aparece uma única vez: guardamos só o hash SHA-256, então não há como recuperá-lo depois.
Dá para enviar mensagem para quem nunca falou comigo pela API?
Sim, mas só com template aprovado pela Meta (tipo template no POST /whatsapp-send). A API cria o contato e a conversa na hora. Texto livre, mídia e mensagens interativas só passam dentro da janela de 24 horas desde a última mensagem do contato; fora dela a API responde 409 JANELA_EXPIRADA sem chamar a Meta.
Como listo conversas, contatos e números pela API?
Não há rota REST para listar. Use o servidor MCP com a mesma chave: as ferramentas listar_conversas, buscar_contatos e listar_numeros devolvem essas listas em JSON. O histórico de uma conversa específica sai pelo GET /messages-list.
Posso usar a API com o n8n, Make ou meu próprio backend?
Sim. Qualquer sistema que faça requisições HTTPS com o header Authorization: Bearer ck_live_ funciona. Para receber as mensagens do contato, cadastre um webhook de saída; para o n8n também há o nó MCP Client Tool apontando para o servidor MCP.
Uma chave pode ver dados de outra empresa?
Não. Cada chave pertence a uma única conta (tenant) e só enxerga números, conversas e configurações dela. Um recurso de outra conta responde 404, como se não existisse.
A mensagem enviada pela API aparece no painel?
Sim. Toda mensagem enviada fica gravada no histórico da conversa com autor ia (quando vem de chave de API) ou humano, e os status seguintes (entregue, lida, falhou) chegam pelo evento message.status do webhook.
Quer usar a FlashConnect?
O acesso está sendo liberado por convite. Fale com a gente no WhatsApp.
Pedir convite no WhatsApp