Two server-to-server calls and one URL.
That is the integration. There is no SDK requirement, so the language your product is written in is not a gating question, and nothing about the capture — the camera, the chip read, the trust chain, the deletion — has to be built or audited inside your app.
The whole flow.
Three steps, and only the first and third touch your backend. Every payload on this page is illustrative — the authoritative field sets are agreed per client.
STEP 1
Your server creates a verification session.
You declare the assurance level you require and the fields you are willing to receive. The client token lives on your server and never reaches a browser or an app bundle.
Request — server side
POST /v1/verification-sessions
Authorization: Bearer <your client token>
Content-Type: application/json
{
"assurance_level": "substantial",
"age_gate_min": 18,
"return_fields": ["verified", "meets_age", "age_gate_min"],
"redirect_url": "https://your-app.example/verify/return",
"webhook_url": "https://your-app.example/hooks/jerix"
}Illustrative shape. A session is single-use and expires.
STEP 2
You send the person to the URL that came back.
This is the whole client-side integration: a redirect, or the same URL opened in a web view. Everything that follows it — capture, NFC chip read, offline trust-chain verification, face match against the photograph the issuing state itself signed, and the deletion of the images — happens on our side of it.
Response — the one URL
201 Created
{
"session_id": "vs_8K31QD…",
"url": "https://<verification-host>/s/8K31QD…",
"expires_in": 900
}Illustrative shape. There is no second client-side step and no library to keep current.
STEP 3
Your server learns the verdict.
Either we push it to a signed webhook, or you read it when the person returns. Pick by whether your backend can accept an inbound request. Never take the verdict from the browser; the redirect tells you the person came back, not what happened.
3a — read it yourself
GET /v1/verification-sessions/vs_8K31QD…
Authorization: Bearer <your client token>
200 OK
{
"verified": true,
"meets_age": true,
"age_gate_min": 18
}Illustrative shape. This is the production field set of the live integration: three fields and nothing else.
3b — or receive the signed webhook
POST /hooks/jerix (to your endpoint)
X-Jerix-Signature: v1=<hex>
X-Jerix-Timestamp: <unix seconds>
{
"session_id": "vs_8K31QD…",
"verified": true,
"meets_age": true,
"age_gate_min": 18
}Illustrative shape. Verify the signature over the raw body before you parse it, and reject a stale timestamp — that is what makes a replay useless.
Simulation — computed in this page, no network call is made
Decide how little your server receives.
Set the level you require and the fields you are willing to hold. Both plates recompute as you change them. Shapes are illustrative.
1 — your server creates the session
POST /v1/verification-sessions
Authorization: Bearer <your client token>
Content-Type: application/json
{
"assurance_level": "substantial",
"age_gate_min": 18,
"return_fields": ["verified", "meets_age", "age_gate_min"],
"redirect_url": "https://your-app.example/verify/return",
"webhook_url": "https://your-app.example/hooks/jerix"
}Because you asked for an age field, the request carries the gate. The gate is a number you choose, not a date of birth we hand back.
2 — the result your server reads
200 OK
{
"verified": true,
"meets_age": true,
"age_gate_min": 18
}Illustrative shape. Everything you did not ask for is absent — no name, no national ID number, no date of birth, no image.
A client can receive three fields and nothing else.
This is the part worth reading twice. The minimum field set is not a privacy mode you switch on — it is what a session returns when you ask for nothing more.
| Field | What it means |
|---|---|
| verified | The verdict. Whether this person is who they claimed to be. |
| meets_age | Whether the holder clears the gate you declared. Not a date of birth. |
| age_gate_min | The gate that was applied, echoed back so your own log explains itself. |
No name, no national ID number, no date of birth, no document image, no face image. Larger field sets exist and are configured per client, but a platform that only needs a gate can hold nothing but the gate.
And nothing you receive can be cross-referenced.
Tokens are isolated per client. Two platforms that verify the same person receive different tokens, and no comparison between them resolves to the same identity. The isolation is structural, not a setting, which is also why it cannot be relaxed later by an account manager.
On our side, images and biometrics are not retained — no face images, no embeddings or templates, no document images, no chip data, verified on disk.
Your runtime is not a question we need answered.
The hosted URL is the default path and it has no language requirement at all. The SDKs exist for teams that want the capture inside their own app.
A static frontend with no backend
React Native and Flutter
iOS and Android
Sign-in through an identity provider
Placing JERIX in front of an existing enterprise sign-in, as an OIDC provider.
Not shippedSSO / OIDC / Entra. The signing core ships and runs; the four endpoints do not exist yet. Until they do, integrate over REST.
Two things to design around.
An Israeli ID card is a photo-only verification.
That chip is government-locked and cannot be read at all, by us or by anyone else. There is no chip path for it, so an Israeli ID card cannot reach the levels a passport chip read earns. Plan your assurance requirements knowing that.
Liveness is measured and recorded. It does not decide.
The capture ceremony and two detectors compute on every capture and are written into the audit chain, but none of them gates a verdict today. What does the work instead is provenance: App Attest, the on-device signed capture manifest with its single-use nonce, and the state’s own signature on a passport chip.
Bring a backend. We will integrate it on the call.
Twenty minutes, a real passport, and the two calls run against a live session in front of you.
Request a walkthrough