Cairos
Facturación
Programa de facturaciónOrzamentosFacturas recorrentesGastos e provedoresCobros e tesouraría
Contabilidade e impostos
ContabilidadeModelos de FacendaLibros rexistroInmobilizadoIGIC e Canarias
Operacións
Inventario e almacénsCRMControl horarioProxectosSubvencións e axudas
Cumprimento
VeriFactuTicketBAIFactura electrónicaToda a normativaSeguridade e datos
Por tipo de negocio
AutónomosPemesAsesorías e xestoríasEstranxeiros en EspañaStartupsComercios e tendas
Por sector
Hostalaría e restaurantesConstrución e reformasServizos profesionaisComercio electrónicoTodos os sectores
Por forma xurídica
AsociaciónsFundaciónsCooperativasClubs deportivosTodas as formas xurídicas
Cambiar de programa
ComparativasAlternativa a HoldedMigrar os teus datos
Ferramentas gratis
Modelo de facturaCalculadora de IVECalculadora de IRPFTodas as ferramentas
Aprender
GuíasGlosarioCalendario fiscalBlog
Desenvolvedores
API e documentaciónComezar en cinco minutosReferencia de recursosWebhooks
Axuda
Centro de axudaContacto
Prezos
Comeza gratis Iniciar sesión
Automatización

n8n: HTTP Request para chamar e Code para verificar

Tampouco hai nodo oficial, e aquí importa menos ca en ningún sitio: n8n ten un nodo de código, e iso é o que fai falta para comprobar a sinatura dun webhook antes de fiarse del.

Credencial Header AuthSinatura comprobada nun nodo CodePaxinación por cursor

A API está en marcha. Isto é o que hai hoxe e o que non

Funciona. As rutas desta documentación están despregadas e respondendo en https://erp.cairos.es/api/v1/. Os exemplos destas páxinas pódense copiar e executar. A especificación completa está en openapi.json, que é o que importan Make e n8n.

As claves créalas ti, desde Desenvolvedores na túa conta de Cairos. Comeza cunha cai_test_: traballa contra os teus datos de verdade pero non rexistra en VeriFactu nin envía correos, así que podes montar a túa integración sen enlixar unha serie de facturación.

E o que aínda NON hai, dito sen adornos: ningún conector oficial. Nin app de Shopify, nin plugin de WooCommerce, nin módulo publicado en Make ou n8n. Coa API e a súa especificación pódense construír —para iso están as guías desta sección— pero construílos é traballo, e ese traballo non está feito.

Se montas algo con isto, escríbenos a hola@cairos.es. Interésanos especialmente o que che falte do contrato: é o que decide que se amplía primeiro.

Non hai nodo oficial de Cairos en n8n

Non está publicado e non hai data. O que hai é a API —coa súa lista de eventos, o seu OpenAPI e os seus webhooks— e esta páxina, que che di exactamente que enganchar e con que código. Dentro de Cairos hai ademais receitas xa montadas e un fluxo de n8n descargable, en API e integracións → Comezar.

Se a túa tenda é de PrestaShop, este é o teu camiño

Cairos conecta só con Shopify, WooCommerce e Odoo. Con PrestaShop aínda non, e está a medias a propósito: o tipo de IVE de cada liña non vén na liña —hai que resolvelo contra outros dous recursos da súa API—, os cupóns son un recurso aparte que se aplica ao pedido e non ás liñas, e cada tenda chámalle dun xeito distinto ao estado que significa «vendido», porque eses estados edítaos o comerciante. Facturar tres de cada catro pedidos e inventar o IVE do cuarto é peor ca dicir que non: o «non» vese o primeiro día e o IVE mal posto vese no 303.

Mentres tanto, os seus pedidos entran perfectamente por aquí: PrestaShop sabe avisar a un enderezo cando entra un pedido, e o que hai debaixo é exactamente o mesmo percorrido que conta esta páxina.

A credencial, que se monta unha vez

n8n non ten nodo de Cairos, e non fai falta: o nodo HTTP Request chama a calquera API. O que si convén montar ben desde o principio é a credencial, para non repetir a clave en cada nodo nin deixala escrita no fluxo.

Créase unha credencial de tipo Header Auth con estes dous valores:

Credencial Header Auth
Name:  Authorization
Value: Bearer cai_live_TU_CLAVE

A partir de aí, cada nodo HTTP Request usa esa credencial e non volve saber nada da clave. Cando a rotes, cámbiase nun sitio.

Chamar a Cairos

Un nodo HTTP Request por operación. O que hai que cubrir é sempre o mesmo:

Campo do nodoValor
MethodPOST
URLhttps://erp.cairos.es/api/v1/facturas
AuthenticationXenérica, coa credencial Header Auth de arriba
Send BodyActivado, en JSON
HeadersIdempotency-Key, co identificador do pedido do nodo anterior

E activa o reintento do propio nodo só se puxeches a chave de idempotencia. Un reintento dun POST sen chave é a forma máis rápida de acabar con dúas facturas.

O corpo, en modo JSON, coas expresións de n8n para tomar os datos do nodo anterior:

Body · JSON
{
  "contacto_id": "{{ $json.id }}",
  "serie": "WEB",
  "fecha_emision": "{{ $now.format('yyyy-MM-dd') }}",
  "lineas": [
    {
      "descripcion": "{{ $('Pedido').item.json.titulo }}",
      "cantidad": 1,
      "precio": 180.00,
      "tipo_iva": 21
    }
  ]
}

Os nomes van tal cal: fecha_emision, descripcion e tipo_iva. Un campo que non existe non se ignora, devolve 422 e noméao en error.detalles.campos, así que ese é o primeiro sitio onde mirar cando o nodo se pon vermello.

Recibir sucesos de Cairos, que é onde n8n brilla

Aquí é onde n8n gaña ás alternativas sen código: ten un nodo de código onde se pode comprobar a sinatura dun webhook, que é o único que non é negociable ao abrir un extremo público.

A montaxe son tres nodos:

#NodoQue fai
1WebhookRecibe o POST de Cairos. Hai que activar a opción de corpo sen procesar: sen ela non se pode comprobar a sinatura.
2CodeComproba a sinatura co segredo da subscrición e corta se non cadra.
3O que queirasAvisar por Slack, escribir nunha folla, actualizar o pedido na túa tenda.
Nodo Code · comprobar a sinatura
const crypto = require("crypto");

const secreto = $env.CAIROS_SECRETO;
const entrada = $input.first().json;

// El cuerpo CRUDO, tal y como llegó. Si aquí usas el JSON ya
// convertido, la firma no cuadrará nunca y perderás una tarde.
const crudo = entrada.rawBody || entrada.body;
// La cabecera se llama "x-cairos-firma", en minuscula.
const cabecera = entrada.headers["x-cairos-firma"] || "";

const partes = Object.fromEntries(
  cabecera.split(",").map((t) => t.trim().split("="))
);

const ahora = Math.floor(Date.now() / 1000);
if (!partes.t || Math.abs(ahora - Number(partes.t)) > 300) {
  throw new Error("Suceso caducado o sin marca de tiempo");
}

const esperada = crypto
  .createHmac("sha256", secreto)
  .update(partes.t + "." + crudo)
  .digest("hex");

if (esperada !== partes.v1) {
  throw new Error("Firma no valida");
}

return [{ json: JSON.parse(crudo) }];

Como se calcula esa sinatura e por que a marca de tempo vai dentro está en webhooks. E o enderezo que che dá o nodo Webhook é o que se rexistra con POST /webhooks.

Percorrer listas longas

Para ler todas as facturas dun ano non vale unha soa chamada: a API paxina con cursor. E aquí n8n ponno fácil, porque siguiente xa é a URL enteira da páxina que segue, cos teus filtros dentro: non hai que recompoñer ningunha consulta.

  • Pide con ?limite=200&orden=antiguo, que é a orde que non se move mentres percorres.
  • Colle siguiente da resposta e úsao como URL tal cal. Non é o id do último elemento nin un cursor que haxa que pegar a man en ?desde=: é o enderezo completo.
  • Para cando siguiente veña a null, non cando datos veña baleiro.

Na paxinación do propio nodo HTTP Request iso configúrase co modo de «seguinte URL» e a expresión {{ $response.body.siguiente }}, e a condición de parada é que ese campo sexa nulo.

O detalle da paxinación, co bucle escrito en JavaScript e en PHP, está en erros e paxinación.

Preguntas sobre n8n

Non. Úsase o nodo HTTP Request cunha credencial de tipo Header Auth. Para todo o que describe esta documentación, abonda.
Cunha credencial Header Auth: nome Authorization e valor Bearer máis a clave. Os nodos referéncianna e non a conteñen, así que ao rotala cámbiase nun sitio.
Si, e é onde n8n vai mellor ca as alternativas sen código: nodo Webhook coa opción de corpo sen procesar activada, e un nodo Code que comproba a sinatura HMAC antes de seguir.
Case sempre porque estás asinando contra o JSON xa convertido a obxecto e volto a serializar, que non é idéntico ao que chegou. Hai que activar o corpo sen procesar no nodo Webhook e asinar contra iso.
Si, pero só se mandas Idempotency-Key. Un reintento dun POST sen chave é exactamente como se acaba con dúas facturas do mesmo pedido.
Si, e hoxe é o camiño. Cairos conecta só con Shopify, WooCommerce e Odoo; con PrestaShop aínda non, porque a súa API non deixa deducir con seguridade o tipo de IVE de cada liña nin os cupóns. Co webhook de pedido de PrestaShop entrando no nodo Webhook e o percorrido desta páxina, o pedido acaba nunha factura emitida igual.
Si, e descárgase desde o propio Cairos: API e integracións → Comezar. Trae os nodos e as conexións feitas, e a clave non vai dentro do ficheiro: ao importalo, n8n pídeche crear a credencial e aí é onde se pega, unha soa vez.

Monta o fluxo e cobre a credencial

As rutas, as cabeceiras e a sinatura son as que usa o servidor hoxe. A clave créala ti desde a túa conta, e cunha de probas podes lanzar o fluxo sen enlixar nada.

HTTP Request · Header Auth · Corpo sen procesar no Webhook

Soporte