Datele tale, decizia ta

Alege ce putem păstra pe dispozitivul tău

  • Niciun script de analiză sau marketing nu rulează înainte să decizi — nici măcar în fundal.
  • Fiecare categorie este o decizie separată. Acceptarea uneia nu le acceptă pe celelalte.
  • Îți poți schimba sau retrage alegerea oricând, dintr-un singur clic.

Alege ce putem păstra pe dispozitivul tău

Folosim cookie-uri esențiale pentru funcționarea platformei și, doar cu acordul tău, cookie-uri funcționale, de analiză sau de marketing. Nimic neesențial nu se încarcă fără consimțământul tău. Detalii în Politica de cookie-uri

Strict necesare

Autentificare, securitate (CSRF), preferință de limbă și temă, reținerea alegerii tale privind consimțământul. Întotdeauna active.

Funcționale

Rețin preferințe suplimentare (ex. setări de afișare) pentru o experiență îmbunătățită.

Analiză

Ne ajută să înțelegem cum este folosit site-ul (statistici agregate). Nu se încarcă fără acordul tău.

Marketing

Folosite pentru publicitate personalizată de către terți. Nu se încarcă fără acordul tău.

Brivio Developers
Create accountSign in
OverviewQuickstartAuthenticationIdempotencyWebhooksErrors & sandboxSDKs & CLIMCP serverOAuth2 appsAPI reference

Webhooks

Signed, retried HTTP callbacks for business events — invoices, e-Factura status, orders, contracts and more.

Subscribe

curl
curl -X POST https://api.brivio.ro/v1/webhooks \
  -H "Authorization: Bearer brivio_sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/hooks/brivio",
    "events": ["invoice.created", "invoice.paid", "efactura.validated", "efactura.rejected"]
  }'

The response includes a secret (shown once) used to sign every delivery. List available event types at GET /v1/webhooks/events.

Verify signatures

Brivio implements the Standard Webhooks specification, so a verifier you already wrote for another provider works unchanged. Every delivery carries three headers:

webhook-id:        evt_0f3c…            unique per event — use it to deduplicate
webhook-timestamp: 1788153475           unix SECONDS
webhook-signature: v1,<base64> v1,<b64> space-separated list

The signature is HMAC-SHA256 over {webhook-id}.{webhook-timestamp}.{rawBody}. The timestamp is inside the signed content, so a captured delivery cannot be replayed by rewriting it — reject anything older than about five minutes.

Always verify against the raw body. Re-serialising parsed JSON changes the bytes and the signature will not match.

TypeScript
import { createHmac, timingSafeEqual } from "node:crypto";

function verify(rawBody: string, headers: Record<string, string>, secrets: string[]) {
  const id = headers["webhook-id"];
  const ts = Number(headers["webhook-timestamp"]);
  if (!id || !Number.isInteger(ts)) return false;
  if (Math.abs(Date.now() / 1000 - ts) > 300) return false; // replay window

  const presented = (headers["webhook-signature"] ?? "").split(" ");
  for (const secret of secrets) {
    const key = Buffer.from(secret.replace(/^whsec_/, ""), "base64");
    const mac = createHmac("sha256", key).update(`${id}.${ts}.${rawBody}`).digest("base64");
    const expected = Buffer.from(`v1,${mac}`);
    for (const token of presented) {
      const actual = Buffer.from(token);
      if (expected.length === actual.length && timingSafeEqual(expected, actual)) return true;
    }
  }
  return false;
}

// Or simply:  import { verifyWebhookSignature } from "@brivio-ro/sdk";

Rotating a secret without downtime

Rotating opens a 24-hour overlap window. During it every delivery is signed with both the old and the new secret, and webhook-signature carries one v1,… token per secret. Accept the delivery if any token verifies — pass both secrets to your verifier — and you can redeploy at your own pace without dropping an event. After the window the old secret stops signing.

Delivery & retries

Return 2xx within 3 seconds. Anything else — a non-2xx status, a timeout, a connection error — counts as a failed attempt. Do your real work asynchronously and acknowledge immediately; a slow consumer is indistinguishable from a broken one.

This is the published retry schedule. 10 attempts in total (the first delivery plus 9 retries), spanning roughly 19 hours:

10s · 20s · 30s · 5m · 20m · 2h · 4h · 6h · 6h

After the last rung a delivery is marked dead and never retried automatically. 410 Gone is treated as a deliberate retirement and stops retries immediately. Endpoints that keep failing are disabled and can be re-enabled from the dashboard. Any delivery from the last 31 days can be replayed from the dashboard or with POST /v1/webhooks/:id/deliveries/:deliveryId/redeliver.

Webhooks are lossy — reconcile daily

Do not treat webhooks as your only source of truth. They are a latency optimisation, not a guaranteed log. Deliveries are lost when your endpoint is down longer than the retry ladder, when it is auto-disabled after repeated failures, when a deploy drops in-flight requests, or when your handler returns 2xx and then crashes before committing.

Run a reconciliation sweep at least daily: list the resources you care about with an updated_after filter and apply anything you have not already processed. Deduplicate on webhook-id, which is stable across retries and redeliveries, and make your handler idempotent — the same event can legitimately arrive more than once.

All events

addendum.created                  affiliate.commission.accrued      affiliate.commission.available
affiliate.enrolled                affiliate.payout.paid             affiliate.referral.created
article.created                   article.deleted                   article.updated
booking.cancelled                 booking.confirmed                 change_request.approved
change_request.created            contact.created                   contact.deleted
contact.fiscal_status_changed     contact.updated                   contract.created
contract.deleted                  contract.signed                   contract.suspended
contract.updated                  contract_obligation.deleted       contract_obligation.updated
court_case.hearing_added          delivery_route.dispatched         dispute.lost
dispute.opened                    document.created                  document.deleted
document.updated                  efactura.rejected                 efactura.submitted
efactura.validated                email.bounced                     email.complained
email.delivered                   email.received                    email.sent
email.suppressed                  expense.created                   expense.deleted
expense.updated                   export.completed                  fidic.ipc.certified
fixed_asset.created               fixed_asset.disposed              fleet_vehicle.created
fleet_vehicle.deleted             fleet_vehicle.updated             import.completed
invoice.cancelled                 invoice.created                   invoice.credited
invoice.deleted                   invoice.overdue                   invoice.paid
invoice.partially_paid            invoice.payment_recorded          invoice.payment_reversed
invoice.sent                      invoice.updated                   marketing.campaign.sent
milestone.accepted                milestone.delivered               milestone.rejected
order.created                     order.paid                        payment.failed
payment.refunded                  payment.succeeded                 payout.failed
payout.paid                       project.created                   project.deleted
project.updated                   restaurant.order.placed           reward.earned
reward.expired                    reward.member.level_up            reward.redeemed
reward.reversed                   saft_generation.completed         stock.below_minimum
subscription.activated            subscription.canceled             subscription.updated
trust.batch.completed             trust.batch.failed                trust.provider.health_changed
trust.signature.completed         trust.signature.failed            trust.timestamp.completed
trust.validation.completed        work_certificate.confirmed

Payload shape

{
  "id": "evt_...",            // unique delivery id (X-Brivio-Delivery)
  "type": "efactura.validated",
  "created_at": "2026-08-01T10:00:00Z",
  "data": { "invoice_id": "...", "efactura_id": "...", "stare": "ok" }
}

Deliveries are at-least-once — deduplicate on the delivery id if your handler isn't idempotent.