Pular para o conteúdo

n8n

O n8n conversa com a Ligga API pelo nó HTTP Request, sem nó dedicado e sem código. Uma credencial de cabeçalho carrega a chave, e cada nó só precisa do método, da URL e do corpo.

A chave vive numa credencial, nunca escrita dentro do nó. Em Credentials → New, escolha Header Auth:

CampoValor
NameLigga API
Header NameAuthorization
Header ValueBearer ligga_live_…

O Bearer e o espaço fazem parte do valor. Sem eles, toda chamada volta 401 invalid_token.

Todas as URLs desta página partem do mesmo endereço, https://api.ligga.app/functions/v1/api, seguido do caminho do recurso.

Adicione um nó HTTP Request e configure:

CampoValor
MethodGET
URLhttps://api.ligga.app/functions/v1/api/v1/me
AuthenticationGeneric Credential TypeHeader AuthLigga API

Clique em Test step. A resposta descreve a chave e confirma que a credencial está correta:

{
"data": {
"team_id": "bca09e2f-41ab-4417-b84b-f2ff50f991ca",
"team_name": "Pet Shop Aurora",
"scopes": ["*:read", "sales:write"],
"modules": ["clientes", "vendas"]
},
"meta": { "request_id": "req_01JZXQ8V2K5M7N9P0R1S2T3U4V" }
}

O nó HTTP Request pagina sozinho. Configure a listagem e ligue a paginação nas opções do nó:

CampoValor
MethodGET
URLhttps://api.ligga.app/functions/v1/api/v1/customers
Send Query Parametersligado, com limit = 100
Options → Pagination → Pagination ModeUpdate a Parameter in Each Request
TypeQuery
Namecursor
Value{{ $response.body.pagination.next_cursor }}
Pagination Complete WhenOther
Complete Expression{{ !$response.body.pagination.has_more }}
Interval Between Requests200 ms

O cursor é opaco: o nó só o copia da resposta anterior para a query da próxima requisição. limit vai de 1 a 100, com padrão 20.

Se preferir controlar o laço na mão, o desenho é o mesmo em nós:

  1. HTTP RequestGET /v1/customers?limit=100&cursor={{ $json.cursor ?? '' }}.

  2. Nó de processamento — o que você faz com data (gravar em planilha, enviar para outro sistema).

  3. If — condição {{ $json.pagination.has_more }} é verdadeira?

  4. Ramo verdadeiro — um nó Set guarda cursor = {{ $json.pagination.next_cursor }} e volta para o HTTP Request. O ramo falso encerra.

Repetir a execução de um workflow é normal no n8n: o usuário reprocessa, o trigger dispara duas vezes, um nó falha e você reexecuta. O cabeçalho Idempotency-Key é o que impede a segunda passada de criar uma segunda venda.

CampoValor
MethodPOST
URLhttps://api.ligga.app/functions/v1/api/v1/sales
AuthenticationHeader AuthLigga API
Send Headersligado
Header — Idempotency-Key{{ $execution.id }}
Send Bodyligado, Body Content Type = JSON
{
"customer_id": "{{ $json.customer_id }}",
"transaction_type": "sale",
"sale_date": "{{ $now.format('yyyy-MM-dd') }}",
"items": [
{
"catalog_type": "product",
"catalog_item_id": "{{ $json.product_id }}",
"quantity": {{ $json.quantity }},
"unit_price": {{ $json.unit_price }}
}
]
}

$execution.id muda a cada execução e é estável dentro dela, então a nova tentativa automática de um nó reaproveita a mesma chave. Se o mesmo workflow cria mais de um registro por execução, componha a chave com algo do item, por exemplo {{ $execution.id }}-{{ $json.id }}, para que cada registro tenha a sua.

Respostas de sucesso saem como application/json e o n8n as converte sozinho. Respostas de erro saem como application/problem+json, e esse tipo o n8n não converte: o corpo chega como texto.

Para ler type, detail e request_id de um 4xx ou 5xx, ligue Settings → On Error → Continue (using error output) no nó HTTP Request e faça o parse no ramo de erro:

Code node — ramo de erro
const bruto = $json.body ?? $json.error;
const problema = typeof bruto === 'string' ? JSON.parse(bruto) : bruto;
return [{
json: {
status: problema.status,
tipo: problema.type,
detalhe: problema.detail ?? problema.title,
request_id: problema.request_id,
},
}];
{
"type": "https://api.ligga.app/errors/validation",
"title": "Validation failed",
"status": 422,
"detail": "full_name is required",
"request_id": "req_01JZXQ8V2K5M7N9P0R1S2T3U4V"
}

Sem parse nenhum, o mesmo identificador chega pelo cabeçalho X-Request-Id. Com Options → Include Response Headers and Status ligada, use {{ $json.headers['x-request-id'] }} — é o que o time da Ligga pede para investigar uma chamada.

SintomatypeCausa
401 em todos os nósinvalid_tokenFalta Bearer (com espaço) no valor do cabeçalho, ou a chave está errada
403 ao escreverinsufficient_scopeA chave não carrega o escopo de escrita do recurso, por exemplo customers:write
403 em um recurso sómodule_not_enabledO módulo daquele recurso não está no contrato
409 ao reexecutaridempotency_conflictMesma Idempotency-Key com corpo diferente
422 ao criarvalidationCampo obrigatório ausente ou com tipo errado. Confira as aspas do JSON: quantity e unit_price são números
429 em laçorate-limit-exceededSem espera entre as voltas. Use Interval Between Requests ou um nó Wait
type e detail vaziosCorpo de erro ainda em texto: falta o parse acima

Para receber dados de um formulário ou de outro sistema e criar o registro na Ligga:

  1. Webhook — recebe a requisição do sistema de origem.

  2. Set — mapeia os campos recebidos para os nomes da Ligga, por exemplo full_name, email e phone.

  3. HTTP RequestPOST /v1/customers, com a credencial Ligga API e o cabeçalho Idempotency-Key = {{ $execution.id }}.

  4. Respond to Webhook — devolve o id criado para quem chamou.

full_name é obrigatório e pelo menos um entre email e phone precisa vir preenchido, senão a criação volta 422 validation.