IDfier Developers

Webhooks

Get told when a login session is scanned, approved or denied, instead of polling.

Set a webhook when you create a login session:

POST /business/auth/request
{
  "webhookUrl": "https://example.com/idfier/webhook",
  "webhookSecret": "a-random-string-of-at-least-16-characters"
}
FieldDescription
webhookUrlAn https URL, at most 500 characters
webhookSecretRequired with webhookUrl, 16–255 characters; signs each event

Events

IDfier POSTs JSON to your URL:

{ "event": "authentication.completed", "referenceId": "550e8400-…", "status": "approved" }
eventstatusWhen
authentication.startedstartedThe customer scanned the QR code
authentication.completedapprovedThe customer approved. From an EU wallet, the event also has "method": "eudi_wallet"
authentication.denieddeniedThe customer declined

An event never contains the customer's data. Fetch it with POST /business/auth/result, as you would when polling, and keep the browser binding of your login flow.

Verify the signature

Each request has an x-idfier-signature: sha256=<hex> header: the HMAC-SHA256 of the raw request body with your webhookSecret. Check it before trusting the event:

import { createHmac, timingSafeEqual } from 'node:crypto';

export function isFromIdfier(rawBody: string, header: string | null, secret: string) {
  const expected = `sha256=${createHmac('sha256', secret).update(rawBody).digest('hex')}`;
  return header !== null && header.length === expected.length && timingSafeEqual(Buffer.from(header), Buffer.from(expected));
}

Compute it over the body exactly as received, before parsing the JSON.

Delivery

  • Answer with a 2xx within 15 seconds.
  • On a timeout, a network error or a 5xx, IDfier tries again after 2 and 4 seconds: at most 3 attempts in all. A 4xx is not retried.
  • Events can arrive late or not at all, so treat them as a hint: the result endpoint is the source of truth, and polling is a fine fallback.

On this page