ffacturifirma

Documentație

Webhooks

Primește notificări HTTP semnate în sistemele tale de fiecare dată când un document se schimbă în facturifirma.ro.

Cum înregistrezi un webhook

Din aplicație: pagina Webhooks (meniul de administrare) — adaugi URL-ul destinație și un secret de semnare. Secretul este write-only: nu mai poate fi citit după salvare.

Prin API, cu o cheie API de administrator:

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>"}'

Evenimente

În prezent se trimite un singur tip de eveniment:

document.changedorice modificare a unui document — creare, editare, emitere, încasare, stornare, anulare sau ștergere, pentru orice tip de document (factură, proformă, chitanță, aviz, comandă, storno).

Tipuri noi de evenimente vor fi adăugate în timp; tratează câmpul „event” ca extensibil și ignoră tipurile necunoscute.

Payload

Fiecare livrare este un POST cu corp JSON:

POST https://example.com/webhook

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

Headere

Fiecare request include tipul evenimentului și semnătura corpului:

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

Verificarea semnăturii

Semnătura este HMAC-SHA256 peste corpul brut al requestului, cu secretul tău de semnare, în format „sha256=<hex>”. Compar-o în timp 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));
}

Livrare și reîncercări

Livrările pleacă dintr-o coadă de joburi cu reîncercări automate (livrare at-least-once, fără garanție de ordine). Endpoint-ul tău trebuie să răspundă cu un status 2xx; orice altceva contează ca eșec și se reîncearcă.

Securitate

Sunt acceptate doar URL-uri http(s) absolute care rezolvă către adrese publice (protecție anti-SSRF). Secretul de semnare este criptat at-rest și nu este returnat niciodată de API.