IDfier Logo
IDfier for Business · Developers

Verified identity in two API calls.

Create a session, show a QR code, and fetch the verified details your customer approves. The same API powers Login with IDfier and age verification.

POST
/business/auth/requestCreate a session
QR
idfier.{referenceId}.{qrTime}.{qrAuthCode}Show a signed QR code
POST
/business/auth/resultFetch the result
Base URL https://api.idfier.com/api/v3
Before you start

What you need

No SDK to install. If your backend can make an HTTPS request and your page can show a QR code, you can integrate IDfier.

API credentials

A client ID and client secret for your business account. Keep the secret on your server.

A backend

Any server that can make HTTPS requests. Both endpoints are called from your backend.

A place for the QR code

Your login, sign-up or checkout page, where the customer scans the code with the IDfier app.

Quickstart

From zero to a verified login

Authenticate every request with your client ID and secret in the clientid and clientsecret headers.

1

Create a session

Call this when the customer starts signing in. You get a referenceId for the session and a qrReferenceSecret to sign the QR code. The session is valid for five minutes.

POST /business/auth/request
curl -X POST https://api.idfier.com/api/v3/business/auth/request \
  -H "clientid: $IDFIER_CLIENT_ID" \
  -H "clientsecret: $IDFIER_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{}'
Response
{
  "status": 100,
  "data": {
    "referenceId": "550e8400-e29b-41d4-a716-446655440000",
    "qrReferenceSecret": "abc123",
    "createdAt": "2026-03-12T10:00:00.000Z"
  }
}
2

Show the QR code

Build the QR payload from the session and redraw it every ~2 seconds. Each payload is signed with HMAC-SHA256 and expires quickly, so an old screenshot of the code won't work.

On a phone, skip the QR code and open the IDfier app with the idfier://auth deep link instead.

QR payload
import crypto from "node:crypto";

// Call every ~2 seconds and re-render the QR code
export function qrPayload({ referenceId, qrReferenceSecret, createdAt }) {
  const qrTime = String(
    Math.floor((Date.now() - new Date(createdAt).getTime()) / 1000)
  );
  const key = crypto.createHash("sha256").update(qrReferenceSecret).digest();
  const qrAuthCode = crypto
    .createHmac("sha256", key)
    .update(qrTime)
    .digest("hex");

  return `idfier.${referenceId}.${qrTime}.${qrAuthCode}`;
}
3

Fetch the result

Poll until the customer has approved. The user object contains only the fields your business account is set up for, plus a stable id you can store.

POST /business/auth/result
curl -X POST https://api.idfier.com/api/v3/business/auth/result \
  -H "clientid: $IDFIER_CLIENT_ID" \
  -H "clientsecret: $IDFIER_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"referenceId": "550e8400-e29b-41d4-a716-446655440000"}'
Response (approved)
{
  "status": 100,
  "data": {
    "user": {
      "id": "u_8f3k2…",
      "fullname": "Anna Lindqvist",
      "email": "anna.lindqvist@outlook.com",
      "authLevel": "Gold"
    },
    "session": {
      "referenceId": "550e8400-e29b-41d4-a716-446655440000",
      "status": "approved",
      "expiresAt": "2026-03-12T10:05:00.000Z",
      "createdAt": "2026-03-12T10:00:00.000Z"
    }
  }
}
4

Sign the customer in

Once approved, the customer is a verified person. Create or update their account in your system and sign them in as you normally would.

Use user.id to find or create the account, save the verified details you need, and start your own session or token. IDfier doesn't manage your sessions.
API explorer

Build your request

Pick the fields you need and a language. Get the scopes to set up on your account, ready-to-copy code for every step, and the response you'll receive.

1. Choose the fields you need

Age rule

2. Scopes for your business account

ageOver18,fullname,email

Scopes are set on your business account when we set up your API access, not sent with each request. Every response then contains only these fields plus a stable id. Age limit and range scopes are Coming soon.

9:41
IDfier
H

Hemly

hemly.se

wants to verify the following details from your IDfier identity:

Full nameAnna Lindqvist
Emailanna.lindqvist@outlook.com
Age over 18Yes

Deny

3. Make the requests

async function waitForUser(referenceId) {
  for (let delay = 2000; ; delay = Math.min(delay * 1.5, 10000)) {
    const res = await fetch("https://api.idfier.com/api/v3/business/auth/result", {
      method: "POST",
      headers: {
        clientid: process.env.IDFIER_CLIENT_ID,
        clientsecret: process.env.IDFIER_CLIENT_SECRET,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ referenceId }),
    });
    const { data } = await res.json();
    const { status, expiresAt } = data.session;

    if (status === "approved") return data.user;
    if (status === "denied" || status === "error") throw new Error(status);
    if (new Date(expiresAt) < new Date()) throw new Error("expired");
    await new Promise((r) => setTimeout(r, delay));
  }
}

const user = await waitForUser(referenceId);
const { id, ageOver18, fullname, email } = user;

Replace $IDFIER_CLIENT_ID and $IDFIER_CLIENT_SECRET with your credentials. Keep the secret on your server.

Reference

Statuses, fields and errors

Session statuses

StatusMeaningWhat to do
pendingWaiting for the customer to scan the QR codeKeep polling
startedThe QR code has been scannedKeep polling
approvedThe customer approved and verified data is availableSign the customer in
deniedThe customer declinedStop and offer another way in
errorAuthentication failedStop and show an error

Data fields (scopes)

Scopes are configured on your business account. Each scope returns the field with the same name. id is always included.

ScopeTypeDescription
fullnamestringFull name
displayNamestringPreferred display name
emailstringEmail address
handlestringIDfier handle
personalNostringSwedish personal identity number
dateOfBirthstringDate of birth
agenumberAge, calculated from date of birth
ageOver13 / 16 / 18 / 21 / 65Coming soonbooleanYes or no for the age limit, without the birth date
ageBetween{min}And{max}Coming soonbooleanYes or no for an inclusive age range, e.g. ageBetween18And25, without the birth date
countrystringCountry
nationalitystringNationality from the ID document
genderstringGender from the ID document or personal number
documentTypestringType of ID document used
authLevelstringVerification level: Bronze, Silver or Gold
authMethodIdnumberVerification method (1 = BankID, 2 = document scan)

Errors

HTTPMeaningExample body
400Bad request, for example a missing referenceId{ "error": "Missing referenceId" }
401Invalid client ID or client secret{ "success": false, "message": "Unauthorized: …" }
404Session or business client not found{ "error": "Session not found" }
500Server error; retry with backoff{ "error": "Database error" }
Good to know

Best practices

Refresh the QR code every ~2 seconds

Old payloads stop working after about 10 seconds, so screenshots can't be reused.

Poll with backoff

Start at 2–3 seconds and slow down over time to reduce load.

Sessions last five minutes

When expiresAt has passed, create a new session and a new QR code.

Issue your own session

After approval, create or update the account in your system and sign the customer in as usual.

One integration

Built on the same API

Choose the scopes for your use case. The flow above stays the same.

Ready to build?

Get your API credentials

Tell us about your use case and we'll set up your business account and scopes.

Request API access