Integration Architecture
This page applies to both API versions. It is the shape of a correct integration, before any endpoint detail.
Your backend is the gateway
End-user device Your backend Biometry API┌──────────────┐ ┌──────────────────┐ ┌───────────────┐│ Browser / │ │ │ │ ││ Mobile app │─────>│ Your server │────>│ Biometry ││ │<─────│ (API token │<────│ API Gateway ││ (SDK) │ │ stored here) │ │ │└──────────────┘ └──────────────────┘ └───────────────┘Why this matters:
- Token security — the token never leaves your backend.
- Request validation — your backend can sanitise input before forwarding it.
- Rate control — you enforce your own limits and business rules (e.g. only authenticated users may submit a check).
- Audit trail — your logs record what was sent and when, alongside the
request_idBiometry returns.
Two credentials, not one
| Credential | Who holds it | What it opens |
|---|---|---|
| Project API token | Your backend | Verification, enrollment, documents, deepfake checks, sessions, consent records, transaction queries |
| Console user session | A person logged into the Console | Configuration: scoring systems, webhooks, consent documents, project and member management, user deletion |
They are not interchangeable. An endpoint that needs a Console session rejects
an API token with 401, and no API call will mint you a Console session. If a
task needs configuration, it belongs in the Console or in tooling that
authenticates as a Console user — not in your integration.
See API Token for how tokens are issued and scoped.
Who owns which identifier
user_id(v2) /X-User-Fullname(v1) — you choose it, and it is the same value in both versions. Use your own primary key, a UUID, or a hash. Never a person’s name: it is the key consent, enrollment and history are filed under, and it ends up in your own dashboards. It is unique per project.session_id— created by Biometry, held by you for the duration of one verification attempt. Pass it on every call in that attempt so the Console shows them as one unit.- API token — one per application, ideally, so you can revoke a single integration without disturbing the others.
Capture on the client, call from the server
The SDKs are capture tools: they handle camera, microphone, framing and quality on the end-user’s device. The captured file goes to your backend, which forwards it to Biometry with your token.
| Platform | Package | Role |
|---|---|---|
| Web | biometry-sdk, biometry-react-components | Capture UI + client |
| Flutter | biometry | Capture UI + client |
| Go | biometry-go | Server-side client, no capture |
import { FaceRecorder } from 'biometry-react-components';
function Verification() { const handleConfirm = async (video: File, audio: File, phrase: string) => { const formData = new FormData(); formData.append('video', video); formData.append('phrase', phrase);
// Send to YOUR backend, not directly to Biometry await fetch('/api/verify', { method: 'POST', body: formData }); };
return <FaceRecorder onConfirmRecording={handleConfirm} />;}app.post('/api/verify', async (req, res) => { const formData = new FormData(); formData.append( 'request', new Blob( [JSON.stringify({ user_id: req.user.id, session_id: req.body.sessionId, phrase: req.body.phrase, })], { type: 'application/json' } ) ); formData.append('video', req.files.video);
const response = await fetch( 'https://api.biometrysolutions.com/api-gateway/v2/liveness', { method: 'POST', headers: { Authorization: `Bearer ${process.env.BIOMETRY_API_TOKEN}` }, body: formData, } );
res.json(await response.json());});app.post('/api/verify', async (req, res) => { const formData = new FormData(); formData.append('video', req.files.video); formData.append('phrase', req.body.phrase);
const response = await fetch( 'https://api.biometrysolutions.com/api-gateway/process-video', { method: 'POST', headers: { Authorization: `Bearer ${process.env.BIOMETRY_API_TOKEN}`, 'X-User-Fullname': req.user.id, 'X-Session-ID': req.body.sessionId, }, body: formData, } );
res.json(await response.json());});Onboarding versus returning users
The two flows differ in what they compare against, and on v2 you can tell them apart before you start:
| Onboarding | Returning user | |
|---|---|---|
| Reference | The user’s identity document | The stored enrollment template |
| Typical calls | document check → liveness → face match → enroll | liveness → face verify / voice verify |
| Pre-flight | — | GET /v2/users/{user_id} tells you what is enrolled |
On v1 there is no pre-flight: your own database has to remember whether a user was enrolled.
Operational habits
- Use sessions. Group the calls of one attempt and end the session on both the success and failure paths — unended sessions show as abandoned.
- Log
request_id. Every v2 response carriesmeta.request_id; it is what support traces. - Retry only
5xx, with backoff and jitter. Never retry a successful enrollment or deepfake submission — both create records. - Don’t read the HTTP status alone. A
200can carry a failed service or a rejected enrollment. See the error catalog. - Use webhooks for slow work rather than polling, where the operation supports them.
- Pass device and location context (
X-Device-Info,X-Geo-Location) when you have it — it feeds fraud detection. See Device Information and Geo Location.
Where to go next
| Goal | Page |
|---|---|
| Build on the current API | v2 Quick Start |
| Maintain an existing v1 integration | v1 Quick Start |
| Move v1 → v2 | Migration guide |
| Understand the verdict | Scoring Systems |
| Hand the whole thing to a coding agent | AI Integration Skill |