Skip to content
Log in

Webhooks

To ensure the webhook is authentic and sent by B2Brouter, verify the signature included in the X-B2Brouter-Signature header. Here is how you can verify the signature on your server:

  1. Extract the Header Information: The X-B2Brouter-Signature header contains two components:

    • t: The UNIX timestamp when the payload was signed.
    • s: The HMAC-SHA256 signature. Example header:
    t=1732530076,s=9f117925ea533a2ea74b19699e03ab5de5664b4ff021d3d01eaff8868ed29e4d
  2. Recreate the Payload: Combine the received timestamp (t) and the raw JSON payload (data) using a period (.):

    payload = "#{timestamp}.#{data}"
  3. Compute the HMAC-SHA256 Signature: Use the shared signature_key and the payload to compute the signature:

    computed_signature = HMAC-SHA256(signature_key, payload)
  4. Compare Signatures: Compare the computed_signature with the s value from the header. If they match, the webhook is valid.

  1. PHP:
$headers = getallheaders();
$header = $headers['X-B2Brouter-Signature'];
preg_match('/t=([^,]+),s=(.+)/', $header, $matches);
$timestamp = $matches[1];
$signatureHash = $matches[2];
$recalculatedHash = hash_hmac(
'sha256',
$timestamp . '.' . file_get_contents('php://input'),
'your_webhook_secret'
);
$isValid = hash_equals($signatureHash, $recalculatedHash);
  • ledger.state_change — fired when a ledger (DGFiP Flux 10, Verifactu) transitions to a new state. See Submit a Flux-10 e-reporting file for the payload shape and the list of states.

Each event creates a delivery: B2Brouter sends a POST with the signed payload to the webhook URL.

  • A 2xx response completes the delivery.
  • If your server answers 5xx or 429, does not answer in time, or cannot be reached (DNS, connection, TLS), B2Brouter tries the delivery again later. The interval between attempts grows with each attempt, and retries continue for about one week. This period can change.
  • Any other 4xx response is final: the delivery is not tried again.

Answer 2xx as soon as you receive the webhook, and process the event afterwards. A slow answer counts as a temporary error, and the delivery is repeated.

In addition to X-B2Brouter-Signature, each attempt carries these headers:

  • X-B2Brouter-Delivery-Id: the identifier of the delivery. It is the same on all attempts of one delivery.
  • X-B2Brouter-Delivery-Attempt: the attempt number, starting at 1.

The same delivery can arrive more than once. Use X-B2Brouter-Delivery-Id to discard duplicates.

Deliveries do not always arrive in order: while one delivery waits for its retry, later events are still delivered. A webhook tells you that an object has changed. Before you act, read its current state with the API.

In the Webhooks log, each delivery shows its state and the number of attempts:

  • Retrying: the delivery failed and more attempts are scheduled.
  • Gave up: all attempts are spent.
  • Failed: your server answered with a final error (4xx).
  • Delivered: the delivery is complete.
  • Cancelled: the webhook was disabled or deleted before the delivery finished.

To repeat a delivery, open it in the log and use Resend. A resend carries the number of the last attempt in X-B2Brouter-Delivery-Attempt. The log keeps deliveries for 15 days.