A API do CRM Asender: o contato canônico da pessoa (com estágio, dono, origem, consentimento e timeline), os segmentos que recortam a base, as jornadas de automação, os alertas de captura, os destinos de lead (webhooks e integrações de conversão) e as configurações de retenção e uso. É um sistema à parte, com endereço próprio — o CRM fora do ar é o CRM fora do ar, e não arrasta as outras ferramentas.
Base URL:https://api.crm.asender.net
Autenticação: sessão do usuário (Authorization: Bearer <token> ou o cookie asender_session) + o header X-Asender-Tenant
Formato: JSON (application/json; charset=utf-8)
Esta é a API que o painel do CRM consome. Diferente da Mail e da Platform, ela não aceita API key: é uma superfície de sessão, pensada para o usuário logado operando a própria conta. Integração máquina-a-máquina com dado de CRM ainda não tem superfície pública.
Autenticação
Toda rota de /v1 (fora das probes de saúde) exige uma sessão válida. O token de sessão é emitido pelo Identity Server (OIDC / OAuth 2.1 + PKCE) e chega de duas formas equivalentes:
Authorization: Bearer <token-de-sessão>
ou, no navegador, pelo cookie asender_session que o painel já mantém. O serviço valida o token no asender_auth_api a cada requisição — token ausente, inválido ou de sessão sem usuário responde 401; se o serviço de identidade estiver fora do ar, a resposta é 503 (a distinção importa: 401 manda refazer login, 503 manda olhar o auth).
A conta em que você opera — X-Asender-Tenant
Um usuário pode pertencer a mais de uma conta. O header X-Asender-Tenant diz em qual conta a requisição opera; ele aceita o id ou o slug da conta:
X-Asender-Tenant: acme-corp
O header é uma preferência, não uma autorização: o que impede operar em conta alheia é a checagem de pertinência contra a lista de contas que a sessão prova serem suas. Um tenant fora dessa lista responde 404 (não 403 — um 403 confirmaria que a conta existe, e é assim que se enumeram contas alheias). Sem o header, a requisição cai na primeira conta da sessão.
Acesso à ferramenta
Ter sessão não basta: a conta precisa ter o produto CRM habilitado. Quem não tem acesso à ferramenta recebe 404 em todas as rotas de /v1 — o mesmo 404 de recurso inexistente, de propósito (um 403 contaria a quem não tem acesso que a ferramenta existe; isso se descobre pelo site, não pela API).
Erros
Toda falha usa o mesmo envelope — um campo só, erro, com a mensagem legível:
{ "erro": "contato não encontrado" }
A mensagem descreve o que está errado no pedido, nunca o estado interno: um erro nunca vaza schema, nome de tabela ou mensagem de driver (isso vai para o log do servidor, com trace_id).
código HTTP
quando
400
corpo malformado, campo desconhecido (contrato estrito), query string inválida, cursor adulterado
401
sessão ausente ou inválida (sem tenant na sessão quando o tenant não chegou ao contexto)
404
recurso não encontrado, de outra conta, ou sem acesso à ferramenta (não revela existência alheia)
409
conflito de unicidade (contato com e-mail repetido, segmento com nome em uso)
422
corpo bem formado mas conteúdo inválido pela regra de negócio (estágio desconhecido, jornada com buraco na numeração, recebe ausente no consentimento)
500
falha interna (mensagem genérica; o erro real vai para o log)
503
serviço de identidade fora, ou dependência opcional desligada (ex.: exportação sem trilha)
O corpo de escrita é lido com contrato estrito: campo desconhecido é 400, não é ignorado em silêncio — é o que barra mass assignment (um tenant_id no corpo vira erro explícito, não uma conta escolhida pelo cliente). O limite de corpo é 256 KiB.
Paginação
As coleções longas — contatos e a timeline de um contato — paginam por cursor opaco, nunca por offset:
GET /v1/contatos?limite=50
→ { "contatos": [...], "proximo": "eyJ…" }
GET /v1/contatos?limite=50&cursor=eyJ…
Passe proximo de volta como cursor. Vazio significa que acabou. Um cursor adulterado responde 400. O cursor é cifrado de propósito: o id interno é uma sequência global, e devolvê-lo cru entregaria o volume e a ordem da base. As demais coleções (segmentos, alertas, destinos, jornadas) são curtas e voltam inteiras.
Convenções que valem para todos os recursos
O tenant nunca vem do corpo nem da URL — vem da sessão. O mesmo vale para o autor de uma nota ou exportação: é quem a sessão provou ser, não um campo do pedido. É o que mantém a trilha de auditoria confiável.
404 é o "não é seu" — contato, segmento, jornada, destino ou alerta de outra conta respondem o mesmo 404 de um id que nunca existiu.
Datas saem em UTC, formato YYYY-MM-DDTHH:MM:SSZ.
Jornadas — /v1/jornadas
A automação: gatilho + passos. O contato entra pelo gatilho e caminha pelos passos (esperar, agir, condição), um de cada vez e na ordem.
Uma jornada nasce sempre desligada (ativa: false): criar e ativar são operações separadas porque ativar tem consequência no mundo — assim que liga, o próximo lead capturado entra nela e recebe mensagem, e não há desfazer para e-mail enviado.
Corpo: nome (obrigatório), gatilho e passos. Os passos são numerados de 1 em diante, sem buraco. Gatilhos: lead_capturado, campo_mudou, inatividade, evento_pixel. Tipos de passo: esperar (exige espera > 0), agir (exige acao conhecida: email, push, webhook, mudar_estagio, entrar_lista), condicao (exige se_pular_ir para um passo existente).
201 → a Jornada criada. 422 se o nome faltar ou a validação não fechar (numeração com buraco, ação desconhecida, salto inválido).
espera é uma duração em nanossegundos (o time.Duration do Go); 1 dia = 86400000000000.
GET /v1/jornadas/{id} — obter
200 → a Jornada; 404 se não existe ou é de outra conta.
PUT /v1/jornadas/{id}/ativa — ligar/desligar
Corpo: { "ativa": true }. Ligar revalida a jornada (ela pode ter sido editada depois de criada); desligar não revalida — uma jornada quebrada tem de poder ser parada. 200 → a Jornada; 422 ao tentar ligar uma jornada inválida.
Contatos — /v1/contatos
O contato canônico. O e-mail e o telefone são PII cifrada no banco e só aparecem decifrados na leitura de quem é dono da conta; nunca saem os índices cegos (HMAC de dedup), sob risco de enumeração.
GET /v1/contatos — listar (paginado)
Query: estagio (allowlist: novo, contatado, qualificado, cliente, descartado), limite, cursor. Um estagio desconhecido é 400 (o silêncio mentiria: quem filtra por um plural e recebe a base inteira acha que não há ninguém).
Corpo: email, telefone, nome, estagio, dono_id, marcadores. Ao menos um de e-mail/telefone. Nasce em novo se o estágio não vier. 201 → o Contato; 409 se já existe contato com aquele identificador; 422 se a validação falha.
GET /v1/contatos/{id} — obter
200 → o Contato; 404 se não é seu.
PATCH /v1/contatos/{id} — atualizar (parcial)
Campo ausente preserva o que havia; marcadores: [] remove todos (a lista vazia é intencional). 200 → o Contato.
DELETE /v1/contatos/{id} — apagar o contato (soft delete)
Corpo opcional { "motivo": "..." }. Apagar é reversível (ADR-0112): o contato ganha apagado_em/por/motivo e some das listagens, relatórios e jornadas, mas nada é destruído — o painel master restaura. Registra contato_apagado na timeline. 204 sem corpo; 404 cobre "não existe", "de outra conta" e "já apagado". Só existe quando o serviço tem a trilha ligada; senão, 503.
/v1/pedidos-exclusao — o pedido do titular (LGPD art. 18)
A plataforma nunca apaga dado do contratante por conta própria. O pedido do titular vira uma task que um administrador da conta aprova ou recusa:
POST /v1/pedidos-exclusao{contato_id, solicitante, canal, motivo?} — qualquer membro registra; 201 com o pedido pendente. Não apaga nada. Avisa os admins pela central de notificações. 409 se já há pedido pendente para o contato.
GET /v1/pedidos-exclusao?status=&cursor=&limite= — a fila (só admin; quem não é recebe 404).
POST /v1/pedidos-exclusao/{id}/aprovar — só admin (decidido no servidor pelo PDP): anonimiza aquele contato irreversivelmente, na mesma transação que a timeline e a auditoria; 200 com o pedido executado.
POST /v1/pedidos-exclusao/{id}/recusar{motivo} — só admin; motivo obrigatório (422); nada é apagado. 409 se o pedido já foi decidido.
GET /v1/contatos/exportar.csv — exportar
Query opcional limite (teto de 10.000). Devolve um CSV (não JSON) com Content-Disposition: attachment, e registra a exportação na timeline antes de o arquivo sair (LGPD art. 37 — sem trilha, não exporta). 503 se a trilha não estiver disponível.
A trilha de auditoria do contato: mudanças de estágio, mensagens, submissões e notas manuais. Mora sob o contato de propósito — não há rota de topo que despejaria o histórico da conta inteira.
GET /v1/contatos/{id}/atividades — listar (paginado)
Query: limite, cursor. 200 → { "atividades": [ Atividade, … ], "proximo": "eyJ…", "total": 42 }. 404 se o contato não é seu.
POST /v1/contatos/{id}/atividades — anexar nota
Corpo: { "texto": "..." } (até 4000 caracteres). Só nota: os outros tipos são consequência do que o sistema fez, e deixar o cliente escrevê-los permitiria forjar a trilha. O autor vem da sessão, não do corpo. 201 → a Atividade; 422 se o texto é vazio ou longo demais.
Consentimento — /v1/contatos/{id}/consentimento
A preferência da pessoa, canal a canal (email, push).
GET /v1/contatos/{id}/consentimento
200 → { "recebe": { "email": true, "push": false }, "fuso": "America/Sao_Paulo" }. Responde todos os canais conhecidos, inclusive os sem opt-out. O campo é recebe (positivo) e não opt_out — uma negação no nome faria toda leitura exigir uma inversão mental que alguém erra, e o erro liga o envio para quem pediu para sair.
PUT /v1/contatos/{id}/consentimento
Corpo: { "canal": "email", "recebe": false, "origem": "painel" }. Um canal por vez, e recebe é obrigatório — sua ausência é 422 (com bool comum, "esqueci o campo" seria indistinguível de "descadastra esta pessoa"). 200 → o estado relido do banco.
Segmentos — /v1/segmentos
Conjuntos salvos de critérios que recortam a base. Cada critério é campo + operador + valor; os critérios se combinam por conjuncao (e / ou, padrão e).
201 → { "segmento": Segmento, "alcance": 128 }. 409 se o nome já existe; 422 se um campo/operador está fora da allowlist ou não há critério.
POST /v1/segmentos/previa — alcance sem salvar
Mesmo corpo do criar; não grava nada, só responde quantas pessoas o segmento alcança agora. 200 → { "alcance": 128 }.
GET /v1/segmentos/{id} — obter (com alcance)
200 → { "segmento": Segmento, "alcance": 128 }. O alcance vem junto porque é a única razão de abrir um segmento; alcance: -1 significa "não consegui contar" (distinto de 0, que é "não alcança ninguém").
PUT /v1/segmentos/{id} — substituir
PUT e não PATCH: um segmento é a sua lista de critérios, e mesclar listas não tem significado. 200 → { "segmento", "alcance" }; 409/404/422 como no criar.
DELETE /v1/segmentos/{id} — remover
Remoção lógica. 204 sem corpo.
Alertas — /v1/alertas
Avisam quando a captura para ou a qualidade cai. Tipos: sem_leads, queda_qualidade. Estado: calmo / disparado.
GET /v1/alertas — listar
200 → { "alertas": [ Alerta, … ] }.
POST /v1/alertas — criar
Corpo: nome, tipo, limiar, janela_minutos, destino_id (opcional), ativo (opcional). 201 → o Alerta; 422 se a regra não valida (janela curta demais, limiar fora de faixa).
GET /v1/alertas/eventos — histórico de transições
Query opcional limite. 200 → { "eventos": [ AlertaEvento, … ] }. Da conta, não de um alerta: quem investiga "o que aconteceu ontem" quer a linha do tempo inteira.
PUT /v1/alertas/{id} — atualizar
Mudar a configuração acalma o alerta (ele passa a observar outra coisa). 200 → o Alerta; 404 se não é seu.
DELETE /v1/alertas/{id} — remover
204 sem corpo.
Destinos de lead — /v1/destinos
Para onde o lead capturado é entregue: webhooks do cliente. O segredo de assinatura nunca volta na resposta — só o booleano tem_segredo.
GET /v1/destinos — listar
200 → { "destinos": [ Destino, … ] }.
POST /v1/destinos — criar
Corpo: nome, url (http/https; a rede interna é recusada com 422), segredo (opcional), ativo. 201 → o Destino.
PUT /v1/destinos/{id} — atualizar
segredo ausente preserva o gravado (a tela nunca recebe o valor atual, e apagá-lo a cada edição de nome derrubaria a assinatura). 200 → o Destino.
DELETE /v1/destinos/{id} — remover
204 sem corpo.
GET /v1/destinos/{id}/entregas — diagnóstico
Query opcional limite. 200 → { "entregas": [ Entrega, … ] }. O payload não volta (carrega PII) — só estado, código e tentativas.
POST /v1/destinos/{id}/testar — entrega de teste
Enfileira uma entrega de teste pela mesma fila das reais (mesmo guard do piso 18, mesma assinatura). 202 → { "enfileiradas": 1, "aviso": "…" }; 404 se o destino está inativo ou não existe. Acompanhe o resultado em /entregas.
Integrações de conversão — /v1/integracoes-de-conversao
O mesmo conjunto de rotas dos destinos, para o outro assunto: mandar a conversão de volta à plataforma de anúncio (hoje o provedor meta). São um grupo separado porque, numa lista só, quem procura uma acharia as duas — e a integração de conversão não tem URL própria (o endereço da API é do provedor e é fixo; deixar o cliente escolhê-lo permitiria vazar o token de acesso para qualquer lugar). O corpo pede provedor (meta) e config (com pixel_id).
GET /v1/integracoes-de-conversao → { "integracoes": [ Destino, … ] }
POST /v1/integracoes-de-conversao → 201Destino
PUT /v1/integracoes-de-conversao/{id} → 200Destino
DELETE /v1/integracoes-de-conversao/{id} → 204
GET /v1/integracoes-de-conversao/{id}/entregas → { "entregas": [ … ] }
POST /v1/integracoes-de-conversao/{id}/testar → 202
Configurações da conta
GET /v1/configuracoes/retencao — política de retenção
200 → { "retencao": { "dias": 90, "anonimizados_total": 12, … } }. Conta sem política responde dias: null (o estado normal), não 404.
PUT /v1/configuracoes/retencao — definir
Corpo: { "dias": 90 } ou { "dias": null } (guardar indefinidamente). O campo ausente é 400 (não desliga por engano); null é a ordem explícita de manter para sempre. 422 se o prazo sai da faixa de 30 a 3650 dias.
GET /v1/uso — consumo da conta
Query opcional periodo=YYYY-MM (padrão: mês corrente). 200 → { "uso": UsoView }. Os números locais (quantos contatos, quantos entraram no mês) sempre voltam; a quota e os contadores de envio vivem no core, e com ele fora a resposta sai com core_disponivel: false e quota_conhecida: false (nunca "ilimitado" — a tela mostra o que sabe e diz o que não conseguiu saber).
Superfície interna (não pública). O CRM também expõe um canal interno de control plane e uma sessão de suporte (somente leitura), reservados aos serviços da casa. Nada disso é superfície de integração e não está documentado aqui — a superfície pública é a sessão do usuário.
Referência
Toda operação registrada no código, com o que faz, o que recebe e o que devolve.
Alertas
GET/v1/alertas
Lista os alertas da conta.
Onde é usada
tela de alertas.
Efeitos
uma leitura.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
Respostas
código
significado
200
os alertas.
401
sessão ausente ou inválida.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/alertas' \
-H 'Authorization: Bearer SEU_TOKEN'
POST/v1/alertas
Cria um alerta.
Onde é usada
tela de alertas.
Efeitos
uma escrita.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
Respostas
código
significado
201
o alerta criado.
400
corpo malformado, campo desconhecido ou query inválida.
401
sessão ausente ou inválida.
422
corpo bem formado, mas o conteúdo não passa na regra de negócio.
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
id
path
sim
id público do recurso.
Respostas
código
significado
204
removido.
401
sessão ausente ou inválida.
404
recurso inexistente, de outra conta, ou sem acesso à ferramenta.
uma escrita. Mudar a configuração ACALMA o alerta: ele passa a observar outra coisa, e manter o estado faria a próxima avaliação comparar maçã com laranja — ele não avisaria pela condição NOVA, porque já estaria "disparado" pela antiga.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
id
path
sim
id público do recurso.
Respostas
código
significado
200
o alerta atualizado.
400
corpo malformado, campo desconhecido ou query inválida.
401
sessão ausente ou inválida.
404
recurso inexistente, de outra conta, ou sem acesso à ferramenta.
422
corpo bem formado, mas o conteúdo não passa na regra de negócio.
Lista o histórico de transições dos alertas da conta.
Onde é usada
tela de alertas — a linha do tempo.
Efeitos
uma leitura. Da CONTA, e não de um alerta: quem investiga "o que aconteceu ontem" quer a linha do tempo inteira, e paginar por alerta a obrigaria a abrir um por um.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
limite
query
não
máximo de itens por página (inteiro positivo).
Respostas
código
significado
200
os eventos.
400
corpo malformado, campo desconhecido ou query inválida.
401
sessão ausente ou inválida.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/alertas/eventos' \
-H 'Authorization: Bearer SEU_TOKEN'
clientes
GET/v1/clientessem schema na spec
GET /v1/alertas.
Onde é usada
tela de alertas.
Efeitos
uma leitura.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/clientes' \
-H 'Authorization: Bearer SEU_TOKEN'
GET /v1/clientes/{id}. Outra conta = 404, como inexistente.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/clientes/id_AQUI' \
-H 'Authorization: Bearer SEU_TOKEN'
PATCH/v1/clientes/{id}sem schema na spec
PUT /v1/alertas/{id}.
Onde é usada
tela de alertas.
Efeitos
uma escrita. Mudar a configuração ACALMA o alerta: ele passa a observar outra coisa, e manter o estado faria a próxima avaliação comparar maçã com laranja — ele não avisaria pela condição NOVA, porque já estaria "disparado" pela antiga.
Conta sem política responde 200 com dias: null, não 404.
Onde é usada
tela de configurações da conta.
Efeitos
uma leitura. Conta sem política configurada responde 200 com dias: null — e não 404: "não configurei retenção" é o estado NORMAL, e a tela precisa dele para desenhar o formulário vazio.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
Respostas
código
significado
200
a política.
401
sessão ausente ou inválida.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/configuracoes/retencao' \
-H 'Authorization: Bearer SEU_TOKEN'
PUT/v1/configuracoes/retencao
Define a política de retenção.
dias ausente é 400; null guarda indefinidamente; fora de 30..3650 é 422.
Onde é usada
tela de configurações da conta.
Efeitos
uma escrita; passa a anonimizar contato antigo em até uma hora. # null desliga, ausente é erro Os dois cairiam no mesmo ponteiro nil se o corpo fosse decodificado direto — e um cliente que esquecesse o campo desligaria a retenção sem querer. null é uma ORDEM ("guarde para sempre"); campo ausente é um pedido malformado.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
Respostas
código
significado
200
a política salva.
400
corpo malformado, campo desconhecido ou query inválida.
401
sessão ausente ou inválida.
422
corpo bem formado, mas o conteúdo não passa na regra de negócio.
Lê o consumo da conta (números locais + quota do core).
Os números locais sempre voltam; com o core fora, core_disponivel: false.
Onde é usada
tela de conta/plano.
Efeitos
uma leitura local e até duas chamadas ao core. # O core fora do ar NÃO derruba esta rota Os números locais (quantos contatos, quantos entraram no mês) são a metade que o CRM sabe sozinho, e são justamente a metade que a tela usa todo dia. Com o core fora, a resposta sai com core_disponivel: false — a tela mostra o que tem e diz o que não conseguiu saber (piso 10).
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
periodo
query
não
mês no formato AAAA-MM (padrão, o mês corrente).
Respostas
código
significado
200
o consumo da conta.
400
corpo malformado, campo desconhecido ou query inválida.
401
sessão ausente ou inválida.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/uso' \
-H 'Authorization: Bearer SEU_TOKEN'
Consentimento
GET/v1/contatos/{id}/consentimento
Lê a preferência do contato, canal a canal.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
id
path
sim
id público do recurso.
Respostas
código
significado
200
o que o contato recebe por canal.
401
sessão ausente ou inválida.
404
recurso inexistente, de outra conta, ou sem acesso à ferramenta.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/contatos/id_AQUI/consentimento' \
-H 'Authorization: Bearer SEU_TOKEN'
PUT/v1/contatos/{id}/consentimento
Muda a preferência de um canal (um por vez).
recebe é obrigatório; sua ausência é 422 para não descadastrar por engano.
Onde é usada
tela de contato, e o link de descadastro via BFF.
Efeitos
cria ou remove a linha de opt-out. # recebe é ponteiro, e a ausência é ERRO Com um bool comum, um corpo sem o campo viria como false — e "esqueci de mandar o campo" seria indistinguível de "descadastra esta pessoa". O ponteiro transforma a omissão em 422 explícito.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
id
path
sim
id público do recurso.
Respostas
código
significado
200
o estado relido do banco.
400
corpo malformado, campo desconhecido ou query inválida.
401
sessão ausente ou inválida.
404
recurso inexistente, de outra conta, ou sem acesso à ferramenta.
422
corpo bem formado, mas o conteúdo não passa na regra de negócio.
POST /v1/contatos/{id}/promover (D1, 028/029). Sem corpo — a ação é binária, e um corpo que aceitasse `promovido_em`/`promovido_por` do cliente deixaria a data e o autor da promoção sob controle de quem chama a API.
Onde é usada
botão "Promover a contato" nas telas Leads e Contatos.
Efeitos
escreve a coluna, a timeline (ciclo_mudou) e o outbox (crm.contact.promoted), atômico (repo.ContatoPG.MudarCiclo). Promover quem já é contato responde 200 sem gerar nova atividade nem novo evento (idempotente) — não é erro repetir o clique.
POST /v1/contatos/{id}/rebaixar — reverte uma promoção feita por engano.
Onde é usada
ação "Rebaixar a lead" na ficha do contato.
Efeitos
escreve a coluna e a timeline (ciclo_mudou); NÃO publica evento — só a promoção é fato que jornadas/relatórios querem (doc-comment de eventos.SubjectContatoPromovido).
GET/v1/contatos/{id}/visita-pagessem schema na spec
GET /v1/clientes/{id}. Outra conta = 404, como inexistente.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/contatos/id_AQUI/visita-pages' \
-H 'Authorization: Bearer SEU_TOKEN'
Contatos
GET/v1/campos
Catálogo de campos nativos de contato e empresa.
Onde é usada
tela de contatos (colunas e filtros), editor de contato e integrações.
Efeitos
nenhum — o catálogo é estático, embutido no binário.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
Respostas
código
significado
200
o catálogo.
401
sessão ausente ou inválida.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/campos' \
-H 'Authorization: Bearer SEU_TOKEN'
GET/v1/contatos
Lista uma página de contatos da conta.
Onde é usada
tela de alertas.
Efeitos
uma leitura.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
estagio
query
não
filtra por estágio (allowlist); valor desconhecido → 400.
q
query
não
trecho de nome+sobrenome; com @ busca o e-mail EXATO (índice cego); com 8+ dígitos busca o telefone EXATO (forma canônica)
pais
query
não
ISO-2; outro formato → 400
estado
query
não
igualdade sem caixa
cidade
query
não
igualdade sem caixa
empresa_id
query
não
id público da empresa
cargo
query
não
trecho, sem caixa
marcador
query
não
um marcador
dono_id
query
não
responsável
fonte
query
não
fonte do lead, sem caixa
utm_source
query
não
UTM source da primeira captura
dispositivo
query
não
desktop|mobile|tablet|bot|desconhecido (último envio); outro valor → 400
so
query
não
sistema do último envio, sem caixa
navegador
query
não
navegador do último envio, sem caixa
ip_pais
query
não
ISO-2 do país pelo IP do último envio; outro formato → 400
email_status
query
não
ok|suspeito|dominio_inexistente|descartavel|desconhecido; outro valor → 400
criado_de
query
não
AAAA-MM-DD ou RFC 3339 (inclusivo)
criado_ate
query
não
AAAA-MM-DD (inclui o dia) ou RFC 3339
limite
query
não
máximo de itens por página (inteiro positivo).
cursor
query
não
cursor opaco devolvido em `proximo`; adulterado → 400.
Respostas
código
significado
200
a página de contatos e o cursor seguinte.
400
corpo malformado, campo desconhecido ou query inválida.
401
sessão ausente ou inválida.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/contatos' \
-H 'Authorization: Bearer SEU_TOKEN'
POST/v1/contatos
Cria um contato; cifra a PII antes de gravar.
Onde é usada
tela de alertas.
Efeitos
uma escrita.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
Respostas
código
significado
201
o contato criado.
400
corpo malformado, campo desconhecido ou query inválida.
401
sessão ausente ou inválida.
409
já existe contato com aquele identificador.
422
corpo bem formado, mas o conteúdo não passa na regra de negócio.
Apaga um contato (soft delete, reversível pelo painel master).
Carimba apagado_em/por/motivo e registra contato_apagado na timeline. Nada é destruído: a PII fica, o contato some das leituras do cliente e o painel master restaura. A anonimização irreversível NÃO acontece aqui — só por pedido de exclusão aprovado por um admin da conta (/v1/pedidos-exclusao).
Onde é usada
tela de alertas.
Efeitos
uma escrita.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
id
path
sim
id público do recurso.
Respostas
código
significado
204
apagado (soft delete).
400
corpo malformado, campo desconhecido ou query inválida.
401
sessão ausente ou inválida.
404
recurso inexistente, de outra conta, ou sem acesso à ferramenta.
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
id
path
sim
id público do recurso.
Respostas
código
significado
200
o contato.
401
sessão ausente ou inválida.
404
recurso inexistente, de outra conta, ou sem acesso à ferramenta.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/contatos/id_AQUI' \
-H 'Authorization: Bearer SEU_TOKEN'
PATCH/v1/contatos/{id}
Atualiza um contato (parcial — campo ausente preserva).
Onde é usada
tela de alertas.
Efeitos
uma escrita. Mudar a configuração ACALMA o alerta: ele passa a observar outra coisa, e manter o estado faria a próxima avaliação comparar maçã com laranja — ele não avisaria pela condição NOVA, porque já estaria "disparado" pela antiga.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
id
path
sim
id público do recurso.
Respostas
código
significado
200
o contato atualizado.
400
corpo malformado, campo desconhecido ou query inválida.
401
sessão ausente ou inválida.
404
recurso inexistente, de outra conta, ou sem acesso à ferramenta.
422
corpo bem formado, mas o conteúdo não passa na regra de negócio.
Exporta os contatos da conta em CSV (registra a exportação na timeline).
Devolve CSV (não JSON), com Content-Disposition attachment. Registra a operação na timeline ANTES de o arquivo sair (LGPD art. 37); sem trilha disponível, responde 503. Teto de 10.000 linhas.
Onde é usada
botão "exportar" da lista de contatos.
Efeitos
uma leitura; decifra a PII; registra a exportação na timeline. # A PII é decifrada AQUI, e só para quem é dono O tenant vem da sessão verificada e a RLS já filtra a consulta. Este handler nunca vê contato de outra conta, e a decifragem acontece com a chave do processo — não há caminho em que o CSV carregue dado alheio. # Cada exportação vira uma ATIVIDADE, e isso não é opcional A LGPD (art. 37) exige registro das operações de tratamento, e exportar é tratamento: a partir dali o dado existe num arquivo que ninguém controla. Sem esse registro, "quem baixou a base e quando" não tem resposta — e é a primeira pergunta de todo incidente de vazamento. O registro é gravado ANTES do arquivo sair. Se a gravação falhar, a exportação não acontece: um download sem trilha é exatamente o que a trilha existe para impedir, e "o arquivo já foi" não se desfaz.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
limite
query
não
máximo de itens por página (inteiro positivo).
Respostas
código
significado
200
o CSV dos contatos.
400
corpo malformado, campo desconhecido ou query inválida.
curl -X GET 'https://api.crm.asender.net/v1/contatos/exportar.csv' \
-H 'Authorization: Bearer SEU_TOKEN'
Destinos
GET/v1/destinos
Lista os destinos (webhooks) da conta.
Onde é usada
tela de alertas.
Efeitos
uma leitura.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
Respostas
código
significado
200
os destinos.
401
sessão ausente ou inválida.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/destinos' \
-H 'Authorization: Bearer SEU_TOKEN'
POST/v1/destinos
Cria um destino (webhook); cifra o segredo antes.
Onde é usada
tela de alertas.
Efeitos
uma escrita.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
Respostas
código
significado
201
o destino criado.
400
corpo malformado, campo desconhecido ou query inválida.
401
sessão ausente ou inválida.
422
corpo bem formado, mas o conteúdo não passa na regra de negócio.
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
id
path
sim
id público do recurso.
Respostas
código
significado
204
removido.
401
sessão ausente ou inválida.
404
recurso inexistente, de outra conta, ou sem acesso à ferramenta.
Atualiza um destino; segredo ausente preserva o gravado.
Onde é usada
tela de alertas.
Efeitos
uma escrita. Mudar a configuração ACALMA o alerta: ele passa a observar outra coisa, e manter o estado faria a próxima avaliação comparar maçã com laranja — ele não avisaria pela condição NOVA, porque já estaria "disparado" pela antiga.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
id
path
sim
id público do recurso.
Respostas
código
significado
200
o destino atualizado.
400
corpo malformado, campo desconhecido ou query inválida.
401
sessão ausente ou inválida.
404
recurso inexistente, de outra conta, ou sem acesso à ferramenta.
422
corpo bem formado, mas o conteúdo não passa na regra de negócio.
Lista as tentativas de entrega de um destino (sem o payload).
Onde é usada
diagnóstico da tela de integrações.
Efeitos
uma leitura. O PAYLOAD não volta: ele carrega a PII do contato, e quem pergunta "por que não chegou" precisa do estado e do código — não do dado da pessoa repetido numa segunda tela.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
id
path
sim
id público do recurso.
limite
query
não
máximo de itens por página (inteiro positivo).
Respostas
código
significado
200
as entregas.
400
corpo malformado, campo desconhecido ou query inválida.
401
sessão ausente ou inválida.
404
recurso inexistente, de outra conta, ou sem acesso à ferramenta.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/destinos/id_AQUI/entregas' \
-H 'Authorization: Bearer SEU_TOKEN'
POST/v1/destinos/{id}/testar
Enfileira uma entrega de teste pela mesma fila das reais.
Onde é usada
botão "testar" da tela de integrações.
Efeitos
cria uma entrega pendente. # ENFILEIRA, e não entrega na hora A entrega passa pelo MESMO dreno das entregas de verdade — e portanto pelo mesmo guard do piso 18, pela mesma guarda de rede e pela mesma assinatura. Um caminho de teste que chamasse o webhook direto seria um segundo caminho de saída, e o segundo caminho é sempre o que esquece uma guarda. O operador vê o resultado em GET /entregas, que é a mesma tela onde ele vê as entregas reais — então "o teste funcionou" e "a integração funciona" são a mesma leitura, e não duas afirmações que podem divergir.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
curl -X GET 'https://api.crm.asender.net/v1/empresas/id_AQUI/pessoas' \
-H 'Authorization: Bearer SEU_TOKEN'
POST/v1/empresas/{id}/pessoassem schema na spec
POST /v1/empresas/{id}/pessoas {contato_id, papel}. Sempre entra como vínculo SECUNDÁRIO — tornar principal é a rota dedicada, que passa pela coluna `contatos.empresa_id` (a fonte da verdade, migration 031).
DELETE/v1/empresas/{id}/pessoas/{contato_id}sem schema na spec
DELETE /v1/empresas/{id}/pessoas/{contato_id} → 204. Era o vínculo PRINCIPAL: `contatos.empresa_id` desta pessoa também é zerado (o repo cuida disso na mesma transação — nunca duas fontes divergentes).
Lista as empresas da conta (também serve o seletor flutuante).
Onde é usada
tela de alertas.
Efeitos
uma leitura.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
q
query
não
trecho do nome ou do domínio
setor
query
não
porte
query
não
pais
query
não
limite
query
não
máximo de itens por página (inteiro positivo).
cursor
query
não
cursor opaco devolvido em `proximo`; adulterado → 400.
Respostas
código
significado
200
a página de empresas.
400
corpo malformado, campo desconhecido ou query inválida.
401
sessão ausente ou inválida.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/empresas' \
-H 'Authorization: Bearer SEU_TOKEN'
POST/v1/empresas
Cria uma empresa.
Onde é usada
tela de alertas.
Efeitos
uma escrita.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
Respostas
código
significado
201
a empresa criada.
400
corpo malformado, campo desconhecido ou query inválida.
401
sessão ausente ou inválida.
409
CNPJ (ou nome sem CNPJ) já em uso na conta.
422
corpo bem formado, mas o conteúdo não passa na regra de negócio.
Remove a empresa (lógico) e solta os contatos dela — os contatos ficam.
Onde é usada
tela de alertas.
Efeitos
uma escrita.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
id
path
sim
id público do recurso.
Respostas
código
significado
204
removida.
401
sessão ausente ou inválida.
404
recurso inexistente, de outra conta, ou sem acesso à ferramenta.
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
id
path
sim
id público do recurso.
Respostas
código
significado
200
a empresa.
401
sessão ausente ou inválida.
404
recurso inexistente, de outra conta, ou sem acesso à ferramenta.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/empresas/id_AQUI' \
-H 'Authorization: Bearer SEU_TOKEN'
PATCH/v1/empresas/{id}
Altera uma empresa (parcial).
Onde é usada
tela de alertas.
Efeitos
uma escrita. Mudar a configuração ACALMA o alerta: ele passa a observar outra coisa, e manter o estado faria a próxima avaliação comparar maçã com laranja — ele não avisaria pela condição NOVA, porque já estaria "disparado" pela antiga.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
id
path
sim
id público do recurso.
Respostas
código
significado
200
a empresa alterada.
400
corpo malformado, campo desconhecido ou query inválida.
401
sessão ausente ou inválida.
404
recurso inexistente, de outra conta, ou sem acesso à ferramenta.
409
CNPJ (ou nome sem CNPJ) já em uso na conta.
422
corpo bem formado, mas o conteúdo não passa na regra de negócio.
Contatos da empresa — mesma listagem e filtros de /v1/contatos.
Onde é usada
ficha da empresa.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
id
path
sim
id público do recurso.
limite
query
não
máximo de itens por página (inteiro positivo).
cursor
query
não
cursor opaco devolvido em `proximo`; adulterado → 400.
Respostas
código
significado
200
a página de contatos da empresa.
400
corpo malformado, campo desconhecido ou query inválida.
401
sessão ausente ou inválida.
404
recurso inexistente, de outra conta, ou sem acesso à ferramenta.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/empresas/id_AQUI/contatos' \
-H 'Authorization: Bearer SEU_TOKEN'
identidades
GET/v1/identidades/sugestoessem schema na spec
GET /v1/alertas.
Onde é usada
tela de alertas.
Efeitos
uma leitura.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/identidades/sugestoes' \
-H 'Authorization: Bearer SEU_TOKEN'
PUT/v1/identidades/sugestoes/{id}/decisaosem schema na spec
PUT /v1/identidades/sugestoes/{id}/decisao
Onde é usada
tela do atendente, nos botões "é a mesma pessoa" / "não é".
Efeitos
uma escrita. # ACEITAR NÃO FUNDE NADA Esta rota grava que um humano concordou que os dois contatos são a mesma pessoa. As duas fichas continuam existindo, separadas, com e-mail, telefone, timeline, consentimento e dono intactos. Fundir automaticamente é decisão do dono e está PARQUEADA (ADR-0061) — e é por isso que a resposta desta rota devolve a sugestão decidida, e não um contato.
Traduz uma identidade (e-mail, telefone…) no contato que a tem.
Não funde nada (ADR-0061): só diz se ALGUM contato já tem este endereço neste canal, e qual. O valor nunca é ecoado nem logado em claro além do necessário para calcular o índice cego.
Onde é usada
item 1 do plano — "API para resolver identidade → contato". Uso previsto: a inbox do atendimento (frente C, front do CRM) perguntando "esta pessoa já é alguém?" antes de abrir uma ficha nova à mão.
Efeitos
uma leitura. O VALOR nunca é ecoado de volta, e a resposta nunca inclui PII — só achou/contato_id. Quem quiser o e-mail/telefone pede GET /v1/contatos/{id} depois, pela rota que já decifra sob autorização.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
canal
query
sim
valor
query
sim
o e-mail ou telefone em claro, nunca persistido fora do índice cego.
Respostas
código
significado
200
achou (e o contato), ou achou:false.
401
sessão ausente ou inválida.
422
corpo bem formado, mas o conteúdo não passa na regra de negócio.
503
resolução de identidade indisponível (cifrador não configurado).
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/identidades/resolver' \
-H 'Authorization: Bearer SEU_TOKEN'
importacoes
GET/v1/importacoessem schema na spec
GET /v1/alertas.
Onde é usada
tela de alertas.
Efeitos
uma leitura.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/importacoes' \
-H 'Authorization: Bearer SEU_TOKEN'
POST/v1/importacoessem schema na spec
POST /v1/importacoes (multipart: campo "arquivo" + campo "config" com o JSON de `pedidoIniciar`) — o MESMO arquivo da prévia, reenviado.
Onde é usada
botão "confirmar importação" da tela de mapeamento.
Efeitos
uma escrita (o lote, status pendente); o processamento em si acontece depois, em segundo plano — a resposta não espera por ele.
GET/v1/importacoes/{id}/erros.csvsem schema na spec
GET /v1/importacoes/{id}/erros.csv.
Efeitos
uma leitura. # Mesma neutralização de fórmula da exportação de contatos O MOTIVO de um erro pode ecoar um valor da própria linha ("e-mail inválido: =cmd|'/c calc'!A1"): se um CSV hostil chegou como upload, o relatório de erro NÃO pode virar o vetor de saída da mesma injeção — por isso reaproveita exportacao.Escritor, o mesmo pacote que já neutraliza a exportação de contatos.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/importacoes/id_AQUI/erros.csv' \
-H 'Authorization: Bearer SEU_TOKEN'
GET/v1/importacoes/campossem schema na spec
GET /v1/campos → `{versao, grupos, campos}` do contrato `asender_docs/contratos/campos-contato.json`.
Onde é usada
tela de contatos (colunas e filtros), editor de contato e integrações.
Efeitos
nenhum — o catálogo é estático, embutido no binário.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/importacoes/campos' \
-H 'Authorization: Bearer SEU_TOKEN'
POST/v1/importacoes/previasem schema na spec
POST /v1/importacoes/previa (multipart, campo "arquivo").
Onde é usada
primeiro passo da tela de importação, assim que a pessoa solta o CSV.
Efeitos
nenhum — nada é persistido aqui (ver o doc-comment de Servico.Prevalidar para o porquê de o mesmo arquivo ser reenviado no passo de confirmação).
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
Respostas
código
significado
200
as integrações.
401
sessão ausente ou inválida.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/integracoes-de-conversao' \
-H 'Authorization: Bearer SEU_TOKEN'
POST/v1/integracoes-de-conversao
Cria uma integração de conversão (provedor meta; sem URL própria).
Onde é usada
tela de alertas.
Efeitos
uma escrita.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
Respostas
código
significado
201
a integração criada.
400
corpo malformado, campo desconhecido ou query inválida.
401
sessão ausente ou inválida.
422
corpo bem formado, mas o conteúdo não passa na regra de negócio.
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
id
path
sim
id público do recurso.
Respostas
código
significado
204
removida.
401
sessão ausente ou inválida.
404
recurso inexistente, de outra conta, ou sem acesso à ferramenta.
uma escrita. Mudar a configuração ACALMA o alerta: ele passa a observar outra coisa, e manter o estado faria a próxima avaliação comparar maçã com laranja — ele não avisaria pela condição NOVA, porque já estaria "disparado" pela antiga.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
id
path
sim
id público do recurso.
Respostas
código
significado
200
a integração atualizada.
400
corpo malformado, campo desconhecido ou query inválida.
401
sessão ausente ou inválida.
404
recurso inexistente, de outra conta, ou sem acesso à ferramenta.
422
corpo bem formado, mas o conteúdo não passa na regra de negócio.
Lista as tentativas de entrega de uma integração (sem o payload).
Onde é usada
diagnóstico da tela de integrações.
Efeitos
uma leitura. O PAYLOAD não volta: ele carrega a PII do contato, e quem pergunta "por que não chegou" precisa do estado e do código — não do dado da pessoa repetido numa segunda tela.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
id
path
sim
id público do recurso.
limite
query
não
máximo de itens por página (inteiro positivo).
Respostas
código
significado
200
as entregas.
400
corpo malformado, campo desconhecido ou query inválida.
401
sessão ausente ou inválida.
404
recurso inexistente, de outra conta, ou sem acesso à ferramenta.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/integracoes-de-conversao/id_AQUI/entregas' \
-H 'Authorization: Bearer SEU_TOKEN'
POST/v1/integracoes-de-conversao/{id}/testar
Enfileira uma entrega de teste da integração pela mesma fila das reais.
Onde é usada
botão "testar" da tela de integrações.
Efeitos
cria uma entrega pendente. # ENFILEIRA, e não entrega na hora A entrega passa pelo MESMO dreno das entregas de verdade — e portanto pelo mesmo guard do piso 18, pela mesma guarda de rede e pela mesma assinatura. Um caminho de teste que chamasse o webhook direto seria um segundo caminho de saída, e o segundo caminho é sempre o que esquece uma guarda. O operador vê o resultado em GET /entregas, que é a mesma tela onde ele vê as entregas reais — então "o teste funcionou" e "a integração funciona" são a mesma leitura, e não duas afirmações que podem divergir.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
Respostas
código
significado
200
as jornadas da conta.
401
sessão ausente ou inválida.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/jornadas' \
-H 'Authorization: Bearer SEU_TOKEN'
POST/v1/jornadas
Cria uma jornada — sempre INATIVA.
Criar e ativar são operações separadas; a jornada nasce desligada.
Onde é usada
painel, botão "criar jornada".
Efeitos
cria a linha. # Nasce desligada, sem exceção Criar e ativar são operações separadas porque ativar tem consequência no mundo: assim que a jornada liga, o próximo lead capturado entra nela e recebe mensagem. Um POST que já criasse ativa transformaria um erro de digitação numa campanha disparando — e não existe desfazer para e-mail enviado.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
Respostas
código
significado
201
a jornada criada.
400
corpo malformado, campo desconhecido ou query inválida.
401
sessão ausente ou inválida.
422
corpo bem formado, mas o conteúdo não passa na regra de negócio.
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
id
path
sim
id público do recurso.
Respostas
código
significado
200
a jornada.
401
sessão ausente ou inválida.
404
recurso inexistente, de outra conta, ou sem acesso à ferramenta.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/jornadas/id_AQUI' \
-H 'Authorization: Bearer SEU_TOKEN'
PUT/v1/jornadas/{id}
Reescreve o desenho de uma jornada DESLIGADA.
Salva a edição (do construtor visual ou do diálogo): substitui nome/gatilho/passos/layout. Só a jornada desligada pode ser editada — editar uma ativa mexeria nos passos por baixo das inscrições em andamento (409). NÃO liga; ativar tem rota própria que revalida.
Onde é usada
botão "salvar" da tela de edição visual.
Efeitos
reescreve a jornada. NÃO liga: a jornada continua desligada, e ativar tem rota própria que revalida. # Por que a jornada tem de estar DESLIGADA para ser editada Uma inscrição em andamento guarda o número do passo em que está. Trocar os passos por baixo dela faria o contato retomar num passo que virou outra coisa — a oferta no lugar da espera, ou um salto para um número que não existe mais. Editar exige desligar antes; religar revalida. O 409 diz isso ao operador em vez de deixá-lo salvar por cima de uma campanha correndo.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
id
path
sim
id público do recurso.
Respostas
código
significado
200
a jornada atualizada.
400
corpo malformado, campo desconhecido ou query inválida.
401
sessão ausente ou inválida.
404
recurso inexistente, de outra conta, ou sem acesso à ferramenta.
409
a jornada está ativa; desligue-a antes de editar.
422
corpo bem formado, mas o conteúdo não passa na regra de negócio.
Ligar revalida a jornada; desligar não. Ligada, ela passa a inscrever contatos.
Onde é usada
painel, interruptor da jornada.
Efeitos
muda o estado; ligada, a jornada passa a inscrever contatos. # Revalida ANTES de ligar A jornada foi validada na criação, mas pode ter sido editada depois — e uma jornada com buraco na numeração deixaria o contato preso no meio do caminho, sem erro em lugar nenhum. Validar de novo aqui custa nada e é o último ponto antes de a coisa começar a mandar mensagem. Desligar NÃO revalida: uma jornada quebrada tem de poder ser desligada, e exigir que ela esteja válida para parar seria prender o operador justamente no caso em que ele mais precisa do botão.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
id
path
sim
id público do recurso.
Respostas
código
significado
200
a jornada com o novo estado.
400
corpo malformado, campo desconhecido ou query inválida.
401
sessão ausente ou inválida.
404
recurso inexistente, de outra conta, ou sem acesso à ferramenta.
422
corpo bem formado, mas o conteúdo não passa na regra de negócio.
GET /v1/clientes/{id}. Outra conta = 404, como inexistente.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/painel' \
-H 'Authorization: Bearer SEU_TOKEN'
Painel
GET/v1/resumo
Resumo da ferramenta para o hub e a home (contrato comum de resumo).
Leads novos (com a janela anterior), contatos, oportunidades abertas (projetos em coluna não fechada) e o valor delas em centavos, tarefas vencidas e a série de leads por dia — os MESMOS números da Início do CRM. Conversas do chat ficam no resumo do atendimento. Tenant e usuário vêm da credencial verificada, nunca da query. Conta alheia → 404; membro sem acesso ao produto → 403.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
periodo
query
não
janela dos indicadores — os N últimos dias fechados em hoje (UTC). Padrão 30d.
Respostas
código
significado
200
o resumo da ferramenta `crm`.
400
corpo malformado, campo desconhecido ou query inválida.
401
sessão ausente ou inválida.
403
membro da conta sem acesso a esta ferramenta.
404
recurso inexistente, de outra conta, ou sem acesso à ferramenta.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/resumo' \
-H 'Authorization: Bearer SEU_TOKEN'
Pedidos de exclusão
GET/v1/pedidos-exclusao
Lista a fila de pedidos de exclusão (só admin da conta).
A decisão de autorização é do servidor (PDP, produto admin, nível >= 30). Quem não é admin recebe 404.
Onde é usada
tela de alertas.
Efeitos
uma leitura.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
status
query
não
cursor
query
não
limite
query
não
Respostas
código
significado
200
a página de pedidos.
401
sessão ausente ou inválida.
404
recurso inexistente, de outra conta, ou sem acesso à ferramenta.
422
corpo bem formado, mas o conteúdo não passa na regra de negócio.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/pedidos-exclusao' \
-H 'Authorization: Bearer SEU_TOKEN'
POST/v1/pedidos-exclusao
Registra o pedido de exclusão de um titular (task pendente; NÃO apaga nada).
Qualquer membro da conta registra. Cria a task, a auditoria e avisa os admins pela central de notificações.
Onde é usada
tela de alertas.
Efeitos
uma escrita.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
Respostas
código
significado
201
o pedido pendente.
400
corpo malformado, campo desconhecido ou query inválida.
401
sessão ausente ou inválida.
404
recurso inexistente, de outra conta, ou sem acesso à ferramenta.
409
já existe um pedido pendente para este contato.
422
corpo bem formado, mas o conteúdo não passa na regra de negócio.
Aprova o pedido e anonimiza o contato (só admin da conta; irreversível).
Único caminho HTTP até a anonimização. Grava timeline e auditoria na mesma transação.
Efeitos
irreversível sobre a PII; é o ÚNICO caminho HTTP até ela.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
id
path
sim
id público do recurso.
Respostas
código
significado
200
o pedido executado.
401
sessão ausente ou inválida.
404
recurso inexistente, de outra conta, ou sem acesso à ferramenta.
Recusa o pedido (só admin da conta; motivo obrigatório; nada é apagado).
O contato permanece intacto e a recusa fica na timeline e na auditoria.
Efeitos
nada é apagado; o contato recebe um registro na timeline.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
id
path
sim
id público do recurso.
Respostas
código
significado
200
o pedido recusado.
401
sessão ausente ou inválida.
404
recurso inexistente, de outra conta, ou sem acesso à ferramenta.
409
o pedido já foi decidido.
422
corpo bem formado, mas o conteúdo não passa na regra de negócio.
GET /v1/clientes/{id}. Outra conta = 404, como inexistente.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/projetos/id_AQUI' \
-H 'Authorization: Bearer SEU_TOKEN'
PATCH/v1/projetos/{id}sem schema na spec
PUT /v1/alertas/{id}.
Onde é usada
tela de alertas.
Efeitos
uma escrita. Mudar a configuração ACALMA o alerta: ele passa a observar outra coisa, e manter o estado faria a próxima avaliação comparar maçã com laranja — ele não avisaria pela condição NOVA, porque já estaria "disparado" pela antiga.
Atividade responde GET /v1/relatorios/atividade?de=&ate=.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/relatorios/atividade' \
-H 'Authorization: Bearer SEU_TOKEN'
GET/v1/relatorios/funilsem schema na spec
Funil responde GET /v1/relatorios/funil?de=&ate=.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/relatorios/funil' \
-H 'Authorization: Bearer SEU_TOKEN'
GET/v1/relatorios/origemsem schema na spec
Origem responde GET /v1/relatorios/origem?de=&ate=.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/relatorios/origem' \
-H 'Authorization: Bearer SEU_TOKEN'
GET/v1/relatorios/projetossem schema na spec
Projetos responde GET /v1/relatorios/projetos?de=&ate=.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/relatorios/projetos' \
-H 'Authorization: Bearer SEU_TOKEN'
GET/v1/relatorios/tarefassem schema na spec
Tarefas responde GET /v1/relatorios/tarefas?de=&ate=.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/relatorios/tarefas' \
-H 'Authorization: Bearer SEU_TOKEN'
GET/v1/relatorios/trafegosem schema na spec
duas leituras INDEPENDENTES — uma consulta local (`LeadsPorOrigemUTM`) e uma chamada HTTP ao Pages (`pages.Resumo`, reaproveitando `top_origens`, já calculado com o mesmo critério que a Início usa) — casadas em memória pela string de `utm_source`. NUNCA um JOIN de banco: os dois dados vivem em bancos de serviços diferentes (piso 6/10), e cruzá-los aqui, na borda, é o único jeito de fazer isso sem um serviço ler o schema do outro.
Onde é usada
tela de Relatórios do CRM.
Efeitos
uma consulta local; uma chamada HTTP ao Pages. Pages fora do ar NÃO derruba a rota: ela responde 200 com disponivel: false e as linhas só com o lado do CRM (sessões ficam de fora, e taxa_de_conversao sai vazia em todas) — o operador ainda vê "quantos leads por origem", só sem cruzar com sessão.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/relatorios/trafego' \
-H 'Authorization: Bearer SEU_TOKEN'
Segmentos
GET/v1/segmentos
Lista os segmentos vivos da conta.
Onde é usada
tela de alertas.
Efeitos
uma leitura.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
Respostas
código
significado
200
os segmentos.
401
sessão ausente ou inválida.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/segmentos' \
-H 'Authorization: Bearer SEU_TOKEN'
POST/v1/segmentos
Cria um segmento; devolve o alcance atual.
Onde é usada
tela de alertas.
Efeitos
uma escrita.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
Respostas
código
significado
201
o segmento criado e seu alcance.
400
corpo malformado, campo desconhecido ou query inválida.
401
sessão ausente ou inválida.
409
já existe um segmento com esse nome.
422
corpo bem formado, mas o conteúdo não passa na regra de negócio.
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
id
path
sim
id público do recurso.
Respostas
código
significado
204
removido.
401
sessão ausente ou inválida.
404
recurso inexistente, de outra conta, ou sem acesso à ferramenta.
Lê um segmento e quantas pessoas ele alcança agora.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
id
path
sim
id público do recurso.
Respostas
código
significado
200
o segmento e seu alcance.
401
sessão ausente ou inválida.
404
recurso inexistente, de outra conta, ou sem acesso à ferramenta.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/segmentos/id_AQUI' \
-H 'Authorization: Bearer SEU_TOKEN'
PUT/v1/segmentos/{id}
Substitui nome, conjunção e critérios de um segmento.
PUT (não PATCH) — um segmento é sua lista de critérios; manda-se o conjunto inteiro.
Onde é usada
tela de alertas.
Efeitos
uma escrita. Mudar a configuração ACALMA o alerta: ele passa a observar outra coisa, e manter o estado faria a próxima avaliação comparar maçã com laranja — ele não avisaria pela condição NOVA, porque já estaria "disparado" pela antiga.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
id
path
sim
id público do recurso.
Respostas
código
significado
200
o segmento atualizado e seu alcance.
400
corpo malformado, campo desconhecido ou query inválida.
401
sessão ausente ou inválida.
404
recurso inexistente, de outra conta, ou sem acesso à ferramenta.
409
já existe um segmento com esse nome.
422
corpo bem formado, mas o conteúdo não passa na regra de negócio.
Não grava nada; responde quantas pessoas os critérios alcançam agora.
Onde é usada
enquanto o usuário monta os critérios na tela.
Efeitos
uma consulta; NÃO grava nada. Existe para que a pergunta "isto alcança quem?" seja respondida ANTES de salvar. Sem ela, o caminho para descobrir o alcance é criar o segmento — e a tela enche de segmentos descartados chamados "teste 3".
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
Respostas
código
significado
200
o alcance calculado.
400
corpo malformado, campo desconhecido ou query inválida.
401
sessão ausente ou inválida.
422
corpo bem formado, mas o conteúdo não passa na regra de negócio.
GET /v1/clientes/{id}. Outra conta = 404, como inexistente.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/tarefas/id_AQUI' \
-H 'Authorization: Bearer SEU_TOKEN'
PATCH/v1/tarefas/{id}sem schema na spec
PUT /v1/alertas/{id}.
Onde é usada
tela de alertas.
Efeitos
uma escrita. Mudar a configuração ACALMA o alerta: ele passa a observar outra coisa, e manter o estado faria a próxima avaliação comparar maçã com laranja — ele não avisaria pela condição NOVA, porque já estaria "disparado" pela antiga.
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
id
path
sim
id público do recurso.
limite
query
não
máximo de itens por página (inteiro positivo).
cursor
query
não
cursor opaco devolvido em `proximo`; adulterado → 400.
Respostas
código
significado
200
a página de atividades, o cursor seguinte e o total.
400
corpo malformado, campo desconhecido ou query inválida.
401
sessão ausente ou inválida.
404
recurso inexistente, de outra conta, ou sem acesso à ferramenta.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/contatos/id_AQUI/atividades' \
-H 'Authorization: Bearer SEU_TOKEN'
POST/v1/contatos/{id}/atividades
Anexa uma nota à timeline do contato.
Só NOTA — os outros tipos são consequência do que o sistema fez. O autor vem da sessão.
Onde é usada
tela de alertas.
Efeitos
uma escrita.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
id
path
sim
id público do recurso.
Respostas
código
significado
201
a nota criada.
400
corpo malformado, campo desconhecido ou query inválida.
401
sessão ausente ou inválida.
404
recurso inexistente, de outra conta, ou sem acesso à ferramenta.
422
corpo bem formado, mas o conteúdo não passa na regra de negócio.
Lista as conversas do atendimento ligadas a este contato.
Projeção LOCAL (crm.contato_conversas, migration 056), alimentada pelo consumo de atendimento.conversa.criada/.identificada — nunca uma chamada síncrona ao asender_atendimento_api (piso 10). Por isso o item é RASO: só conversa_id (opaco, do atendimento), canal e vinculado_em — sem estado nem prévia de mensagem.
Onde é usada
tela de alertas.
Efeitos
uma leitura.
Parâmetros
nome
em
obrigatório
descrição
X-Asender-Tenant
header
não
Conta em que a requisição opera — id OU slug. É uma preferência conferida contra as contas da sessão (tenant fora da lista → 404). Ausente, cai na primeira conta da sessão.
id
path
sim
id público do recurso.
limite
query
não
máximo de itens por página (inteiro positivo).
Respostas
código
significado
200
as conversas, mais recente primeiro.
401
sessão ausente ou inválida.
404
recurso inexistente, de outra conta, ou sem acesso à ferramenta.
Exemplo
curl -X GET 'https://api.crm.asender.net/v1/contatos/id_AQUI/conversas' \
-H 'Authorization: Bearer SEU_TOKEN'