Skip to content
Integration Guide

Othento REST API

Single-step, synchronous, API-key-driven verification endpoints. Call one step directly — no SDK and no session flow required. Each endpoint either creates a new session for you or attaches to an existing one you pass in.

Base URL

Base URL
https://be.<your-domain>/api/v1/steps

Use the host assigned to your environment — sandbox or production.

Authentication

Every request must include your API key in a header:

Header
X-API-KEY: <your_api_key>

Server-to-server only. Never put your API key in a browser-facing URL or in client-side code.

  • Missing or malformed key → 401 Unauthorized.
  • Suspended organization or application → 403 Forbidden.
  • No active subscription → 402 Payment Required.

Session handling

Every request body accepts these two fields, whichever endpoint you call:

Field Required Description
sessionId No An existing session’s external ID. When provided, this step is attached to that session.
workflowId Only if sessionId is omitted The workflow to create a new session under. Ignored when sessionId is provided.

If you omit sessionId, a new session is created automatically and its ID is returned in the response as sessionId — use that value to chain further steps onto the same session.

If the step has already completed or failed on that session, calling it again returns the existing result instead of re-running it. If it is still in progress you will get a 409.

Response shape

Every endpoint returns the same envelope:

Response
{
  "sessionId": "string",
  "stepCode": "step_xxx",
  "status": "Completed | Failed | Pending | SentToInference",
  "decision": "Approved | Declined | InReview | null",
  "statusReason": "string | null",
  "result": { /* step-specific — see each endpoint below */ }
}

result is null until the step reaches Completed.

Error format

Validation and business-rule errors return an RFC 9110 problem-details body:

Problem details
{
  "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
  "title": "The request could not be processed",
  "status": 400,
  "errors": {
    "<fieldName>": ["<message>"]
  },
  "instance": "/api/v1/steps/..."
}
Status Meaning
400 Validation error — missing or invalid field
401 Missing or invalid API key
402 No active subscription on your account
403 Application or organization suspended, or feature not enabled on your plan
404 sessionId or workflowId not found, or not owned by your application
409 Step already in progress for this session

ID Verification

POST /api/v1/steps/id-verification

Verifies an identity document — front and back images — against your configured document template.

Request
{
  "sessionId": null,
  "workflowId": "wf_xxx",
  "documentId": "doc_xxx",
  "frontImageBase64": "<base64>",
  "backImageBase64": "<base64 | null>",
  "fileExtension": "jpg"
}
  • documentId — required only if the session does not already have a document type selected.
  • backImageBase64 — required only if the selected document requires both sides.
Response — result
{
  "firstName": "string | null",
  "lastName": "string | null",
  "fullName": "string | null",
  "dateOfBirth": "yyyy-MM-dd | null",
  "dateOfExpiry": "yyyy-MM-dd | null",
  "documentNumber": "string | null",
  "personalNumber": "string | null",
  "nationality": "ISO3 | null",
  "nationalityCountryId": "string | null",
  "issuingCountry": "ISO3 | null",
  "issuingCountryId": "string | null",
  "isMismatch": true,
  "errorCategory": "string | null"
}

Face Match

POST /api/v1/steps/face-match

Compares a live or candidate face image against a reference face image. Both images are always required directly in the request — this endpoint does not read a portrait from a prior ID-verification step.

Request
{
  "sessionId": null,
  "workflowId": "wf_xxx",
  "selfieImageBase64": "<base64>",
  "refImageBase64": "<base64>",
  "fileExtension": "jpg"
}
Response — result
{
  "verified": true,
  "similarity": 0.99,
  "faceDetected": true,
  "multipleFaces": false,
  "errorCategory": "string | null"
}

similarity is in the range [0, 1].

Liveness Check

POST /api/v1/steps/liveness-check

Passive liveness — checks whether the submitted face media is a live capture or a spoof (a photo of a photo, a screen replay, a mask). No interactive challenge is required from the user.

Request
{
  "sessionId": null,
  "workflowId": "wf_xxx",
  "selfieImageBase64": "<base64>",
  "fileExtension": "jpg"
}

selfieImageBase64 accepts either a single photo (jpg, jpeg, png, webp) or a short video (mp4) — set fileExtension accordingly. A video generally yields a more confident score through multi-frame fusion than a single photo does.

Response — result
{
  "livenessPassed": true,
  "livenessConfidence": 99.9,
  "livenessType": "Fusion(mfas=1.00)",
  "faceDetected": true,
  "multipleFaces": false,
  "errorCategory": "string | null"
}

livenessConfidence is in the range [0, 100].

AML Screening

POST /api/v1/steps/aml-screening

Screens an individual’s identity details against sanctions, PEP and watchlist data.

Request
{
  "sessionId": null,
  "workflowId": "wf_xxx",
  "firstName": "string | null",
  "lastName": "string | null",
  "fullName": "string | null",
  "dateOfBirth": "yyyy-MM-dd | null",
  "nationality": "ISO3 | null",
  "nationalityCountryId": "string | null",
  "issuingCountry": "ISO3 | null",
  "issuingCountryId": "string | null",
  "documentNumber": "string | null",
  "personalNumber": "string | null",
  "gender": "string | null"
}
Response — result
{
  "matchStatus": "clear | potential_match | true_match",
  "riskLevel": "low | medium | high | unknown",
  "totalHits": 0,
  "matches": [
    {
      "id": "string",
      "name": "string",
      "entityType": "person | company",
      "types": ["sanction", "pep", "warning"],
      "sources": ["string"],
      "aka": ["string"],
      "countries": ["ISO2"],
      "countryIds": ["string"],
      "matchTypes": ["string"],
      "score": 0.0,
      "isWhitelisted": false
    }
  ]
}

If the provider errors out, decision resolves to Declined with no result attached and statusReason set.

IP Analysis

POST /api/v1/steps/ip-analysis

Analyzes an IP address for fraud-risk signals — VPN, proxy, Tor and hosting detection, plus geolocation.

Request
{
  "sessionId": null,
  "workflowId": "wf_xxx",
  "ipAddress": "203.0.113.10"
}
Response — result
{
  "ipAddress": "string",
  "countryId": "string | null",
  "country": "ISO3 | null",
  "region": "string | null",
  "city": "string | null",
  "isp": "string | null",
  "organisation": "string | null",
  "asn": "string | null",
  "isVpn": false,
  "isProxy": false,
  "isTor": false,
  "isHosting": false,
  "connectionType": "string | null",
  "riskScore": 0
}

riskScore is in the range [0, 100]. If the provider errors out, decision resolves to InReview with no result attached.

Step codes

Each endpoint reports its own stepCode in the response envelope:

Endpoint stepCode
/id-verification step_id_verification
/face-match step_face_match
/liveness-check step_liveness_check
/aml-screening step_aml_screening
/ip-analysis step_ip_analysis

Example request

A complete call against the face-match endpoint, creating a new session:

curl
curl -X POST https://be.<your-domain>/api/v1/steps/face-match \
  -H "X-API-KEY: <your_api_key>" \
  -H "Content-Type: application/json" \
  -d '{
    "workflowId": "wf_xxx",
    "selfieImageBase64": "<base64>",
    "refImageBase64": "<base64>",
    "fileExtension": "jpg"
  }'