Cairos
Facturació
Programa de facturacióPressupostosFactures recurrentsDespeses i proveïdorsCobraments i tresoreria
Comptabilitat i impostos
ComptabilitatModels d'HisendaLlibres registreImmobilitzatIGIC i Canàries
Operacions
Inventari i magatzemsCRMControl horariProjectesSubvencions i ajuts
Compliment
VeriFactuTicketBAIFactura electrònicaTota la normativaSeguretat i dades
Per tipus de negoci
AutònomsPimesAssessories i gestoriesEstrangers a EspanyaStartupsComerços i botigues
Per sector
Hostaleria i restaurantsConstrucció i reformesServeis professionalsComerç electrònicTots els sectors
Per forma jurídica
AssociacionsFundacionsCooperativesClubs esportiusTotes les formes jurídiques
Canviar de programa
ComparativesAlternativa a HoldedMigrar les teves dades
Eines gratis
Plantilla de facturaCalculadora d'IVACalculadora d'IRPFTotes les eines
Aprendre
GuiesGlossariCalendari fiscalBlog
Desenvolupadors
API i documentacióComença en cinc minutsReferència de recursosWebhooks
Ajuda
Centre d'ajudaContacte
Preus
Comença gratis Inicia la sessió
Automatització

n8n: HTTP Request per cridar i Code per verificar

Tampoc no hi ha node oficial, i aquí importa menys que enlloc: n8n té un node de codi, i això és el que cal per comprovar la signatura d'un webhook abans de fiar-se'n.

Credencial Header AuthSignatura comprovada en un node CodePaginació per cursor

L'API està en marxa. Això és el que hi ha avui i el que no

Funciona. Les rutes d'aquesta documentació estan desplegades i responent a https://erp.cairos.es/api/v1/. Els exemples d'aquestes pàgines es poden copiar i executar. L'especificació completa és a openapi.json, que és el que importen Make i n8n.

Les claus te les crees tu, des de Desenvolupadors al teu compte de Cairos. Comença amb una cai_test_: treballa contra les teves dades de veritat però no registra a VeriFactu ni envia correus, així que pots muntar la teva integració sense embrutar una sèrie de facturació.

I el que encara NO hi ha, dit sense adorns: cap connector oficial. Ni app de Shopify, ni plugin de WooCommerce, ni mòdul publicat a Make o n8n. Amb l'API i la seva especificació es poden construir —per això hi ha les guies d'aquesta secció— però construir-los és feina, i aquesta feina no està feta.

Si muntes alguna cosa amb això, escriu-nos a hola@cairos.es. Ens interessa especialment el que et falti del contracte: és el que decideix què s'amplia primer.

No hi ha node oficial de Cairos a n8n

No està publicat i no hi ha data. El que hi ha és l'API —amb la seva llista d'esdeveniments, la seva OpenAPI i els seus webhooks— i aquesta pàgina, que et diu exactament què connectar i amb quin codi. Dins de Cairos hi ha, a més, receptes ja muntades i un flux d'n8n descarregable, a API i integracions → Comença.

Si la teva botiga és de PrestaShop, aquest és el teu camí

Cairos connecta només amb Shopify, WooCommerce i Odoo. Amb PrestaShop encara no, i està a mitges a propòsit: el tipus d'IVA de cada línia no ve a la línia —cal resoldre'l contra dos recursos més de la seva API—, els cupons són un recurs a part que s'aplica a la comanda i no a les línies, i cada botiga anomena d'una manera diferent l'estat que significa «venut», perquè aquests estats els edita el comerciant. Facturar tres de cada quatre comandes i inventar-se l'IVA de la quarta és pitjor que dir que no: el «no» es veu el primer dia i l'IVA mal posat es veu al 303.

Mentrestant, les seves comandes entren perfectament per aquí: PrestaShop sap avisar una adreça quan entra una comanda, i el que hi ha a sota és exactament el mateix recorregut que explica aquesta pàgina.

La credencial, que es munta un sol cop

n8n no té node de Cairos, i no cal: el node HTTP Request crida qualsevol API. El que sí que convé muntar bé des del principi és la credencial, per no repetir la clau a cada node ni deixar-la escrita al flux.

Es crea una credencial de tipus Header Auth amb aquests dos valors:

Credencial Header Auth
Name:  Authorization
Value: Bearer cai_live_TU_CLAVE

A partir d'aquí, cada node HTTP Request fa servir aquesta credencial i no torna a saber res de la clau. Quan la rotis, es canvia en un sol lloc.

Cridar Cairos

Un node HTTP Request per operació. El que cal omplir és sempre el mateix:

Camp del nodeValor
MethodPOST
URLhttps://erp.cairos.es/api/v1/facturas
AuthenticationGenèrica, amb la credencial Header Auth de dalt
Send BodyActivat, en JSON
HeadersIdempotency-Key, amb l'identificador de la comanda del node anterior

I activa el reintent del mateix node només si has posat la clau d'idempotència. Un reintent d'un POST sense clau és la manera més ràpida d'acabar amb dues factures.

El cos, en mode JSON, amb les expressions d'n8n per prendre les dades del node 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
    }
  ]
}

Els noms van tal qual: fecha_emision, descripcion i tipo_iva. Un camp que no existeix no s'ignora, retorna 422 i el nomena a error.detalles.campos, així que aquest és el primer lloc on mirar quan el node es posa vermell.

Rebre esdeveniments de Cairos, que és on n8n brilla

Aquí és on n8n guanya les alternatives sense codi: té un node de codi on es pot comprovar la signatura d'un webhook, que és l'única cosa que no és negociable en obrir un extrem públic.

El muntatge són tres nodes:

#NodeQuè fa
1WebhookRep el POST de Cairos. Cal activar l'opció de cos sense processar: sense ella no es pot comprovar la signatura.
2CodeComprova la signatura amb el secret de la subscripció i talla si no quadra.
3El que vulguisAvisar per Slack, escriure en un full, actualitzar la comanda a la teva botiga.
Node Code · comprovar la signatura
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) }];

Com es calcula aquesta signatura i per què la marca de temps va a dins és a webhooks. I l'adreça que et dóna el node Webhook és la que es registra amb POST /webhooks.

Recórrer llistes llargues

Per llegir totes les factures d'un any no serveix una sola crida: l'API pagina amb cursor. I aquí n8n ho posa fàcil, perquè siguiente ja és la URL sencera de la pàgina que segueix, amb els teus filtres a dins: no cal recompondre cap consulta.

  • Demana amb ?limite=200&orden=antiguo, que és l'ordre que no es mou mentre el recorres.
  • Agafa siguiente de la resposta i fes-lo servir com a URL tal qual. No és l'id de l'últim element ni un cursor que s'hagi d'enganxar a mà a ?desde=: és l'adreça completa.
  • Para quan siguiente vingui a null, no quan datos vingui buit.

Al paginat del mateix node HTTP Request això es configura amb el mode de «següent URL» i l'expressió {{ $response.body.siguiente }}, i la condició d'aturada és que aquest camp sigui nul.

El detall de la paginació, amb el bucle escrit en JavaScript i en PHP, és a errors i paginació.

Preguntes sobre n8n

No. Es fa servir el node HTTP Request amb una credencial de tipus Header Auth. Per a tot el que descriu aquesta documentació, n'hi ha prou.
Amb una credencial Header Auth: nom Authorization i valor Bearer més la clau. Els nodes la referencien i no la contenen, així que en rotar-la es canvia en un sol lloc.
Sí, i és on n8n va millor que les alternatives sense codi: node Webhook amb l'opció de cos sense processar activada, i un node Code que comprova la signatura HMAC abans de continuar.
Gairebé sempre perquè estàs signant contra el JSON ja convertit a objecte i tornat a serialitzar, que no és idèntic al que va arribar. Cal activar el cos sense processar al node Webhook i signar contra això.
Sí, però només si envies Idempotency-Key. Un reintent d'un POST sense clau és exactament com s'acaba amb dues factures de la mateixa comanda.
Sí, i avui és el camí. Cairos connecta sol amb Shopify, WooCommerce i Odoo; amb PrestaShop encara no, perquè la seva API no deixa deduir amb seguretat el tipus d'IVA de cada línia ni els cupons. Amb el webhook de comanda de PrestaShop entrant al node Webhook i el recorregut d'aquesta pàgina, la comanda acaba en una factura emesa igualment.
Sí, i es descarrega des del mateix Cairos: API i integracions → Comença. Porta els nodes i les connexions fetes, i la clau no va dins del fitxer: en importar-lo, n8n et demana crear la credencial i aquí és on s'enganxa, una sola vegada.

Munta el flux i omple la credencial

Les rutes, les capçaleres i la signatura són les que fa servir el servidor avui. La clau te la crees tu des del teu compte, i amb una de proves pots llançar el flux sense embrutar res.

HTTP Request · Header Auth · Cos sense processar al Webhook

Suport