Contrato de handoff.
O Contrato de handoff v1 é a interface que o seu CRM implementa para receber leads do Jataí: três rotas HTTP autenticadas por token (health, receber lead e consultar estado) e uma rota de retorno, do lado do Jataí, para o desfecho. O lead chega com a organização, a pessoa, os números, o motivo e o histórico da conversa. Nunca traz estágio de pipeline.
O que a Entrega envia ao seu CRM, campo a campo. Versionado: o v1 continua funcionando quando sair o v2.
Visão geral.
O Jataí não escreve um adaptador para cada CRM. Publica um contrato, e cada plataforma o implementa no repositório dela, rodando a suíte de conformidade até ficar verde. Quem pluga uma marca não precisa de ninguém do Jataí no meio — e o Jataí não precisa conhecer o CRM.
Para um sistema legado que não vai implementar rota nenhuma, existe o adaptador genérico: ele mapeia os campos por configuração, sem código novo, e recusa escrever qualquer campo que denuncie estágio de pipeline.
As rotas.
| Rota | Quem implementa | Para quê |
|---|---|---|
POST {base}/health | o seu CRM | declara as versões do contrato que fala ({ "versoes": ["v1"], "ok": true }). Sem isto o Jataí teria de adivinhar o formato. |
POST {base}/leads | o seu CRM | recebe o lead entregue. Idempotente por externalId: a mesma chave duas vezes produz um lead só, e a reentrega responde duplicado: true, não erro. |
GET {base}/leads/{externalId} | o seu CRM | reconciliação, não sincronização: diz se conhece o lead e em que resultado ele está. Chave desconhecida responde 200 com `conhecido: false`, nunca 404. |
POST /handoff/retorno | o Jataí | o único caminho pelo qual o desfecho entra no Jataí. O seu CRM chama esta rota, autenticada com a chave de API da marca. |
Todas exigem token. A rota que recebe dado de pessoa real de uma marca, sem token, seria pública — e a suíte recusa a plataforma que aceita entrega sem autenticação.
O lead: `POST {base}/leads`.
| Campo | O que é |
|---|---|
versao | sempre "v1" |
externalId | a chave de idempotência (até 120 caracteres) |
entregueEm | o instante da entrega, em ISO 8601 |
gatilho | por que o lead está sendo entregue agora: resposta_positiva, selecao_em_lote, envio_individual ou temperatura |
organizacao | nome, site, tipo, pais, cidade e identificadores (um mapa: CNPJ, domínio…) |
pessoa | nome, cargo e contatos[]: cada um com tipo (email ou whatsapp), valor, confianca (0 a 1) e verificadoEm |
fit | um inteiro de 0 a 100: o quanto a organização casa com o perfil da marca |
jataiTemperatura | um inteiro de 0 a 100: o sinal de prioridade, para o vendedor. Vai para o campo jatai_temperatura |
valorEstimado | número ou null |
porQue | a frase que o operador leu na fila: por que este lead chegou aqui |
angulo | o ângulo usado no contato, ou null |
historico[] | até 50 mensagens: de (nos ou eles), canal, assunto, corpo e em |
atributos | um objeto livre para o que a marca queira levar junto |
{
"versao": "v1",
"externalId": "lead-8f3a2c",
"entregueEm": "2026-09-18T09:20:00-03:00",
"gatilho": "resposta_positiva",
"organizacao": {
"nome": "Instituto Horizonte de Formação",
"site": "https://exemplo.org.br",
"tipo": "instituto",
"pais": "BR",
"cidade": "Goiânia",
"identificadores": { "cnpj": "••.•••.•••/••••-••" }
},
"pessoa": {
"nome": "Helena Prado",
"cargo": "Coordenação pedagógica",
"contatos": [
{ "tipo": "email", "valor": "helena@exemplo.org.br", "confianca": 0.9, "verificadoEm": null }
]
},
"fit": 84,
"jataiTemperatura": 82,
"valorEstimado": null,
"porQue": "Respondeu pedindo valores; a comissão se reúne dia 22.",
"angulo": "Turma nova em fevereiro: decisão de material didático até novembro.",
"historico": [
{ "de": "nos", "canal": "email", "assunto": "Turma de fevereiro", "corpo": "…", "em": "2026-09-15T09:00:00-03:00" },
{ "de": "eles", "canal": "email", "assunto": "Re: Turma de fevereiro", "corpo": "…", "em": "2026-09-18T09:12:00-03:00" }
],
"atributos": {}
}O campo que nunca existirá.
Estágio de pipeline. O Jataí escreve atividade e jatai_temperatura, nunca estágio. Dois autores no mesmo campo destroem a confiança da equipe no CRM, e isso não se recupera. Por isso o contrato não tem o campo — não é um null permanente, é a ausência —, e a suíte recusa a plataforma que exige estágio para aceitar um lead.
O retorno: `POST /handoff/retorno`.
O Jataí não consulta o seu CRM. Quem avisa é ele, quando algo acontece com um lead entregue.
| Campo | O que é |
|---|---|
versao | sempre "v1" |
externalId | a chave do lead entregue |
resultado | virou_cliente, perdido, duplicado ou atividade_humana |
em | quando aconteceu, em ISO 8601 |
detalhe | texto livre opcional (até 1.000 caracteres) |
`atividade_humana` é o retorno mais importante. Depois da entrega, o Jataí segue dono do canal automatizado e o seu vendedor é dono da conversa direta: mensagem automática por cima de conversa humana queima o lead e a marca. Este retorno pausa toda Rota automática daquele lead, e ela só retoma se o lead for marcado como perdido ou esfriar.
Chave desconhecida responde 200 com conhecido: false: pode ser a reentrega de um retorno antigo, e um 4xx faria a plataforma repetir para sempre.
A suíte de conformidade.
A suíte roda contra a sua implementação de verdade, com dados de teste — ela escreve na plataforma, com externalId prefixado por conformance- para dar para achar e apagar depois. Sai com código 1 quando algo falha, para poder ser um passo de CI. São oito verificações:
- health declara a versão — sem isto o Jataí teria de adivinhar o formato.
- aceita um lead válido — é a rota que recebe o trabalho da máquina inteira.
- a mesma chave duas vezes produz um lead só — o Jataí reenvia toda vez que não recebe o ACK, e vai reenviar.
- sabe informar o estado de um lead conhecido — é como o Jataí reconcilia quando desconfia de ter perdido um retorno.
- chave desconhecida devolve 200 com `conhecido: false` — um 404 é indistinguível de rota fora do ar.
- recusa payload inválido com 4xx, e não aceita em silêncio — lead aceito e perdido é pior que lead recusado.
- recusa quem não tem o token.
- não exige estágio de pipeline.
jatai-conformance --url https://sua-plataforma/jatai --token SEU_TOKEN
# o token também pode vir de JATAI_TOKENA suíte é o pacote @jatai/conformance, entregue a quem vai plugar uma plataforma. Peça-a no seu convite.
Versionamento.
O campo versao diz qual contrato o lead segue, e o health diz quais o seu CRM fala. Quebrar contrato é a coisa mais cara que existe quando muitos consumidores dependem dele — por isso o v1 continua funcionando quando sair o v2.
Perguntas frequentes
O que acontece se o meu CRM não responder ao lead?
O Jataí reenvia — é por isso que a rota é idempotente. A mesma externalId duas vezes produz um lead só, e a reentrega responde duplicado: true, não erro.
O Jataí muda o estágio do lead no meu CRM?
Nunca. O contrato não tem o campo. O Jataí escreve atividade e temperatura; o estágio é do seu vendedor.
Como o Jataí sabe que o lead virou cliente?
O seu CRM avisa, chamando POST /handoff/retorno com resultado: "virou_cliente". O Jataí não consulta o CRM.
E se o meu sistema não puder implementar as rotas?
Para um sistema legado, o adaptador genérico mapeia os campos por configuração — sem código novo — e recusa escrever qualquer campo que denuncie estágio de pipeline.