API e integrações
O LinkedFlow fala com o resto das tuas ferramentas por três caminhos: uma API REST com token, um webhook que dispara workflows a partir de fora e nós que chamam os teus próprios serviços de dentro de um percurso. Esta página é o contrato exato, com exemplos prontos para n8n, Make ou um simples curl.
A API que a própria aplicação usa é a API pública: mesmos endpoints, mesma autenticação. Para uma integração não uses o token do navegador: cria um token de API em Definições → Tokens de API, com a expiração que escolheres e preso a este workspace.
Os três caminhos
| Caminho | Quem chama quem | Para que serve |
|---|---|---|
| API REST | A tua ferramenta → LinkedFlow | Criar prospetos e listas, lançar workflows, ler execuções, resolver aprovações, obter o funil. |
| Webhook de entrada | A tua ferramenta → um workflow concreto | Arrancar um percurso para um prospeto que já existe no CRM, com o token do workflow como credencial. |
| Nós de saída | LinkedFlow → a tua ferramenta | Avisar o teu CRM ou o n8n a meio do percurso (Webhook de saída) ou pedir-lhe um dado e continuar com a resposta (Pedido HTTP). |
Autenticação
Toda a API vive em https://app.linkedflow.pro/api/v1 e autentica-se com um token no cabeçalho Authorization. Há duas formas de o obter, e só a primeira serve para integrações.
Token de API (o que queres para o n8n)
Na aplicação: Definições → Tokens de API → Novo token. Dás-lhe um nome («n8n · sinais diários»), escolhes a expiração — 30 dias, 90 dias, 1 ano ou sem expiração — e copia-lo: só é mostrado uma vez.
| Propriedade | O que significa |
|---|---|
| Preso a um workspace | Aquele onde foi criado, e não se pode mudar: mesmo que troques de workspace na aplicação ou alguém envie o cabeçalho X-Workspace, esse token continua a escrever onde foi configurado. |
| Herda o teu papel | Não dá permissões extra. Se desceres de MANAGER para VIEWER, as chamadas de escrita passam a dar 403. |
| Sobrevive à tua palavra-passe | Mudar a palavra-passe fecha as outras sessões do navegador, mas não revoga os tokens de API: rodar a palavra-passe nunca deita abaixo as integrações. |
| Revoga-se num instante | No mesmo ecrã. Deixa de funcionar na chamada seguinte, e aí vês também quando foi usado pela última vez. |
Sugestão: cria um utilizador à parte para a máquina («automacao@aminhaempresa.com») com o papel mínimo necessário e emite o token a partir dessa conta. Assim a atividade do workspace distingue o que fez um humano do que fez o n8n, e podes cortar-lhe o acesso sem mexer no teu.
Token de sessão (para um script descartável)
O login da aplicação também devolve um token, mas expira ao fim de 30 dias e segue o workspace ativo do teu utilizador. Serve para um curl de teste; não para uma automação que tem de aguentar meses:
curl -X POST https://app.linkedflow.pro/api/v1/auth/login \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{"email":"tu@email.com","password":"a-tua-palavra-passe"}'
{
"user": { "id": "…", "name": "Valen", "current_workspace": { "id": "…", "role": "OWNER" } },
"token": "198|eMdBPK8g…"
}
A partir daí, cada chamada leva dois cabeçalhos:
Authorization: Bearer 198|eMdBPK8g…
Accept: application/json
O token é a tua palavra-passe. Guarda-o como credencial no n8n (Header Auth: nome Authorization, valor Bearer <token>), nunca no URL nem no corpo de um nó. Se um token de API escapar, revoga-o em Definições → Tokens de API: é imediato e não afeta os outros.
Workspace e papéis
Não é preciso enviar o workspace: o token trabalha sempre sobre o workspace atual do utilizador. Se pertences a vários, POST /auth/switch-workspace/{workspace} troca. Cada endpoint exige o mesmo papel que o ecrã equivalente na aplicação (VIEWER < MEMBER < MANAGER < ADMIN < OWNER); se faltar, a resposta é 403. Os papéis estão explicados em Definições.
Sugestão para integrações: cria um utilizador à parte para a máquina («automacao@aminhaempresa.com») com o papel mínimo necessário. Podes cortar-lhe o acesso sem mexer no teu, e na atividade do workspace distingue-se o que fez um humano do que fez o n8n.
Convenções
- Sem
Accept: application/jsonnão há JSON: a aplicação responderia com um redirecionamento ou HTML. É o erro número um de quem começa. - Erros:
401token em falta ou expirado,403papel insuficiente ou subscrição inativa,404fora do teu workspace,422validação ({"message":"…","errors":{"campo":["…"]}}),429demasiadas chamadas. - Coleções: os prospetos vêm paginados (
data,current_page,last_page,total); outros recursos devolvem a coleção direta ou dentro deitems. Olha sempre para a primeira resposta antes de mapear campos. - Idioma: as mensagens de erro saem no idioma do teu utilizador. Podes forçá-lo com
Accept-Language: pt. - Ritmo: não há limite global, mas os endpoints caros têm o seu (o webhook de workflow, 30 chamadas por minuto; o compositor de IA, 20).
Endpoints principais
A lista completa é a da aplicação; isto é o que realmente se usa a partir de fora.
Prospetos e listas
| Endpoint | Papel | O que faz |
|---|---|---|
GET /prospects | VIEWER | Lista paginada. Filtros: search, status, list_id, tag. |
POST /prospects | MEMBER | Cria um prospeto. Aceita list_id para o colocar numa lista à passagem. |
GET /prospects/{id} | VIEWER | Ficha completa. |
PUT /prospects/{id} | MEMBER | Edita campos (não o estado: esse é o motor que o move). |
POST /prospects/bulk-tags | MEMBER | Etiqueta em bloco. |
GET /prospects/{id}/conversation | VIEWER | O fio real do LinkedIn. |
POST /prospects/{id}/conversation/messages | MANAGER | Envia uma DM a sério (respeita quotas e horário). |
GET · POST /lists | VIEWER · MEMBER | Listar e criar listas. |
POST /lists/{id}/prospects | MEMBER | Adiciona prospetos existentes a uma lista. |
POST /suppression | MANAGER | Manda alguém para a lista de supressão. |
Workflows e execuções
| Endpoint | Papel | O que faz |
|---|---|---|
GET /workflows | VIEWER | Lista com estado, versão atual e última execução. |
POST /workflows/{id}/run | MANAGER | Lança sobre list_id ou prospect_ids[]. Aceita account_id e allow_repeat. |
POST /workflows/{id}/activate · /pause | MANAGER | Liga ou desliga os disparadores. |
POST /workflows/{id}/validate · /dry-run | MEMBER | Valida e simula sem tocar no LinkedIn. |
GET /executions · /executions/{id} | VIEWER | Execuções e o seu detalhe com KPI por nó. |
GET /prospect-executions/{id} | VIEWER | O percurso de uma pessoa, nó a nó. |
POST /executions/{id}/cancel | MANAGER | Trava o que ficou pendente. |
GET /approvals · POST /approvals/{id}/approve | VIEWER · MANAGER | A caixa de aprovações a partir de fora — do Slack, por exemplo. |
GET /dashboard/funnel · /stats · /activity | VIEWER | Os números do dashboard, para os teus próprios relatórios. |
GET /errors/unmanaged · /paused | VIEWER | O que espera decisão humana. Ideal para um alerta diário. |
A receita que resolve 80 %: criar e disparar
Um prospeto novo entra no CRM e, se o deixares cair numa lista, o workflow que escuta essa lista arranca sozinho. São duas chamadas, ou até uma:
curl -X POST https://app.linkedflow.pro/api/v1/prospects \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" -H "Accept: application/json" \
-d '{
"linkedin_url": "https://www.linkedin.com/in/alguem",
"first_name": "Ana",
"company": "Consultora Norte",
"tags": ["n8n", "sinal:a-contratar"],
"source": "n8n",
"list_id": "01a05d4e-23b2-725c-9aa4-e1ed9e8fd6da"
}'
De onde sai o list_id? Da aplicação: Prospetos → clica na lista para a selecionar → botão Copiar ID. Por API, GET /lists devolve o id de cada uma. É um UUID (01a05d4e-23b2-725c-…); se enviares outra coisa, a resposta é um 422 a dizer que o list_id não é válido.
Três coisas a saber sobre esta chamada:
- Basta
linkedin_urloupublic_identifier. Se o URL não for de um perfil, responde422. - O duplicado responde
409e não é uma falha: devolve o prospeto que já existia e adiciona-o à lista à mesma. No n8n, configura o nó para não abortar com 409 — é o caminho normal quando reprocessas uma fonte. - Ao entrar na lista dispara o trigger «Ao adicionar a uma lista» de qualquer workflow ativo que a escute, quer o prospeto seja novo, quer já existisse e não estivesse nela. É esse o engate: o n8n não precisa de saber nada de workflows, só de encher uma lista.
Um list_id com forma de UUID mas que não existe (ou que é de outro workspace) não dá erro: o prospeto é criado e não entra em lista nenhuma. É isolamento entre inquilinos — a resposta não pode revelar que listas outro tem — por isso confere o campo lists da resposta se queres ter a certeza.
Se preferires lançar explicitamente, usa POST /workflows/{id}/run com {"list_id":"…"} ou {"prospect_ids":["…"]}. Exige papel MANAGER e uma versão guardada do workflow.
Webhook de entrada: disparar um workflow a partir de fora
Um workflow que começa pelo nó Webhook expõe um URL com token próprio (visível no builder, papel MANAGER ou superior):
POST https://app.linkedflow.pro/api/v1/webhooks/workflows/{token}
Content-Type: application/json
{ "linkedin_url": "https://www.linkedin.com/in/alguem" }
Identificadores válidos, pelo menos um: public_identifier, linkedin_url ou email. O que enviares a mais fica disponível dentro do percurso como {{trigger.*}}, por isso podes passar o motivo do sinal e usá-lo no texto da mensagem.
| Resposta | Significa |
|---|---|
202 {"status":"accepted"} | Recebido. É sempre esta, exista ou não o prospeto e arranque ou não o percurso. |
404 | Token desconhecido, workflow não ativo, ou o primeiro nó não é um Webhook. |
422 | Não enviaste qualquer identificador. |
Este endpoint não cria prospetos. Resolve um que já esteja no teu CRM; se não encontrar ninguém, responde 202 à mesma e não acontece nada. É deliberado: a resposta não pode servir para descobrir quem está e quem não está na tua base. Se a tua integração traz gente nova, cria-a antes com POST /prospects.
O 202 também não garante que o percurso comece: um prospeto suprimido, marcado «não contactar» ou que já respondeu fica de fora pelas proteções do costume. O que aconteceu de facto vê-se em Execuções.
Saídas: quando o LinkedFlow chama a tua ferramenta
Webhook de saída
O nó Webhook de saída faz um POST para o URL que indicares. Sem corpo personalizado, envia isto:
{
"prospect": {
"id": "01a0…",
"full_name": "Ana García",
"linkedin_url": "https://www.linkedin.com/in/…",
"company": "Consultora Norte",
"status": "REPLIED"
},
"execution_id": "01a0…",
"node_id": "webhook_1"
}
O POST não vai assinado, e o nó só tem dois campos: método e URL. Não há cabeçalhos nem corpo personalizável, por isso não podes enviar uma assinatura nem um segredo num cabeçalho. Tudo o que queiras que viaje contigo vai no URL, que aceita variáveis:
https://o-teu-n8n/webhook/respostas?s=UM-SEGREDO-LONGO&cat={{previous.classification}}
No n8n isso chega como {{ $json.query.s }} e {{ $json.query.cat }} — não em headers nem em body. Verifica o segredo com um nó Se logo a seguir ao webhook e descarta o que não o traga: sem essa verificação, quem descobrir o URL pode injetar dados falsos.
Detalhes operacionais: 15 segundos de tempo máximo; um 5xx é considerado passageiro e é repetido até três vezes com espera crescente; um 4xx é marcado como falha de configuração e espera decisão tua na caixa de erros. Responde depressa e com 200: se a tua automação for lenta, aceita primeiro e processa depois.
Pedido HTTP: pedir um dado e seguir
O nó Pedido HTTP é igual, mas pensado para usar a resposta. O que devolveres fica disponível no nó seguinte:
{{previous.status}} → 200
{{previous.response.tier}} → "A" (o teu JSON, dentro de "response")
{{previous.response.angulo}} → "está a contratar"
Com isso, um nó Se bifurca pelo teu próprio scoring: {{previous.response.tier}} == "A". Devolve sempre um JSON plano e responde em menos de 15 segundos; se o teu serviço puder demorar, devolve um valor por omissão em vez de fazer o percurso esperar.
Cinco fluxos de n8n que funcionam
1 · Sinal externo → contacto (captar)
Schedule às 07:30 → HTTP Request à tua fonte de sinais (publicações, mudanças de cargo, ofertas de emprego) → Code que normaliza para linkedin_url → Remove Duplicates → HTTP Request para POST /prospects com o list_id de «Sinais de hoje» e o sinal em tags.
No LinkedFlow: um workflow ativo com disparador Ao adicionar a uma lista → Ler perfil → Pontuar com IA → Se {{previous.score}} >= 70 → Reagir à última publicação → Esperar 1 dia → Enviar convite com nota. Configura o nó do n8n para tratar o 409 como sucesso.
2 · Resposta classificada → CRM e agenda (atender)
No LinkedFlow: disparador Mensagem recebida → nó Classificar resposta → todas as saídas para o mesmo Webhook de saída, com a categoria no URL: ?cat={{previous.classification}}.
No n8n: Webhook → um Se que compara {{ $json.query.s }} com o teu segredo → Switch por {{ $json.query.cat }}: INTERESTED cria o negócio no teu CRM, avisa no Slack e envia o link de agendamento; QUESTION redige um rascunho com IA e deixa-o no Slack para aprovação; NOT_NOW escreve a data de recontacto numa folha e um cron reinjeta-a aos 90 dias; DO_NOT_CONTACT chama POST /suppression e fecha.
3 · «Comenta GUIA e eu envio»
No LinkedFlow: disparador Comentário numa publicação com palavra-chave → Reagir ao comentário → Responder ao comentário → Enviar mensagem com o link → Webhook de saída.
No n8n: inscrição na tua ferramenta de email, linha numa folha com comentou → entregue → abriu, e ao fim de três dias, se não houve resposta, um POST para o webhook de entrada de um workflow de seguimento. Lembra-te de que os comentários são sondados a cada 5 minutos e que responder a um comentário não gasta quota de mensagens.
4 · Enriquecimento e scoring próprios a meio do percurso
Aqui é o LinkedFlow que chama o n8n. No percurso: Ler perfil → Pedido HTTP ao teu webhook do n8n (responder com o último nó) → Se {{previous.response.tier}} == "A" → convite com nota à medida; se não, para uma lista de nurturing.
No n8n: Webhook → scraping do site da empresa → um modelo de IA que devolve JSON estrito (tier, angulo, dor) → Respond to Webhook. Põe um fallback (tier: "B") para que uma falha tua nunca entupa o percurso.
5 · O relatório de segunda-feira (vigiar)
Schedule segunda às 07:00 → GET /dashboard/funnel e GET /executions → GET /errors/unmanaged → um modelo de IA com o prompt «três decisões, não três gráficos» → email. Zero painéis novos: os números saem da mesma API que desenha o dashboard da aplicação.
Descarrega-os já montados
Quatro workflows de n8n prontos a importar a partir de ficheiro. Antes de os ativar: cria uma credencial Header Auth com o nome Authorization e o valor Bearer <o-teu-token>, e substitui o id de lista de exemplo pelo teu.
- 1 · Sinal externo → prospeto numa lista — o que resolve 80 %.
- 2 · Resposta classificada → CRM e agenda — inclui a verificação do cabeçalho secreto.
- 3 · Enriquecimento e scoring — o que responde ao nó Pedido HTTP.
- 4 · O relatório de segunda-feira — funil, execuções e erros pela API.
Boas práticas
- Deduplica antes de chamar, por
linkedin_urle dia. Dois POST iguais não duplicam o prospeto, mas podem metê-lo duas vezes no fluxo se o tirares da lista e o voltares a pôr. - Não lutes contra as quotas. Por muito depressa que empurres, as ações saem ao ritmo da conta (25 visitas, 20 convites e 30 mensagens por dia por omissão). Pôr 500 prospetos na fila não acelera nada, só enche a fila.
- Regista o
execution_idque chega nos webhooks de saída: é a chave para voltar a ver esse percurso na aplicação. - Um utilizador por integração, com o papel mínimo, e roda o seu token quando mudar de mãos.
Falta-te um endpoint? Escreve-nos pelo chat de apoio da aplicação: o que se documenta e se abre primeiro é decidido pelas integrações que as pessoas estão mesmo a construir.