GET/account
Validar token e consultar ambienteRetorna id, nome, fuso, permissões e ID do token. Nenhum workspace_id precisa ser informado.
Qualquer token válidoCadastre contatos, crie negociações e atualize campos do Flexa Go com segurança. Integre n8n, páginas de lançamento e ferramentas de tráfego usando um token exclusivo de cada ambiente.
Authorization: Bearer fg_api_SEU_TOKEN
Content-Type: application/json
Idempotency-Key: evento-unico-123Para a gestora de tráfego, gere um token no ambiente iPhone e outro no ambiente Xiaomi. A chave determina a empresa: não há parâmetro para escolher outro workspace.
Somente proprietários e administradores gerenciam tokens. Um token perde acesso ao expirar, ser revogado ou quando seu emissor perde a permissão de administrador. O MCP usa chaves próprias e continua sendo uma integração distinta.
| Permissão | Uso |
|---|---|
contacts:read | Consultar contatos e verificar telefones duplicados |
contacts:write | Cadastrar e atualizar contatos |
leads:read | Consultar negociações e sua origem |
leads:write | Cadastrar negociações, criando seu contato se necessário, e atualizar negociações |
fields:read | Consultar definições e IDs dos campos |
fields:write | Criar definições de campos |
pipelines:read | Consultar IDs de funis e etapas |
contacts:merge | Unir duplicados; também exige contacts:write |
Para um relatório de tráfego, use permissões de leitura. Para captura de formulário, adicione leads:write. Permissões de união ou criação de campos devem ser concedidas apenas quando a integração precisar delas.
Base de produção: https://crm.flexago.com.br/api/v1
GET /account.GET /pipelines e copie o ID do funil e da etapa desejados.POST /leads com nome e telefone. Sem funil explícito, a API prefere Vendas e sua primeira etapa aberta.curl --request POST 'https://crm.flexago.com.br/api/v1/leads' \
--header 'Authorization: Bearer SEU_TOKEN' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: inscricao-123' \
--data '{
"name": "Maria Exemplo",
"phone": "+5541999990000",
"title": "Inscrição · lançamento",
"value_cents": 0,
"attribution": {
"source": "meta",
"medium": "paid_social",
"utm_source": "instagram",
"utm_medium": "cpc",
"utm_campaign": "lancamento",
"form_id": "form-inscricao",
"external_id": "inscricao-123"
}
}'A primeira criação retorna 201. Quando reutiliza uma negociação aberta do mesmo contato e funil, retorna 200 com deduplicated: true. O contato existe no CRM mesmo que nunca tenha enviado mensagem.
{
"data": {
"lead": {
"id": "UUID_DO_LEAD",
"contact_id": "UUID_DO_CONTATO",
"title": "Inscrição · lançamento",
"value_cents": 0
},
"created": true,
"contact_created": true,
"deduplicated": false
},
"request_id": "UUID_DA_REQUISICAO"
}Todos os endpoints exigem Bearer token. As operações POST e PATCH exigem Idempotency-Key, exceto a verificação de duplicados.
/accountRetorna id, nome, fuso, permissões e ID do token. Nenhum workspace_id precisa ser informado.
Qualquer token válido/pipelinesCada funil retorna suas etapas com id, nome, posição e tipo: open, won ou lost.
Permissão: pipelines:read/custom-fieldsFiltre por ?entity=contact ou ?entity=lead. Use o id retornado para preencher fields.
Permissão: fields:read/custom-fieldsCria um campo e retorna seu UUID estável. Mesmo nome/entidade já existente retorna 409.
Permissão: fields:write{
"type": "object",
"additionalProperties": false,
"required": [
"name",
"entity",
"type"
],
"properties": {
"name": {
"type": "string",
"maxLength": 100
},
"entity": {
"type": "string",
"enum": [
"contact",
"lead"
]
},
"type": {
"type": "string",
"enum": [
"text",
"number",
"boolean",
"date",
"select"
]
},
"options": {
"type": "array",
"maxItems": 100,
"items": {
"type": "string"
},
"description": "Obrigatório e não vazio para select; deve ficar vazio nos outros tipos."
}
}
}/contactsLista paginada. Filtros: phone, source, created_since, limit e cursor.
Permissão: contacts:read/contacts/{id}Retorna cadastro, fields, preferências e atribuição. ID de outro ambiente retorna 404.
Permissão: contacts:read/contactsname e phone obrigatórios. Reutiliza telefone equivalente. Preserva nome/e-mail existentes; fields e atribuição recebidos são mesclados.
Permissão: contacts:write{
"type": "object",
"additionalProperties": false,
"properties": {
"name": {
"type": "string",
"maxLength": 150
},
"phone": {
"type": "string",
"description": "Telefone brasileiro completo com DDD ou internacional com +país. Ex.: +5541999990000."
},
"email": {
"type": "string",
"format": "email",
"nullable": true
},
"fields": {
"type": "object",
"description": "Objeto UUID do campo → valor. null limpa apenas o valor indicado. Outros campos são preservados.",
"additionalProperties": {
"oneOf": [
{
"type": "string",
"nullable": true
},
{
"type": "number"
},
{
"type": "boolean"
}
]
}
},
"attribution": {
"type": "object",
"additionalProperties": false,
"properties": {
"source": {
"type": "string",
"maxLength": 1000
},
"medium": {
"type": "string",
"maxLength": 1000
},
"campaign": {
"type": "string",
"maxLength": 1000
},
"utm_source": {
"type": "string",
"maxLength": 1000
},
"utm_medium": {
"type": "string",
"maxLength": 1000
},
"utm_campaign": {
"type": "string",
"maxLength": 1000
},
"utm_content": {
"type": "string",
"maxLength": 1000
},
"utm_term": {
"type": "string",
"maxLength": 1000
},
"landing_page": {
"type": "string",
"maxLength": 1000
},
"referrer": {
"type": "string",
"maxLength": 1000
},
"external_id": {
"type": "string",
"maxLength": 1000
},
"form_id": {
"type": "string",
"maxLength": 1000
},
"ad_id": {
"type": "string",
"maxLength": 1000
},
"adset_id": {
"type": "string",
"maxLength": 1000
},
"campaign_id": {
"type": "string",
"maxLength": 1000
},
"fbclid": {
"type": "string",
"maxLength": 1000
},
"gclid": {
"type": "string",
"maxLength": 1000
}
}
},
"stop_sends": {
"type": "boolean"
}
},
"required": [
"name",
"phone"
]
}/contacts/{id}Altera apenas propriedades informadas. Para trocar telefone, exige que o novo telefone não pertença a outro contato.
Permissão: contacts:write{
"type": "object",
"additionalProperties": false,
"properties": {
"name": {
"type": "string",
"maxLength": 150
},
"phone": {
"type": "string",
"description": "Telefone brasileiro completo com DDD ou internacional com +país. Ex.: +5541999990000."
},
"email": {
"type": "string",
"format": "email",
"nullable": true
},
"fields": {
"type": "object",
"description": "Objeto UUID do campo → valor. null limpa apenas o valor indicado. Outros campos são preservados.",
"additionalProperties": {
"oneOf": [
{
"type": "string",
"nullable": true
},
{
"type": "number"
},
{
"type": "boolean"
}
]
}
},
"attribution": {
"type": "object",
"additionalProperties": false,
"properties": {
"source": {
"type": "string",
"maxLength": 1000
},
"medium": {
"type": "string",
"maxLength": 1000
},
"campaign": {
"type": "string",
"maxLength": 1000
},
"utm_source": {
"type": "string",
"maxLength": 1000
},
"utm_medium": {
"type": "string",
"maxLength": 1000
},
"utm_campaign": {
"type": "string",
"maxLength": 1000
},
"utm_content": {
"type": "string",
"maxLength": 1000
},
"utm_term": {
"type": "string",
"maxLength": 1000
},
"landing_page": {
"type": "string",
"maxLength": 1000
},
"referrer": {
"type": "string",
"maxLength": 1000
},
"external_id": {
"type": "string",
"maxLength": 1000
},
"form_id": {
"type": "string",
"maxLength": 1000
},
"ad_id": {
"type": "string",
"maxLength": 1000
},
"adset_id": {
"type": "string",
"maxLength": 1000
},
"campaign_id": {
"type": "string",
"maxLength": 1000
},
"fbclid": {
"type": "string",
"maxLength": 1000
},
"gclid": {
"type": "string",
"maxLength": 1000
}
}
},
"stop_sends": {
"type": "boolean"
}
}
}/contacts/deduplicateConsulta sem modificar dados. Retorna matches, count e action: create, reuse ou review. Não exige Idempotency-Key.
Permissão: contacts:read{
"type": "object",
"additionalProperties": false,
"required": [
"phone"
],
"properties": {
"phone": {
"type": "string",
"description": "Telefone brasileiro completo com DDD ou internacional com +país. Ex.: +5541999990000."
}
}
}/contacts/mergeUnião explícita, somente para telefones válidos equivalentes. Preserva auditoria e recusa vínculos ou agendamentos conflitantes. Exige também contacts:write.
Permissão: contacts:merge{
"type": "object",
"additionalProperties": false,
"required": [
"keep_id",
"source_id"
],
"properties": {
"keep_id": {
"type": "string",
"format": "uuid"
},
"source_id": {
"type": "string",
"format": "uuid"
}
}
}/leadsFiltros: contact_id, pipeline_id, stage_id, source, created_since, limit e cursor.
Permissão: leads:read/leads/{id}Retorna id, contact_id, pipeline_id, stage_id, título, valor, fields e atribuição.
Permissão: leads:read/leadsEnvie contact_id existente OU name/phone e e-mail opcional. Cria contato se necessário; reutiliza a negociação aberta mais recente do mesmo contato e funil.
Permissão: leads:write{
"type": "object",
"additionalProperties": false,
"properties": {
"contact_id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string",
"maxLength": 150
},
"phone": {
"type": "string",
"description": "Telefone brasileiro completo com DDD ou internacional com +país. Ex.: +5541999990000."
},
"email": {
"type": "string",
"format": "email",
"nullable": true
},
"contact_fields": {
"type": "object",
"description": "Objeto UUID do campo → valor. null limpa apenas o valor indicado. Outros campos são preservados.",
"additionalProperties": {
"oneOf": [
{
"type": "string",
"nullable": true
},
{
"type": "number"
},
{
"type": "boolean"
}
]
}
},
"title": {
"type": "string",
"maxLength": 150
},
"pipeline_id": {
"type": "string",
"format": "uuid"
},
"stage_id": {
"type": "string",
"format": "uuid"
},
"value_cents": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"fields": {
"type": "object",
"description": "Objeto UUID do campo → valor. null limpa apenas o valor indicado. Outros campos são preservados.",
"additionalProperties": {
"oneOf": [
{
"type": "string",
"nullable": true
},
{
"type": "number"
},
{
"type": "boolean"
}
]
}
},
"attribution": {
"type": "object",
"additionalProperties": false,
"properties": {
"source": {
"type": "string",
"maxLength": 1000
},
"medium": {
"type": "string",
"maxLength": 1000
},
"campaign": {
"type": "string",
"maxLength": 1000
},
"utm_source": {
"type": "string",
"maxLength": 1000
},
"utm_medium": {
"type": "string",
"maxLength": 1000
},
"utm_campaign": {
"type": "string",
"maxLength": 1000
},
"utm_content": {
"type": "string",
"maxLength": 1000
},
"utm_term": {
"type": "string",
"maxLength": 1000
},
"landing_page": {
"type": "string",
"maxLength": 1000
},
"referrer": {
"type": "string",
"maxLength": 1000
},
"external_id": {
"type": "string",
"maxLength": 1000
},
"form_id": {
"type": "string",
"maxLength": 1000
},
"ad_id": {
"type": "string",
"maxLength": 1000
},
"adset_id": {
"type": "string",
"maxLength": 1000
},
"campaign_id": {
"type": "string",
"maxLength": 1000
},
"fbclid": {
"type": "string",
"maxLength": 1000
},
"gclid": {
"type": "string",
"maxLength": 1000
}
}
}
},
"oneOf": [
{
"required": [
"contact_id"
],
"not": {
"anyOf": [
{
"required": [
"name"
]
},
{
"required": [
"phone"
]
},
{
"required": [
"email"
]
}
]
}
},
{
"required": [
"name",
"phone"
],
"not": {
"required": [
"contact_id"
]
}
}
]
}/leads/{id}Permite title, pipeline_id, stage_id, value_cents, fields e attribution. Para mover de funil, envie uma etapa pertencente ao destino ou será usada sua primeira etapa aberta.
Permissão: leads:write{
"type": "object",
"additionalProperties": false,
"properties": {
"title": {
"type": "string",
"maxLength": 150
},
"pipeline_id": {
"type": "string",
"format": "uuid"
},
"stage_id": {
"type": "string",
"format": "uuid"
},
"value_cents": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"fields": {
"type": "object",
"description": "Objeto UUID do campo → valor. null limpa apenas o valor indicado. Outros campos são preservados.",
"additionalProperties": {
"oneOf": [
{
"type": "string",
"nullable": true
},
{
"type": "number"
},
{
"type": "boolean"
}
]
}
},
"attribution": {
"type": "object",
"additionalProperties": false,
"properties": {
"source": {
"type": "string",
"maxLength": 1000
},
"medium": {
"type": "string",
"maxLength": 1000
},
"campaign": {
"type": "string",
"maxLength": 1000
},
"utm_source": {
"type": "string",
"maxLength": 1000
},
"utm_medium": {
"type": "string",
"maxLength": 1000
},
"utm_campaign": {
"type": "string",
"maxLength": 1000
},
"utm_content": {
"type": "string",
"maxLength": 1000
},
"utm_term": {
"type": "string",
"maxLength": 1000
},
"landing_page": {
"type": "string",
"maxLength": 1000
},
"referrer": {
"type": "string",
"maxLength": 1000
},
"external_id": {
"type": "string",
"maxLength": 1000
},
"form_id": {
"type": "string",
"maxLength": 1000
},
"ad_id": {
"type": "string",
"maxLength": 1000
},
"adset_id": {
"type": "string",
"maxLength": 1000
},
"campaign_id": {
"type": "string",
"maxLength": 1000
},
"fbclid": {
"type": "string",
"maxLength": 1000
},
"gclid": {
"type": "string",
"maxLength": 1000
}
}
}
}
}Os campos existentes já têm UUIDs. Consulte GET /custom-fields ou copie o ID em Configurações → API → IDs dos campos. O ID de um campo de contato não pode ser usado numa negociação, nem em outro ambiente.
{
"fields": {
"11111111-1111-4111-8111-111111111111": "Instagram",
"22222222-2222-4222-8222-222222222222": true
}
}Use JSON nativo: número sem aspas, booleano true/false, data AAAA-MM-DD e texto nas opções já cadastradas para um campo select. Enviar null limpa o valor daquele ID. Outros valores são preservados.
Na criação de lead, fields preenche a negociação e contact_fields preenche o contato. O valor principal da negociação usa value_cents: R$ 150,00 = 15000. Consulte o esquema antes de preencher um campo de valor já existente.
A identidade é o telefone normalizado dentro do ambiente. Telefones brasileiros precisam estar completos. A comparação reconhece aliases históricos com e sem o nono dígito; novos celulares devem conter o nono dígito correto.
POST /contacts/deduplicate informa se deve criar, reutilizar ou revisar.POST /contacts cria ou reutiliza o contato automaticamente.POST /leads reutiliza a negociação aberta mais recente do contato no funil selecionado. Se todas estiverem encerradas, cria uma nova.Nome e e-mail nunca são usados sozinhos para unir pessoas. Cadastros antigos com múltiplos telefones equivalentes geram conflito para revisão. A união por /contacts/merge é explícita, auditada e pode ser recusada se houver públicos, trabalhos ou agendamentos conflitantes.
Repetir um POST não move uma negociação aberta de etapa nem sobrescreve seu título, valor, nome ou e-mail. Use PATCH quando quiser alterar esses dados explicitamente. Campos e atribuição enviados no POST são mesclados.
Envie attribution na criação ou atualização. A API preserva first_touch e atualiza last_touch, com horário de captura. A origem é declarada pela integração; a API não prova sozinha que uma visita veio da Meta.
{
"attribution": {
"source": "meta",
"medium": "paid_social",
"utm_source": "instagram",
"utm_medium": "cpc",
"utm_campaign": "lancamento",
"form_id": "form-inscricao",
"external_id": "inscricao-123"
}
}Chaves aceitas: source, medium, campaign, utm_source, utm_medium, utm_campaign, utm_content, utm_term, landing_page, referrer, external_id, form_id, ad_id, adset_id, campaign_id, fbclid, gclid.
Para analisar entradas pagas: GET /leads?source=meta&created_since=2026-10-01T00%3A00%3A00-03%3A00. O filtro source considera a última origem registrada; a primeira permanece disponível em cada cadastro. Usar essas UTMs não envia eventos para o pixel nem para a Conversions API da Meta.
Authorization, valor Bearer SEU_TOKEN.https://crm.flexago.com.br/api/v1/leads e Authentication: Generic Credential Type → Header Auth.Idempotency-Key com o ID estável da inscrição, por exemplo form-{{$json.submission_id}}.O arquivo OpenAPI descreve os contratos e a coleção Postman contém os endpoints. Nenhum download inclui credenciais.
O visitante envia nome e telefone ao seu servidor ou a um webhook do n8n. Esse servidor salva o lead na API e, após o sucesso, devolve o link do grupo para a página redirecionar.
// Execute no servidor. FLEXAGO_TOKEN deve ser uma variável secreta.
const response = await fetch('https://crm.flexago.com.br/api/v1/leads', {
method: 'POST',
headers: {
Authorization: 'Bearer ' + process.env.FLEXAGO_TOKEN,
'Content-Type': 'application/json',
'Idempotency-Key': 'form-' + submission.id
},
body: JSON.stringify({
name: submission.name,
phone: submission.phone,
attribution: { source: 'organico', form_id: 'lancamento' }
})
});
const result = await response.json();
if (!response.ok) throw new Error(result.error.message);
// Somente após salvar com sucesso, redirecione para o link do grupo:
// return Response.redirect(process.env.WHATSAPP_GROUP_URL, 303);O token deve ficar em uma variável secreta no servidor ou no cofre do n8n. Não coloque o token no HTML, JavaScript público, URL do formulário ou link do grupo. Proteja o formulário público contra spam e valide seus campos.
O cadastro não depende de mensagem recebida e não cria uma conversa artificial. Entrar no grupo ou preencher o formulário não abre a janela de 24 horas de uma conversa individual. Para contato futuro, registre a autorização adequada e use os canais, regras e templates exigidos pelo provedor. Esta API não executa disparos.
Listas usam limit de 1 a 100 (padrão 50). Passe o pagination.next_cursor na próxima requisição e preserve os mesmos filtros. has_more: false indica o fim. Novos registros inseridos durante a leitura podem exigir uma nova consulta desde a primeira página.
{
"data": [],
"pagination": {
"limit": 50,
"has_more": false,
"next_cursor": null
},
"request_id": "UUID_DA_REQUISICAO"
}Idempotency-Key dura 24 horas por token. A mesma chave e o mesmo conteúdo retornam o resultado anterior, inclusive após timeout; o cabeçalho Idempotent-Replayed: true identifica a repetição. Outra combinação de dados com a mesma chave retorna 409. Depois de 24 horas, o upsert por telefone/negociação ainda ajuda a evitar duplicidade, mas não substitui uma chave única por evento.
| HTTP | Significado / ação |
|---|---|
| 200 / 201 | Sucesso / criação |
| 400 | Formato inválido, UUID ou propriedade desconhecida |
| 401 | Token inválido, expirado ou revogado |
| 403 | Permissão insuficiente ou chamada de navegador de outra origem |
| 404 | Registro ausente ou pertencente a outro ambiente |
| 405 | Método não permitido |
| 409 | Duplicidade, conflito de atualização, união insegura ou chave usada com dados diferentes |
| 413 / 415 | Corpo excede 32 KB / envie application/json |
| 422 | Campo, opção, telefone ou relação inválidos |
| 429 | Aguarde o Retry-After: 60 segundos |
| 503 | Serviço temporariamente indisponível; preserve a chave de idempotência |
O limite é de 60 requisições por minuto por token em cada ponto da rede Cloudflare. É uma proteção de requisições HTTP, distinta dos limites de envio do WhatsApp. Máximo: 32 KB por corpo e 40 campos por entidade. Sempre guarde o request_id de erros para suporte.
A API v1 cobre cadastro e consulta de contatos e negociações, atualização de dados, consulta/criação de campos personalizados, IDs de funis e etapas, verificação/união de duplicados, atribuição de campanhas e tokens por ambiente.
Conversas, mídias, envio de mensagens, templates, flows, disparos, agenda clínica e permissões de usuários continuam nos fluxos próprios do CRM. Não são endpoints públicos desta versão. Não há DELETE público nem webhook de saída nesta API.
Os contratos foram organizados com referência à captura de leads do Kommo e aos campos por ID. O formato e os IDs do Flexa Go são próprios; não são compatíveis automaticamente com a API do Kommo.