ffacturifirma

Documentation

Webhooks

Recevez des notifications HTTP signées dans vos systèmes à chaque changement de document dans facturifirma.ro.

Enregistrer un webhook

Depuis l'app : page Webhooks (menu d'administration) — ajoutez l'URL cible et un secret de signature. Le secret est write-only : illisible après l'enregistrement.

Via l'API, avec une clé API administrateur :

curl -X POST https://app.facturifirma.ro/api/v1/webhooks \
  -H "Authorization: Bearer <API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/webhook", "secret": "<SIGNING_SECRET>"}'

Événements

Un seul type d'événement est actuellement envoyé :

document.changedtout changement d'un document — création, modification, émission, encaissement, avoir, annulation ou suppression, pour chaque type de document (facture, proforma, reçu, bon de livraison, commande, avoir).

De nouveaux types d'événements seront ajoutés ; traitez le champ « event » comme extensible et ignorez les types inconnus.

Payload

Chaque livraison est un POST avec un corps JSON :

POST https://example.com/webhook

{
  "event": "document.changed",
  "documentId": "8b1f7c02-4c33-4a6e-9f0d-2f6f6f0a9d11",
  "at": "2026-07-15T09:30:00Z"
}

En-têtes

Chaque requête porte le type d'événement et la signature du corps :

Content-Type: application/json
X-Facturifirma-Event: document.changed
X-Facturifirma-Signature: sha256=<hex(HMAC-SHA256(secret, body))>

Vérifier la signature

La signature est un HMAC-SHA256 du corps brut de la requête avec votre secret, au format « sha256=<hex> ». Comparez-la en temps constant :

import crypto from "node:crypto";

function verify(rawBody, signatureHeader, secret) {
  const expected = "sha256=" +
    crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(signatureHeader), Buffer.from(expected));
}

Livraison et réessais

Les livraisons partent d'une file de jobs avec réessais automatiques (at-least-once, sans garantie d'ordre). Votre endpoint doit répondre 2xx ; toute autre réponse compte comme un échec et est réessayée.

Sécurité

Seules les URLs http(s) absolues résolvant vers des adresses publiques sont acceptées (protection SSRF). Le secret de signature est chiffré au repos et jamais renvoyé par l'API.