O BIKY.ai se conecta ao CRM ou DMS de cada marca ou distribuidor. Ele entrega cada lead que chega por qualquer canal, informa o andamento (em tempo real ou ao fechar a conversa, conforme o CRM) e recebe as alterações feitas pelo consultor. Tudo gira em torno do SalesCard, o registro do BIKY.ai que guarda o lead, sua etapa no Funnel e o id que o CRM atribui a ele. Este protocolo reúne o que aprendemos em mais de quinze integrações pela América Latina.
Como nos conectamos
Existem três caminhos, e um CRM pode combiná-los: seu CRM nos notifica por webhook, o BIKY.ai consulta a API dele e as atualizações de andamento saem por essa mesma API. Cada id que o CRM retorna fica salvo no SalesCard ou no contato, para que o próximo evento atualize o registro em vez de duplicá-lo.
Quem define a autenticação é o seu CRM: OAuth2 client_credentials com um connected app, OAuth2 autorizado por um usuário administrador, um token de curta duração, uma API key ou Basic Auth. Os webhooks de entrada usam uma URL exclusiva com um token por fluxo. Você também pode ativar a criptografia do corpo, e o Flows verifica a assinatura HMAC das plataformas que a enviam. Formulários web e fornecedores de leads também entram por esse caminho. Os formulários da Meta chegam como mais um canal.
Há três variantes. Algumas integrações rodam em uma plataforma de integração (iPaaS), com conectores OAuth2 autorizados por um dos usuários administradores do cliente. Quando o CRM não tem API, ou a API não cobre algum processo, um robô (RPA) opera o portal web dele com usuários designados pelo cliente. E, se o seu sistema não estiver neste documento, o BIKY.ai pode enviar cada alteração do SalesCard para o webhook que você nos indicar.
Também funciona no sentido inverso: seu CRM pode chamar a API do BIKY.ai com a chave da sua conta. Assim, ele pode criar ou buscar contatos (por telefone, e-mail ou id) e criar, consultar ou mover SalesCards entre as etapas de um Funnel. Há exemplos nas coleções do Postman da Keybe. Os campos, valores permitidos e exemplos dessa API estão na seção Campos e estrutura da API.
Integrações com CRM
Tudo trafega por HTTPS. Três coisas mudam de um CRM para outro: quem inicia a chamada, como ela se autentica e qual identificador evita duplicados. Estas são as integrações com mais tempo de operação.
Sale U
- Conexão e autenticação: entrada por webhook para uma URL exclusiva com token. Saída por API REST com API key, além de um secret e um timestamp no corpo.
- Quais dados trafegam: na entrada, o lead atribuído: nome, telefone, e-mail, concessionária, modelo e id do prospect. Na saída, cada atividade: status, agendamento, nota de acompanhamento, bloqueio ou liberação, temperatura e fechamento.
- Direção e frequência: tempo real. Conforme a concessionária, nos dois sentidos ou apenas do BIKY.ai para o Sale U. Cada concessionária precisa da autorização do fornecedor.
- Como evitamos duplicados: o contato é buscado pelo telefone e o SalesCard pelo id do prospect. Se o Sale U reenviar o mesmo lead, o existente é atualizado.
Salesforce
- Conexão e autenticação: API REST (objetos padrão ou o Apex do cliente), às vezes por trás da camada de integração dele. OAuth2 client_credentials com um connected app, OAuth2 de um usuário administrador ou Basic Auth.
- Quais dados trafegam: na saída, o lead com contato, modelo, origem, concessionária e consultor de vendas; depois, o status e o agendamento. Na entrada, a oportunidade ganha ou faturada.
- Direção e frequência: saída ao fechar a conversa, ao agendar e a cada mudança de status. Entrada por uma consulta SOQL periódica (por exemplo, a cada hora), filtrada pela data da última modificação.
- Como evitamos duplicados: o id do lead fica salvo no contato e os envios seguintes o atualizam. Se o CRM também deduplica do lado dele, a regra dele é respeitada.
Seekop / SICOP
- Conexão e autenticação: robô (RPA) no portal com o usuário de cada concessionária. Se a concessionária tiver acesso à API, API REST em formato ADF com API key.
- Quais dados trafegam: na entrada, os leads da fila de espera do CRM. Na saída, o acompanhamento na ficha do lead; via API, o prospect (contato, modelo, origem e comentário) com sua concessionária, e o agendamento.
- Direção e frequência: com o robô, nos dois sentidos: ele lê a fila a cada poucos minutos e registra o acompanhamento na ficha do lead. Via API, do BIKY.ai para o Seekop ao fechar a conversa e ao agendar.
- Como evitamos duplicados: o robô usa o id do lead no CRM e uma chave de idempotência por ação. Via API, o contato é marcado como enviado.
HubSpot
- Conexão e autenticação: conector do Flows com OAuth2 autorizado por um usuário do cliente; em alguns casos, webhook ou iPaaS.
- Quais dados trafegam: na saída, o contato e, conforme o caso, um negócio em um pipeline combinado. A sincronização de entrada dos negócios que chegam à etapa de ganho já foi projetada.
- Direção e frequência: saída ao fechar a conversa ou a cada compra. A entrada por polling periódico já foi projetada.
- Como evitamos duplicados: upsert do contato. Já foi projetado salvar o id dele no BIKY.ai e fazer a correspondência por esse id.
Microsoft Dynamics 365
- Conexão e autenticação: API OData que o cliente ou seu integrador publica por trás de um API gateway, com uma subscription key no cabeçalho.
- Quais dados trafegam: na saída, o lead com sua campanha; o agendamento é criado e atualizado.
- Direção e frequência: do BIKY.ai para o Dynamics, ao fechar a conversa e a cada evento de agendamento.
- Como evitamos duplicados: só são enviados leads novos, não edições. O id do agendamento fica salvo no contato e as alterações são aplicadas a ele.
CRM da montadora
- Conexão e autenticação: API REST JSON com token de curta duração; multipart com um PDF para o pedido. Sem webhooks: um serviço dedicado consulta a API periodicamente. O que a API não cobre é feito por um robô no portal.
- Quais dados trafegam: na entrada, os leads e suas mudanças de status, por concessionária. Na saída, a criação dos nossos próprios leads, o acompanhamento, o test drive e o pedido de pré-venda.
- Direção e frequência: entrada por polling a cada minuto, respeitando um intervalo mínimo entre consultas para a mesma concessionária; saída a cada evento do SalesCard.
- Como evitamos duplicados: o código do lead fica salvo no SalesCard; a criação de leads usa o id do SalesCard como chave de idempotência.
Outras integrações que já construímos
Algumas não têm mais contas ativas, mas podem ser implementadas novamente.
| Sistema | Tipo | Conexão e dados |
|---|---|---|
| Tecnom | CRM automotivo | Lead em formato ADF via POST para o conector web dele, com usuário e senha. |
| Syonet 360 | CRM automotivo | O CRM envia os leads por webhook; o BIKY.ai registra ligações, visitas e agendamentos via API REST com Basic Auth. |
| Intelisis | DMS | O DMS consome a API do BIKY.ai e lê contatos e SalesCards pelo id. |
| Total Dealer | DMS de pós-venda | API de agendamentos. |
| Upnify | CRM | API REST de prospects e agendamentos, com um token que só pode criar registros. |
| Odoo | CRM e ERP | Criação de contatos e oportunidades com suas UTMs. |
| Zoho CRM | CRM | Conector com OAuth2 e renovação de token; o Zoho notifica por webhook. |
| RD Station CRM | CRM | Conector do Flows: cria negócios e os move entre as etapas do funil dele. |
| Smarthome | CRM | API REST de leitura e escrita. |
| Comunike | CRM | Webhook. |
| SICO | CRM imobiliário | Saída via API REST, com usuário e senha que geram um token de uma hora. |
| Wasi | CRM imobiliário | Sincroniza o estoque de imóveis com o catálogo do BIKY.ai. |
O Flows também inclui nós para os ERPs Siigo, Alegra e Defontana, e para um DMS de pós-venda (agendamento de serviços). As lojas virtuais (Shopify, VTEX e WooCommerce) sincronizam catálogo e contatos com o BIKY.ai e enviam notificações de carrinhos abandonados, pagamentos e alterações de pedidos. Os conectores delas, assim como os de pagamentos e transportadoras, estão na página de integrações.
Mapeamento de dados
O mapeamento é combinado campo a campo antes da construção, e cada lista fechada (origens, modelos, concessionárias, status) ganha sua própria tabela de equivalência.
| Dado do BIKY.ai | Campo típico do CRM | Regra de mapeamento |
|---|---|---|
| Nome e sobrenome | Nome, sobrenome | Algumas origens enviam o nome completo no campo de sobrenome: ele é separado antes do envio. Se o CRM exigir sobrenome e o BIKY.ai não tiver, o que enviar é combinado previamente. |
| Celular | Celular | Com código do país (52 mais 10 dígitos no México), a menos que o CRM ou o objeto exija o número nacional. Se ele chegar dividido em vários campos, a forma de montá-lo é combinada previamente. O código do país só é preenchido se a origem garantir esse dado. |
| Opcional, a menos que o objeto o exija. Se o CRM validar o formato, um campo vazio é omitido; alguns CRMs rejeitam acentos ou ñ. | ||
| Canal e campanha (UTM) | Origem, campanha | Traduzidos para o catálogo de origens do CRM; o que não tiver equivalente vai para "Outro". Cada valor vai em seu próprio campo, sem concatenar. |
| Produto ou modelo de interesse | Modelo, versão | Tabela de equivalência, com o código do CRM salvo no produto: a correspondência por nome falha. Se o campo for obrigatório, um valor padrão é combinado. |
| Concessionária | Código da concessionária ou filial | Tabela concessionária → código, validada com as concessionárias configuradas no BIKY.ai, não com o nome comercial. |
| Consultor de vendas atribuído | Responsável ou consultor | O ID do consultor no CRM, carregado no BIKY.ai. Se o CRM fizer a atribuição com regras próprias, ele não é enviado. |
| Etapa do Funnel | Status ou etapa | Tabela de equivalência nos dois sentidos (exemplo abaixo). |
| Agendamento ou test drive | Agendamento, evento | No fuso horário e no formato exatos que o CRM exige, com início e fim. O ID de cada agendamento é salvo para que ele possa ser atualizado. |
| ID do registro no CRM | Não se aplica | Salvo no contato ou no SalesCard, é a chave de cada atualização. |
| Tamanho de cada campo | Não se aplica | O tamanho máximo de cada campo é confirmado antes da construção: um ID, texto ou telefone mais longo é rejeitado. |
Os status são mapeados com as etapas do Funnel. Em uma conta automotiva, o Funnel de vendas vem com estas nove. O nome exibido de cada etapa pode variar conforme a conta; a chave não muda, e é ela que a API usa.
| Etapa do Funil de Vendas | Quem move o SalesCard | Como isso aparece no CRM |
|---|---|---|
Sem resposta ($step_mql$) | O SalesCard é criado aqui quando o lead chega, por qualquer canal ou pelo CRM. | Lead novo, com ou sem responsável atribuído. |
MQL respondido ($step_responded_mql$) | BIKY.ai, quando o cliente responde. | Primeiro contato registrado como acompanhamento. |
Interessado (SQL) ($step_sql$) | BIKY, quando o cliente é qualificado; ou o CRM, se marcar o lead como em acompanhamento. | Em acompanhamento. |
Agendado ($step_scheduling$) | BIKY ou o consultor, quando o agendamento é feito. | Agendamento ou evento criado. |
Comparecimento ($step_show$) | BIKY. Uma hora depois do horário marcado, envia um template de WhatsApp ao cliente e ao consultor perguntando se o cliente compareceu e move o SalesCard de acordo com a resposta. | Visita registrada. |
Demonstração ($step_test_drive$) | BIKY, quando a resposta a esse template indica que houve test drive. | Test drive registrado. |
Pré-venda ($step_won$) | O consultor, com produto, valor e data; ou o CRM, se informar a oportunidade como ganha. | Continua em acompanhamento; com o CRM da montadora, o pedido de pré-venda é enviado. |
Faturado ($step_billed$) | O consultor. Com o CRM da montadora, o próprio CRM, quando registra a venda. | Venda fechada. Com o CRM da montadora, o BIKY.ai não envia essa etapa, porque lá ela é irreversível. |
Perdido ($step_lost$) | O consultor, informando o motivo; ou o CRM, quando marca o lead como perdido. | Perdido, com motivo. |
Um lead que o CRM marca como inválido não move o SalesCard: apenas o status é armazenado, porque não se trata de uma venda perdida. As contas do setor automotivo também incluem um Funil de Pós-venda (qualificado, recebido, diagnóstico, aprovação, em serviço, entrega, pagamento, acompanhamento e não aprovado), que pode ser mapeado para o DMS de uma oficina quando necessário.
Sincronização e duplicados
Os dados de saída trafegam em tempo real ou quando a conversa é encerrada, dependendo do CRM. Os dados de entrada chegam por webhook, se o CRM oferecer esse recurso, ou, caso contrário, por consulta periódica (polling), com intervalos que vão de um minuto a uma hora. Nenhuma integração com CRM usa SFTP ou troca automática de arquivos.
O que dispara um envio ao CRM:
- A criação de um SalesCard: o lead é criado com contato, origem, modelo e concessionária.
- Um contato do consultor ou do BIKY (ligação, e-mail ou WhatsApp): um registro de acompanhamento.
- Uma mudança de etapa no Funil: o novo status.
- Um agendamento criado, remarcado ou cancelado: o agendamento ou o test drive.
- O encerramento de uma conversa: o lead com todos os seus dados e o seu status.
Os dados históricos são carregados uma única vez pela API do CRM, sem disparar mensagens nem fluxos, e com a data original de cada lead.
Regras contra duplicados:
- Todo id que o CRM retorna é armazenado no BIKY.ai, e o evento seguinte atualiza esse registro em vez de criar um novo.
- Os dados de entrada precisam ser idempotentes: o mesmo id de lead ou o mesmo evento repetido atualiza o SalesCard existente. Os CRMs fazem novas tentativas, e uma nova tentativa não pode abrir outro SalesCard.
- Antes de criar um contato, ele é buscado pelo número de telefone normalizado. Se o CRM já faz a deduplicação por conta própria, a regra dele é respeitada e o id que ele retorna é armazenado.
- Uma pessoa com um SalesCard aberto no Funil de Vendas não abre outro. Um interesse diferente abre, se o CRM o registrar como um lead separado.
- O lead entra por um único caminho. Se um formulário alimenta o BIKY.ai e o CRM ao mesmo tempo, o mesmo lead é criado duas vezes.
- Confirme com o cliente se o CRM dele cria um novo registro a cada envio. Enquanto não houver resposta, são enviados apenas registros novos, não edições.
Do que precisamos e quanto tempo leva
Construir costuma ser a parte rápida. Quem define o prazo são os insumos e as aprovações. Nos nossos projetos de 2025 e 2026, metade das concessionárias que entraram em um CRM já conectado ficou pronta em menos de duas semanas a partir da solicitação. Uma integração nova levou uma mediana de cinco semanas, sem contar a etapa comercial.
O que mais alonga um projeto: credenciais que não funcionam, um sandbox diferente do ambiente de produção, catálogos que chegam atrasados, o acordo de confidencialidade, a aprovação da marca ou do fornecedor do CRM e a linha de WhatsApp de cada concessionária. Veja a lista, por fase.
0. Antes de começar
- Acordo de confidencialidade e quaisquer documentos jurídicos que a sua empresa exija.
- Avaliação de segurança, se aplicável: temos certificação ISO/IEC 27001.
- Aprovação da marca ou do fornecedor do CRM para cada concessionária, se necessário.
1. Descoberta
- Documentação atualizada da API: objetos, campos obrigatórios, valores permitidos para cada lista (picklist), códigos de erro e limites de requisição.
- Se o CRM envia notificações por webhook ou se precisa ser consultado periodicamente.
- Quais objetos são sincronizados (lead, contato, oportunidade, agendamento) e quem é o dono de cada campo.
- Se o seu CRM cria um novo registro a cada envio ou atualiza o existente.
- Se o seu CRM também capta leads pelos próprios formulários e qual dos dois tem prioridade.
- Um responsável técnico do lado do cliente ou do integrador dele.
2. Mapeamento
- Catálogo de origens e status com seus códigos, indicando quais status são finais.
- Lista de modelos ou produtos com seus códigos e o valor padrão, caso o campo seja obrigatório.
- Concessionárias ou filiais com seus códigos no CRM.
- IDs dos consultores, se o CRM precisar saber quem está atendendo o lead.
- O tamanho máximo e o formato de cada campo, incluindo o número de telefone.
- As regras próprias do CRM: deduplicação, validações e atribuição automática.
3. Ambiente de testes
- Sandbox com credenciais válidas e a mesma versão, os mesmos dados de referência e as mesmas concessionárias do ambiente de produção.
- Credencial de integração, uma por ambiente, com permissões nos objetos em que vamos gravar: connected app (OAuth2 client_credentials) ou usuário técnico.
- Leads de teste combinados previamente: um teste em produção cria registros reais no seu CRM.
4. Go-live e monitoramento
- Credenciais de produção pelo canal seguro que combinarmos, nunca por e-mail, chat ou tickets.
- Aviso prévio antes de trocar ou desativar uma credencial.
- A linha de WhatsApp de cada concessionária, os IDs dos seus consultores e o cronograma de implantação por grupo de concessionárias.
- Um contato para incidentes.
Erros comuns e monitoramento
Quase todas as rejeições vêm dos dados, não da rede: um campo obrigatório vazio, um formato que o CRM não aceita ou uma regra específica do CRM. Esses casos não são reenviados automaticamente, porque falhariam da mesma forma. Em vez disso, corrigimos o dado ou a regra e reenviamos o evento.
| Erro | Causa típica | O que fazemos |
|---|---|---|
| O CRM responde 200, mas rejeita | O motivo vem no corpo da resposta; outros CRMs respondem 201 a um duplicado. | É preciso validar o corpo, não só o código HTTP. O Flows marca um 200 com success: false como falha; se o CRM usar outro indicador de erro, a validação é feita dentro do próprio fluxo. |
| Campo obrigatório vazio | O lead chega sem modelo de interesse, produto ou e-mail. | Validações antes do envio e um valor padrão combinado. Uma regra rígida demais, como não enviar sem e-mail, pode bloquear todos os leads. |
| Campo maior que o permitido | Um id, um texto ou um número de telefone que excede o campo do CRM. | O tamanho de cada campo é confirmado no mapeamento. |
| Nova validação no CRM | O CRM passa a exigir um campo ou um formato sem aviso prévio. | Quando as rejeições aumentam, verificamos o que mudou no CRM. |
| Concessionária sem código | Chega um lead de uma concessionária que não está na tabela de equivalências. | A tabela é validada antes de ativar cada concessionária. |
| Número de telefone inválido | Código do país duplicado, um 1 a mais ou um número truncado. | Normalização antes do envio; o que não pode ser recuperado é marcado como inválido e não é enviado. |
| Data ou hora rejeitada | Fuso horário, formato ou um test drive marcado como "realizado" com horário futuro. | O fuso horário e o formato exatos que o CRM exige, validados antes do envio. |
| Credencial expirada ou trocada | Token expirado ou credencial desativada durante uma troca. | O token é renovado antes de expirar usando o refresh token, ou solicitado novamente. |
| Excesso de requisições (429) | As consultas periódicas ultrapassam o limite do CRM. | Um intervalo mínimo entre consultas por distribuidor. |
| CRM fora do ar ou lento | 5xx ou timeout. | Os serviços dedicados e o robô fazem novas tentativas com intervalos crescentes (backoff). No Flows, as novas tentativas são ativadas por fluxo, porque, se o CRM não for idempotente, elas podem gerar duplicados. |
| Regra específica do CRM | Uma validação do cliente, como não permitir reatribuir o responsável. | O envio é ajustado à regra, por exemplo deixando que o CRM atribua o responsável. |
Como monitoramos:
- Cada execução fica registrada no histórico, com os dados enviados nos nós do CRM.
- Nas integrações com serviço dedicado e no robô, um monitor faz verificações a cada 5 minutos. Ele classifica cada falha pela causa, exibe tudo em um painel e envia alertas por e-mail apenas para problemas críticos e recorrentes.
- Acompanhamos de perto cada concessionária nos primeiros dias depois de ativá-la. Depois disso, sempre que há uma reclamação, conciliamos os leads do CRM com os SalesCards e as conversas do BIKY.ai.
Lições aprendidas
Quase tudo o que falhou se resume a quatro regras: armazenar o id externo, validar o corpo de cada resposta, confirmar campos e catálogos antes de construir e testar cada concessionária com um lead de teste antes de ativá-la.
- Sale U. O mesmo lead chegava muitas vezes, e cada reenvio abria outro SalesCard.
- O que mudamos: limpamos os SalesCards duplicados, e o fluxo de entrada agora busca o SalesCard pelo id do prospect antes de criar um novo.
- O que faríamos diferente: vincular o SalesCard ao id do prospect.
- Sale U. O CRM passou a validar campos que antes aceitava, e fluxos antigos começaram a falhar sem nenhuma mudança do nosso lado.
- O que mudamos: corrigimos os campos nos fluxos afetados.
- O que faríamos diferente: enviar um alerta quando as rejeições de uma integração aumentam.
- Sale U. Concessionárias novas não tinham regra de atribuição, então os leads delas voltavam ao CRM sem atendimento.
- O que mudamos: uma revisão da tabela de concessionárias sempre que uma nova conta é configurada.
- O que faríamos diferente: testar cada concessionária com um lead de teste antes de ativá-la.
- Salesforce. Muitos leads foram rejeitados por causa de um campo obrigatório vazio: o modelo de interesse.
- O que mudamos: solicitamos a documentação completa do CRM: campos obrigatórios, valores permitidos para cada lista (picklist) e catálogos.
- O que faríamos diferente: combinar valores padrão antes da ativação.
- Salesforce. Uma regra do CRM bloqueava a reatribuição do responsável, e a rejeição não aparecia no BIKY.ai.
- O que mudamos: encontramos a causa nos logs do conector.
- O que faríamos diferente: registrar cada rejeição e perguntar sobre as regras de validação na fase de descoberta.
- Salesforce. A consulta de vendas ganhas filtrava pela data de criação, então quase nada chegava. Além disso, ela movia SalesCards do Funil de Pós-venda para a etapa de venda ganha (
$step_won$) do Funil de Vendas.- O que mudamos: a consulta agora usa a data da última modificação da oportunidade e filtra pelo Funil de Vendas.
- O que faríamos diferente: testar a consulta com seis meses de histórico antes da ativação.
- Salesforce. Os formulários da Meta alimentavam o BIKY.ai e o CRM ao mesmo tempo, então cada lead era criado duas vezes.
- O que mudamos: agora os leads entram apenas pelo CRM.
- O que faríamos diferente: definir um único caminho de entrada já na fase de descoberta.
- Seekop. Quando uma conta foi dividida em contas por concessionária, o roteamento pelo nome da concessionária deixou de bater e alguns leads nunca foram enviados.
- O que mudamos: um único template compartilhado, com os dados de cada concessionária em variáveis de ambiente, e a integração anterior desligada na mesma etapa.
- O que faríamos diferente: nunca rotear por nomes que o cliente pode alterar.
- HubSpot. A correspondência de negócios ganhos identificava apenas alguns casos: o id do HubSpot não ficava salvo no contato, e as buscas por e-mail geravam falsos positivos.
- O que mudamos: projetamos a correspondência para usar apenas o id, com o número de telefone exato como alternativa.
- O que faríamos diferente: salvar o id externo desde o primeiro envio.
- Zoho. O acesso expirava a cada hora porque o token não estava sendo renovado.
- O que mudamos: passamos a usar um conector que renova o token sozinho.
- O que faríamos diferente: usar sempre o refresh token ou um conector que cuide disso.
- Dynamics 365. A chave de assinatura era enviada na URL, mas o gateway exige que ela vá no header. Além disso, um campo do CRM era mais curto que o nosso id.
- O que mudamos: a chave agora vai no header, e o cliente aumentou o tamanho do campo.
- O que faríamos diferente: revisar headers e tamanhos de campo durante o mapeamento.
- Vários. Alguns CRMs exigem dados que o BIKY.ai nem sempre tem, como um telefone com um número exato de dígitos, o sobrenome ou o produto. Uma regra desse tipo acabou bloqueando todos os leads de um cliente.
- O que mudamos: perguntamos por essas regras na fase de descoberta.
- O que faríamos diferente: medir com dados reais quantos leads cumprem cada regra antes de ativá-la.
- CRM da montadora. Marcar uma venda como fechada congela o lead no CRM para sempre.
- O que mudamos: o BIKY.ai nunca envia esse status. Ele apenas o lê.
- O que faríamos diferente: perguntar na fase de descoberta quais status são irreversíveis.
- CRM da montadora. Uma mudança nas credenciais do CRM interrompeu a entrada de leads.
- O que mudamos: um alerta quando as consultas falham repetidamente ao longo do tempo.
- O que faríamos diferente: combinar aviso prévio de cada mudança e o envio das novas credenciais por um canal seguro.
- CRM da montadora. O sandbox não tinha os dados do distribuidor do projeto e aceitava valores que a produção rejeita.
- O que mudamos: validamos cada campo no sandbox e confirmamos em produção.
- O que faríamos diferente: solicitar desde o início um sandbox idêntico à produção.
- Vários. Telefones com código de país duplicado, um 1 a mais ou sem código de país criavam contatos inválidos e SalesCards duplicados.
- O que mudamos: normalização de telefones nos fluxos de entrada, com regras por origem.
- O que faríamos diferente: combinar o formato do telefone durante o mapeamento, objeto por objeto.
Campos e estrutura da API
Campos, valores permitidos e regras da API do BIKY.ai para contatos e SalesCards.
Acesso
Toda chamada leva a chave da conta no header Authorization: Bearer <key>. A Keybe emite uma chave por conta e a entrega junto com as URLs base dos serviços de Contacts e Funnels.
{app}: o id da conta no BIKY.ai, um por marca ou concessionária. Ele vai em todos os caminhos, exceto no de validação de telefone.{typeEntity}:people,businessouoffice. Para leads, usepeople.- Um recurso único volta como um objeto simples. Uma lista volta como
{data, paginator}. OpaginatorincluitotalDocs,limit,page,totalPages,pagingCounter,hasPrevPage,hasNextPage,prevPageenextPage. - Os erros voltam como
{statusCode, timestamp, path, message, error}. Em um erro de validação,messageé a lista de campos que falharam, por exemplo["responsible should not be empty"].
Contato e SalesCard
O contato é a pessoa. O SalesCard é cada oportunidade de venda dessa pessoa dentro de um Funnel. Normalmente, um CRM mapeia o seu lead para os dois.
| Contato | SalesCard | |
|---|---|---|
| O que é | A pessoa ou empresa, no CDP do BIKY.ai | Uma oportunidade, posicionada em uma etapa de um Funnel |
| Quantos | Um por pessoa; buscado por telefone ou e-mail | Vários por pessoa. Enquanto houver um SalesCard aberto no Funnel de Vendas, nenhum outro é aberto, a menos que o CRM registre um lead diferente |
| Seu id | uuid | _id |
| Como se relacionam | Não se aplica | persons[] contém o uuid do contato |
| O id do seu CRM | externalIds[], com systemName e value | utm.sourceCardId ou um campo de extendedData |
Endpoints
| Recurso | Endpoint | O que faz |
|---|---|---|
| Contatos | POST /{app}/contacts | Cria um contato. |
| Contatos | POST /{app}/contacts/upsert-or-fallback | Cria o contato ou atualiza aquele que já tem esse telefone ou e-mail. Responde com {status, contact}, em que status é created, updated ou fallback. Com dados inválidos, retorna o contato de fallback da conta e o motivo em reason. |
| Contatos | GET /{app}/contacts/{typeEntity}/phone/{phone} | Busca por telefone. |
| Contatos | GET /{app}/contacts/{typeEntity}/email/{email} | Busca por e-mail. |
| Contatos | GET /{app}/contacts/{typeEntity}/{uuid} | Lê um contato. |
| Contatos | PATCH /{app}/contacts/{uuid} | Atualiza um contato; o typeEntity vai no body. |
| Contatos | POST /utils/validate-phone | Valida um telefone com o body {phone}. |
| Funnels | GET /{app}/funnel/with-steps | Os Funnels da conta com suas etapas. |
| Funnels | GET /{app}/{funnelId}/steps | Etapas de um Funnel, com sua chave (name), nome de exibição (label) e ordem (order). |
| SalesCards | POST /{app}/funnel/{funnel}/steps/{step}/cards | Cria um SalesCard em uma etapa. |
| SalesCards | POST /{app}/funnel/{funnel}/steps/{step}/cards/upsert | Se a mesma pessoa tiver um SalesCard nessa etapa criado dentro da janela withinHours (1 hora por padrão), ele é atualizado; caso contrário, um novo é criado. |
| SalesCards | GET /{app}/cards-filter?person={uuid} | Os SalesCards de um contato, do mais recente ao mais antigo. |
| SalesCards | GET /{app}/simple/cards/{id} | Lê um SalesCard. |
| SalesCards | PATCH /{app}/simple/cards/{id} | Atualiza um SalesCard ou o move para outra etapa com stepName. |
| SalesCards | DELETE /{app}/funnel/{funnel}/steps/{step}/cards/{id} | Exclui um SalesCard; a exclusão é lógica (soft delete). |
Campos do contato
| Campo | Tipo | Obrigatório | Significado e valores |
|---|---|---|---|
typeEntity | texto | Sim | people, business ou office. |
name | texto | Sim | Nome. |
surname | texto | Não | Sobrenome. |
phone[] | lista | Não | Cada telefone leva value com código de país (525500001234), countryCode (52), country (MX), isPrimary e verify. Na criação, value, countryCode e isPrimary são obrigatórios; em um PATCH, verify também é obrigatório. |
email[] | lista | Não | Cada e-mail leva value, isPrimary e verify. Na criação, value e isPrimary são obrigatórios; em um PATCH, verify também é obrigatório. |
registerChannel[] | lista | Sim | channel indica de onde o contato veio (api, form, import, web, chatWeb, whatsapp, instagram, facebook, tiktok, email, phone, sms, salesforce, hubspot, rdStation, shopify, vtex, other, entre outros). data é um texto livre com detalhes sobre a origem. |
source | objeto | Não | Atribuição: utmSource, utmMedium, utmCampaign, utmTerm, utmContent, utmPartner, utmKam, utmCloser, channel e channelOther. |
externalIds[] | lista | Não | Os ids do contato em outros sistemas, cada um como {systemName, value}. Em um PATCH, a lista inteira é substituída, por isso recomendamos usá-la junto com isPushData. |
extendedData[] | lista | Não | Campos específicos da conta: category e field são obrigatórios, além de value, valueArray ou valueMultiple. |
documentType, document | texto | Não | Tipo e número do documento (passport, nit, curp, rut, dni, entre outros). |
responsible | objeto | Não | Consultor responsável pelo contato: uuid e name obrigatórios, email e phone opcionais. |
country, province, city, zone | texto | Não | Localização. |
habeasData | objeto | Não | Consentimento: habeasDataStatus (Confirmed, Unconfirmed, OnlyLegals ou Blacklist), aceite por canal, data, IP, país e evidência. |
tags | lista de texto | Não | Tags livres. |
isPushData | booleano | Não | Apenas em PATCH. Com true, os telefones e e-mails enviados são adicionados aos existentes; com false, eles os substituem. |
Campos do SalesCard
| Campo | Tipo | Obrigatório | Significado e valores |
|---|---|---|---|
name | texto | Sim | Título do SalesCard, normalmente o nome do lead. |
persons[] | lista de texto | Sim | O uuid do contato. |
responsible | objeto | Sim | Consultor ou BIKY responsável: uuid e name obrigatórios, email e phone opcionais. |
description | texto | Não | Texto livre visível para o consultor. |
amount | número | Não | Valor da oportunidade. Se chegar como texto, é armazenado como número. |
productsData[] | lista | Não | Produto de interesse: id, sku e name obrigatórios; preço, entrada, valor financiado, marca e opcionais. |
utm | objeto | Não | Atribuição da oportunidade, com sourceCardId, o id da oportunidade no seu CRM. sourceHistory guarda cada source que o SalesCard recebe por meio de cards/upsert. |
extendedData[] | lista | Não | Campos específicos da conta. |
reason | texto | Não | Motivo de fechamento, quando a oportunidade é ganha ou perdida. |
priority | texto | Não | emergency, lowest, low, medium, high ou highest. |
schedule | objeto | Não | Agendamento: dataTime, advisor, status e meetingUUID obrigatórios; type, location, description e entityUUID opcionais. |
invoiceData | objeto | Não | Nota fiscal: documento, carro (vin, marca, modelo, versão, ano e preço) e cliente. |
stepName | texto | Não | Somente em PATCH. Chave da etapa de destino, por exemplo $step_sql$. |
isPushData | booleano | Não | Somente em PATCH. Com true, extendedData é mesclado por field e productsData por id; sem ele, ambos são substituídos por completo. |
Exemplos
Os valores entre < > são fornecidos por cada conta: ids de Funil, etapa, consultor e produto.
1. Criar ou atualizar o contato. POST /{app}/contacts/upsert-or-fallback. A resposta é {status, contact}; contact.uuid é o id usado no SalesCard. Com fallback, o motivo vem em reason, e você não deve criar o SalesCard até corrigir os dados.
{
"typeEntity": "people",
"name": "Mariana",
"surname": "Torres",
"phone": [{ "value": "525500001234", "countryCode": "52", "country": "MX", "isPrimary": true }],
"email": [{ "value": "[email protected]", "isPrimary": true }],
"registerChannel": [{ "channel": "api", "data": "MiCRM" }],
"source": { "utmSource": "micrm", "utmCampaign": "lanzamiento-octubre" },
"externalIds": [{ "systemName": "MiCRM_LeadId", "value": "L-000123" }]
}2. Criar o SalesCard na primeira etapa. POST /{app}/funnel/{funnel}/steps/{step}/cards. A resposta retorna o SalesCard com seu _id.
{
"name": "Mariana Torres",
"persons": ["<contact uuid>"],
"responsible": { "uuid": "<advisor uuid>", "name": "<advisor name>" },
"description": "Lead received from MiCRM.",
"productsData": [{ "id": "<product id>", "sku": "<sku>", "name": "<model>", "price": 450000 }],
"utm": { "source": "micrm", "campaign": "lanzamiento-octubre", "sourceCardId": "OPP-000456" }
}3. Mudança de etapa. PATCH /{app}/simple/cards/{id}. Move o SalesCard para Interessado (SQL) sem alterar mais nada.
{ "stepName": "$step_sql$" }Regras da API
| Caso | O que a API faz | O que fazer |
|---|---|---|
| Telefone mexicano na criação | 52 + 10 dígitos, 521 + 10 e +52 55 1234 5678 com espaços são armazenados como 52 + 10. Com 10 dígitos e sem código do país, upsert-or-fallback responde com status: fallback e o contato de fallback. | Envie o telefone com o código do país. Com status: fallback, não crie o SalesCard: corrija os dados e reenvie. |
| Busca por telefone | 52, 521 e +52 encontram o mesmo contato; 10 dígitos sem código do país retornam 404. | Sempre busque com o código do país. |
| Contato existente | upsert-or-fallback com um telefone já existente atualiza esse contato e responde com status: updated. | Use-o para que a criação a partir do CRM não duplique contatos. |
| Telefones e e-mails em um PATCH | Sem verify, retorna 400. Com isPushData: true, eles são adicionados; com false, substituem os existentes. | Envie verify: false se não estiverem verificados. |
source e externalIds em um PATCH | Ambos são substituídos por completo; externalIds: [] os apaga. | Envie a lista completa de externalIds e escreva source somente na criação. |
Criação do SalesCard sem responsible | 400 responsible should not be empty. | Sempre envie o consultor, ou BIKY se não houver consultor. |
productsData | id, sku ou name vazio: 400. price como texto: 400. | Se o produto não estiver no catálogo, crie o SalesCard sem productsData. |
| PATCH do SalesCard | utm é mesclado. Sem isPushData, extendedData e productsData são substituídos por completo. stepName move o SalesCard. | Use isPushData: true para adicionar sem apagar. |
cards/upsert | Se a pessoa já tiver um SalesCard nessa etapa criado dentro de withinHours, ele é atualizado. | Use-o quando o CRM puder repetir o envio. |
cards-filter | A paginação começa em offset=1; search não filtra neste endpoint. | Filtre por person e compare utm.sourceCardId. |
| Exclusão do SalesCard | A exclusão é lógica (soft delete): o SalesCard deixa de aparecer em cards-filter, embora o GET por id continue respondendo. | Confirme a exclusão com cards-filter. |