API reference

Emnet verification API v1. Three endpoints, JSON over HTTPS, authenticated with a bearer API key.

Base URL

bash
$EMNET_BASE_URL/v1

Your base URL is issued with your early-access key. The environment is resolved from your key — a test key reaches the sandbox, a live key reaches production. There is no separate hostname and no environment parameter. All requests must use HTTPS.

Authentication

bash
Authorization: Bearer sk_live_…

See Authentication for key types and rules. The badges below show which key types each endpoint accepts.

Start a verification

GET/v1/verification/person/fayda/authorize-urlsk_pk_

Creates a verification session and returns the URL to send the user to, plus the state value you must store and compare when they return.

Request

No parameters and no body. Everything is derived from your key.

curl
curl "$EMNET_BASE_URL/v1/verification/person/fayda/authorize-url" \
  -H "Authorization: Bearer sk_test_…"

Response — 200

FieldTypeDescription
authorizeUrlstringProvider URL to redirect the user to. Single-use and time-limited.
statestringOpaque value tying the callback to this session. Store it; compare it on return.
json
{
  "authorizeUrl": "https://…/authorize?client_id=…&state=a7f3d21c9b0e",
  "state": "a7f3d21c9b0e4f8a1c2e9b7d6a5c3e1f"
}

Other statuses: 401 invalid key · 429 rate limited · 503 provider unavailable.

Complete a verification

POST/v1/verification/person/fayda/callbacksk_

Exchanges the authorization code for verified claims. Secret keys only — a publishable key receives 403. Always call this from your server.

Request body

FieldTypeRequiredDescription
codestringYesAuthorization code from the provider redirect. Single-use.
statestringYesThe state value from the redirect. Compare it with your stored copy first.
curl
curl -X POST "$EMNET_BASE_URL/v1/verification/person/fayda/callback" \
  -H "Authorization: Bearer sk_live_…" \
  -H "Content-Type: application/json" \
  -d '{"code":"8f3c9a1b7e2d","state":"a7f3d21c9b0e4f8a1c2e9b7d6a5c3e1f"}'

Response — 200

FieldTypeDescription
sessionIdintegerIdentifier for this verification session.
identityKeystringPseudonymous, stable-per-account identifier for the person.
claimsobjectVerified attributes released to your account, as string values.
availableClaimsarrayClaims the provider could return for your account.
assuranceLevelstringAssurance level of the authentication, e.g. "L2".
livenessEvidencestringLiveness signal where available; may be absent.
providerstringIdentity provider, e.g. "FAYDA".
sourcestringService within the provider, e.g. "esignet".
verifiedAtstringISO-8601 UTC completion timestamp.
environmentstringWhich registry answered: "LIVE" (production registry, billable) or "TEST" (sandbox or simulator). Always equals your key’s environment.

Consumer rule. Under your production profile, grant a tier or any decision from a result only if environment is exactly "LIVE". An absent or unrecognised value is refused, never defaulted. Emnet publishes the rule and does not enforce your side of it. The same value is on the session status view, so a poll and the result agree.

json
{
  "sessionId": 4711,
  "identityKey": "3f9c1a0b7e5d4c2a9b8e7f6d5c4b3a29…",
  "claims": {
    "name": "Yigermal Fantaye",
    "birthdate": "1996-04-11",
    "gender": "male"
  },
  "availableClaims": ["name", "birthdate", "gender", "address", "phone"],
  "assuranceLevel": "L2",
  "livenessEvidence": "PRESENTED",
  "provider": "FAYDA",
  "source": "esignet",
  "verifiedAt": "2026-07-26T09:14:22Z",
  "environment": "LIVE"
}

Other statuses: 400 invalid or already-used code · 401 invalid key · 403 publishable key, or a claim your account is not entitled to · 429 rate limited · 503 provider unavailable.

Read a session

GET/v1/verification/person/session/{id}sk_pk_

Returns the status and metadata of a verification session. Never returns claims, which is why a publishable key may call it.

Path parameter

NameTypeDescription
idintegerThe sessionId.
curl
curl "$EMNET_BASE_URL/v1/verification/person/session/4711" \
  -H "Authorization: Bearer sk_live_…"

Response — 200

FieldTypeDescription
sessionIdintegerThe session identifier.
providerstringIdentity provider used.
statusstringSession state, e.g. "COMPLETED".
assuranceLevelstringAssurance level, once completed.
livenessEvidencestringLiveness signal where available.
environmentstring"LIVE" or "TEST" — the same value the verification result carries, so a poll and the result agree.
completedAtstringCompletion timestamp, if completed.
json
{
  "sessionId": 4711,
  "provider": "FAYDA",
  "status": "COMPLETED",
  "assuranceLevel": "L2",
  "livenessEvidence": "PRESENTED",
  "environment": "LIVE",
  "completedAt": "2026-07-26T09:14:22Z"
}
Cross-tenant reads return 404, not 403

A session belonging to another account is reported as not found. Returning 403 would confirm that the session exists, which is information the API will not give up.

Other statuses: 401 invalid key · 404 unknown session, or not yours · 429 rate limited.

Error format

Every error shares one shape. Messages are safe to log — they never contain personal data.

json
{
  "error": "invalid_request",
  "message": "The authorization code has already been used.",
  "status": 400
}

See Errors for the full list and how to respond to each.

OpenAPI specification

The API is described by a hand-authored OpenAPI 3.0 document that is kept in step with the server by hand rather than generated from it — so it describes the contract we commit to, not an accident of implementation. It ships in the Java SDK repository at openapi/emnet-identity-v1.yaml and can be used to generate a client in any language.