CRM e Radar pela API

Registre oportunidades e demandas por contato, acompanhe o histórico e priorize o que precisa de ação com o Radar.

Use a base https://botozap.com.br/api/v1 com Authorization: Bearer $BOTOZAP_KEY ou X-API-Key. A Conta é derivada da chave; não envie account_id. Os exemplos mostram o caminho depois desse prefixo.

Um contato pode ter várias oportunidades e demandas independentes do Funil de contatos, que continua funcionando como antes. Encerrar uma conversa não encerra registros de CRM. Retornos e notas das conversas estão em Atendimento pela API; compromissos, em Agenda e Google Calendar.

Permissões, plano e ambiente

EscopoPermite
crm:readListar e consultar oportunidades, demandas, histórico, conversas vinculadas, Radar e critérios.
crm:writeCriar e editar oportunidades e demandas, vincular conversas e configurar critérios do Radar.

As rotas seguem a disponibilidade do Funil no plano da Conta: sem ele, retornam 403 feature_unavailable. Chaves live e sandbox são aceitas, e cada uma só enxerga contatos e conversas de Contas de canal do próprio ambiente. Um registro de contato do outro ambiente responde 404 not_found. A única exceção é a gravação de critérios do Radar, que exige chave live.

Rotas

MétodoCaminhoResultado
GET/opportunities, /demandsLista paginada; customer_id obrigatório.
POST/opportunities, /demands201 com o registro em data.
GET/{recurso}/{id}Registro em data.
PATCH/{recurso}/{id}Registro atualizado; exige expected_version.
GET/{recurso}/{id}/activitiesHistórico, 20 itens por página.
GET / POST / DELETE/{recurso}/{id}/conversationsConsultar, criar ou remover vínculos com conversas.
GET/radarItens priorizados do Cliente.
GET/radar/stage-rulesCritérios configurados por etapa.
PUT/radar/stage-rules/{stage_id}Cria ou altera o critério de uma etapa.

{recurso} é opportunities ou demands. IDs são UUID; um valor malformado retorna 422 invalid_id.

Oportunidades

CampoTipoRegras
customer_idUUIDObrigatório na criação. Cliente do contato; imutável.
contact_idUUIDObrigatório na criação. Contato do mesmo Cliente e do ambiente da chave; imutável.
titletextoObrigatório na criação, 1 a 200 caracteres após remover espaços nas pontas.
statusenumopen, won, lost. Padrão open. lost exige outcome_reason.
stage_idUUID ou nullEtapa do Funil do mesmo Cliente. Mudar a etapa reinicia stage_entered_at.
owner_user_idUUID ou nullMembro da Conta (consulte GET /users).
value_centsinteiroValor em centavos, de 0 a 9007199254740991. Padrão 0.
currencytextoCódigo ISO de 3 letras maiúsculas, como BRL ou USD. Padrão BRL.
next_steptexto ou null1 a 1000 caracteres.
next_step_atISO 8601 ou nullData com fuso horário. Só é aceita quando há next_step.
notestexto ou nullAté 10000 caracteres.
outcome_reasontexto ou null1 a 2000 caracteres. Motivo do ganho ou da perda.
metadataobjetoCampos personalizados. Veja as regras abaixo.

Demandas

CampoTipoRegras
customer_id, contact_idUUIDObrigatórios na criação e imutáveis, como nas oportunidades.
titletextoObrigatório na criação, 1 a 200 caracteres.
statusenumopen, in_progress, waiting_customer, resolved, closed. Padrão open.
outcomeenum ou nullresolved, converted, not_applicable, customer_cancelled, lost, no_response.
due_atISO 8601 ou nullPrazo da demanda, com fuso horário.
opportunity_idUUID ou nullOportunidade do mesmo contato e Cliente.
owner_user_id, next_step, next_step_at, notes, metadata—Mesmas regras das oportunidades.

O desfecho acompanha o estado. Em resolved ou closed, outcome é obrigatório, e resolved só aceita outcome: "resolved". Nos demais estados, outcome precisa ser null: para reabrir uma demanda, envie o novo estado e outcome: null no mesmo PATCH. Combinações inválidas retornam 422 invalid_request.

closed_at é preenchido automaticamente quando a oportunidade sai de open ou a demanda chega a resolved ou closed, e volta a null ao reabrir.

Campos personalizados

metadata segue o formato dos campos de contato: objeto plano, até 32 chaves com letras minúsculas, dígitos e sublinhado (1 a 40 caracteres), valores de texto (até 256 caracteres), número ou booleano, e até 8192 bytes no total. null não é aceito como valor. No PATCH, o objeto enviado substitui o anterior por inteiro: leia o registro, altere as chaves e envie o objeto completo.

Criar

POST /opportunities
{
  "customer_id": "UUID-DO-CLIENTE",
  "contact_id": "UUID-DO-CONTATO",
  "title": "Plano anual",
  "value_cents": 129900,
  "currency": "BRL",
  "next_step": "Enviar proposta",
  "next_step_at": "2026-10-01T14:00:00-03:00"
}

O contato precisa pertencer ao Cliente informado e ao ambiente da chave. Etapa, responsável ou oportunidade relacionada de outro Cliente, contato ou Conta retornam 422 invalid_request. Campos fora das tabelas acima também são recusados com 422 invalid_request.

A resposta traz o registro completo, incluindo id, status, closed_at, version, created_at, updated_at e last_activity_at. Oportunidades também trazem stage_entered_at.

Editar sem sobrescrever outra alteração

Envie em PATCH apenas os campos que mudam, junto de expected_version com a version lida. Cada alteração incrementa a versão e atualiza last_activity_at.

PATCH /opportunities/{id}
{
  "expected_version": 3,
  "status": "lost",
  "outcome_reason": "Escolheu outro fornecedor"
}
  • Versão diferente da atual retorna 409 conflict sem aplicar a alteração. Releia e concilie.
  • Sem expected_version (inteiro positivo), o corpo é recusado com 422 invalid_request.
  • O corpo é estrito: campo desconhecido, customer_id ou contact_id retornam 422 invalid_request.
  • Um PATCH só com expected_version retorna 422 invalid_request.

Listar

GET /opportunities e GET /demands exigem customer_id e aceitam:

ParâmetroValores
page, per_pagePágina a partir de 1; per_page padrão 20, máximo 100.
contact_idUUID do contato.
owner_user_idUUID ou unassigned.
statusUm estado do recurso ou active (sem closed_at). Outro valor retorna 422 invalid_status.
qTrecho do título, até 200 caracteres.
stage_idSó oportunidades: UUID ou none (sem etapa).

A ordem é do mais recente para o mais antigo. A resposta traz data e meta (page, per_page, total_pages, total_count), além dos headers de paginação. Página além do último resultado retorna lista vazia.

Histórico

GET /{recurso}/{id}/activities?page=N retorna 20 eventos por página, do mais recente para o mais antigo; per_page é ignorado. Cada item contém:

CampoConteúdo
event_typecrm.opportunity.created, crm.opportunity.updated, crm.demand.created, crm.demand.updated, conversation_linked, conversation_unlinked ou legacy_imported (oportunidade criada a partir do Funil antigo).
actor_user_idPessoa que alterou pelo painel. Alterações feitas pela API ficam com null.
before_dataRegistro antes da alteração; null na criação e nos vínculos.
after_dataRegistro depois da alteração. Nos vínculos, inclui conversation_id.
id, created_atIdentificador e momento do evento.

Conversas vinculadas

GET /{recurso}/{id}/conversations lista { conversation_id, created_at }, 20 por página. POST vincula e DELETE desvincula; os dois recebem o mesmo corpo e respondem 200:

POST /demands/{id}/conversations
{ "conversation_id": "UUID-DA-CONVERSA" }

200
{ "data": { "conversation_id": "UUID-DA-CONVERSA", "linked": true } }

No DELETE, a resposta traz linked: false. Repetir um vínculo existente ou remover um vínculo ausente não gera erro. A conversa precisa ser do mesmo contato e Cliente do registro (senão, 422 invalid_request) e do ambiente da chave (senão, 404 not_found). Mensagens nas conversas vinculadas contam como atividade para o Radar.

Erros

StatusCódigoQuando
400invalid_jsonCorpo que não é JSON.
403feature_unavailablePlano sem Funil.
403sandbox_forbiddenChave sandbox em PUT /radar/stage-rules/{stage_id}.
404not_foundCliente, registro, contato ou conversa inexistente, de outra Conta ou de outro ambiente.
409conflictVersão obsoleta no PATCH ou no critério do Radar.
422invalid_idUUID malformado no caminho, em customer_id ou em filtros.
422invalid_statusFiltro status desconhecido.
422invalid_requestCampo inválido ou extra, vínculo de outro Cliente, combinação de estado e desfecho inválida.
422invalid_customer, invalid_filtersRadar sem customer_id válido ou com filtro desconhecido.
500internal_errorFalha ao consultar o plano ou o banco; tente novamente.

Radar de acompanhamento

GET /radar?customer_id=UUID exige crm:read e reúne, para um Cliente, o que precisa de ação: oportunidades, demandas, retornos pendentes e compromissos. A leitura não altera registros nem envia mensagens.

FiltroValores
bucketcritical, at_risk, scheduled
entity_typeopportunity, demand, return, appointment
owner_user_idUUID ou unassigned
reasonUm motivo da tabela abaixo.
page, per_pagePadrão 20, máximo 100.

Filtro com valor desconhecido retorna 422 invalid_filters. Críticos vêm primeiro, depois atenção e programados; dentro de cada grupo, os itens sem data e os de data mais próxima vêm antes. meta.counts traz os totais critical, at_risk e scheduled com os filtros de tipo, responsável e motivo, sem o filtro bucket; meta.total_count considera também o bucket. Páginas além do último resultado retornam lista vazia e preservam os totais.

Tipos de item

entity_typeEntra no Radar
opportunityOportunidade aberta. Usa os critérios da etapa atual.
demandDemanda não encerrada. Usa o padrão: 24 h de atenção, 72 h de criticidade, responsável e próximo passo exigidos.
returnRetorno pendente de uma conversa (ferramentas do Inbox). Exige responsável; o texto do retorno vira título e próximo passo.
appointmentCompromisso pendente ou confirmado, com régua ativa ou com falha/conflito de sincronização. Exige responsável.

Um item só aparece quando tem ao menos um motivo ou algo programado; oportunidades e demandas em dia ficam fora da lista.

Motivos

reasonNo painelQuando aparece
unassignedSem responsávelRegistro sem responsável quando o critério exige. Retornos e compromissos sempre exigem responsável.
missing_next_stepPróximo passo incompletoSem próximo passo com data, quando o critério exige, e sem régua programada ou compromisso futuro vinculado.
overdueRetorno ou prazo vencidoPróximo passo, prazo da demanda ou retorno com data vencida. Não se aplica a compromissos.
stalled_stageTempo excedido na etapaOportunidade na mesma etapa há mais horas que o prazo de atenção da etapa.
inactiveSem atividade recenteOportunidade ou demanda sem atividade no registro nem mensagem nas conversas vinculadas além do prazo de atenção, sem compromisso futuro nem régua programada.
automation_failedFalha na réguaRégua vinculada ao registro falhou.
automation_overdueEnvio automático atrasadoEnvio programado da régua atrasado há mais de 15 minutos.
automation_pausedRégua pausadaRégua vinculada pausada.
automation_stoppedRégua interrompida sem retorno definidoRégua interrompida sem próximo passo definido no registro.
confirmation_pendingCompromisso a confirmarCompromisso a confirmar: o próprio item ou o próximo compromisso vinculado à oportunidade ou demanda.
appointment_outcome_missingComparecimento não registradoCompromisso pendente ou confirmado cujo horário já terminou, sem comparecimento registrado.
calendar_conflictConflito com Google CalendarCompromisso com conflito entre a versão do BotoZap e a do Google Calendar.
calendar_sync_failedFalha na sincronização do compromissoCompromisso cuja sincronização com o Google Calendar falhou.

Prioridade

bucketNo painelRegra
criticalCríticosMotivo overdue, automation_failed, automation_overdue, appointment_outcome_missing, calendar_conflict ou calendar_sync_failed; ou oportunidade/demanda sem atividade, compromisso futuro nem régua programada além do prazo crítico; ou oportunidade na etapa além do prazo crítico.
at_riskPrecisam de atençãoQualquer outro motivo.
scheduledProgramadosSem motivo, com régua programada, compromisso futuro vinculado, item do tipo appointment ou retorno com data futura.

Cada item traz id, entity_type, customer_id, contact_id, conversation_id (retornos e compromissos), title, owner_user_id, stage_id, next_step, next_step_at, bucket, reasons (lista), last_activity_at, automation_status, automation_due_at, automation_run_id, automation_error e bucket_priority. Quando uma oportunidade ou demanda sem próximo passo tem um compromisso futuro vinculado, o próximo passo exibido é esse compromisso.

Critérios por etapa

GET /radar/stage-rules?customer_id=UUID lista as etapas configuradas. Etapa sem configuração usa atenção após 24 horas e criticidade após 72 horas, exigindo responsável e próximo passo. O critério vale para as oportunidades da etapa: tempo na etapa e última atividade são avaliados separadamente.

PUT /radar/stage-rules/{stage_id}
{
  "customer_id": "UUID-DO-CLIENTE",
  "expected_version": 0,
  "cold_hours": 48,
  "critical_hours": 120,
  "require_owner": true,
  "require_next_step": false
}
  • cold_hours (atenção): inteiro de 1 a 8760.
  • critical_hours: inteiro de 1 a 26280, maior ou igual a cold_hours.
  • Todos os campos são obrigatórios e o corpo é estrito. Erros de validação retornam 422 invalid_request.
  • Na primeira configuração, envie expected_version: 0; depois, a versão consultada. Versão obsoleta retorna 409 conflict.
  • Etapa de outro Cliente retorna 404 not_found.

A gravação exige crm:write e chave live, porque o critério vale para os dois ambientes do Cliente; chave sandbox recebe 403 sandbox_forbidden. A listagem do Radar respeita o ambiente da chave. No painel, qualquer membro da conta altera critérios.

Eventos

Criar ou alterar registros publica crm.opportunity.created, crm.opportunity.updated, crm.demand.created e crm.demand.updated, com before_data e after_data. Consulte o formato em Eventos de webhook.

Os erros comuns de chave, escopo e limite estão em Autenticação. A referência /v1 lista todas as rotas.