Verification Link

Overview

Verification Link lets you start the verification flow without embedding UI. Your backend creates a session and receives a one-time url. You then either redirect the user to this url or render a QR code with that link. After the user completes the flow, the final session payload is sent to your callbackUrl (if provided) and is also available via Get Status.

Authentication

To access the API, you need to include the following headers in your request:

  • APP-ID: Your application's unique identifier.

  • APP-KEY: Your application's authentication key.

Session lifecycle

  • Statuses: CREATED, CAPTCHA_OK, IN_PROGRESS, DONE, FAILED, EXPIRED, CANCELED.

  • nextStep: LIVENESS, DEEPFAKE, ENROLL, SEARCH — the next operation to be performed; null when finished.

  • Expiration (TTL): 86400 s.

Endpoint POST https://cloud.ooto-ai.com/api/v1.0/flow/sessions

Headers APP-ID, APP-KEY Content-Type: application/json

Body

  • scopes: string[] required — allowed values: liveness, deepfake, search, enroll.

  • metadata: object optional — any JSON you need to carry along.

  • callbackUrl: string optional — your HTTPS endpoint that will receive the final session payload via POST.

  • returnUrl: string optional — where to redirect the user after flow completion.

  • ttlSec: number optional — requested TTL in seconds; bounded as per the formula above.

Response (200)

{
  "sessionId": "<UUID>",
  "token": "<opaque>",
  "url": "https://cloud.ooto-ai.com/flow/<token>"
}

Usage

  • Redirect the user with HTTP 302/303 to url, or

  • Render QR containing url for mobile handoff.

Callback contract

  • If callbackUrl is provided, OOTO‑AI sends a POST with the same structure as Get Status at completion time (see below). If you need retries/signature, implement them on your side.


2) Get Status

Endpoint GET https://cloud.ooto-ai.com/api/v1.0/flow/sessions/<TOKEN>

Response (example)

{
  "status": "DONE",
  "scopes": [
    "liveness",
    "deepfake",
    "search"
  ],
  "nextStep": null,
  "expiresAt": "2025-09-23T13:43:31.114Z",
  "uiHints": {
    "needCaptcha": false
  },
  "returnUrl": null,
  "result": {
    "box": {
      "h": 451,
      "w": 351,
      "x": 182,
      "y": 420
    },
    "search": {
      "similarity": 0.8926131725311279,
      "templateId": "16de28ea-dd15-4005-9a42-539e911db2d3"
    },
    "quality": {
      "yaw": 2.1518145874142647,
      "blur": {
        "fine": true,
        "score": 0.0002416080969851464
      },
      "roll": -0.10165892774239182,
      "flare": {
        "fine": false,
        "score": 0.7195543646812439
      },
      "pitch": -2.330978773534298,
      "crfiqa": {
        "fine": true,
        "score": 0.5868616104125977
      },
      "emotion": {
        "fine": true,
        "score": 0.010030289180576801
      },
      "contrast": {
        "fine": true,
        "value": 0.542739260497907
      },
      "exposure": {
        "fine": true,
        "value": 0.4497541851888898
      },
      "occlusion": {
        "fine": true,
        "score": 0.07414574921131134
      },
      "distortion": {
        "fine": true,
        "score": 0.8153706789016724
      },
      "uniformity": {
        "fine": true,
        "value": 0.7228297966860057
      },
      "macroblocks": {
        "fine": true,
        "score": 0.000059822112234542146
      },
      "leftEyeClosed": {
        "fine": true,
        "score": 0.0000013113021850585938
      },
      "rightEyeClosed": {
        "fine": true,
        "score": 2.384185791015625e-7
      }
    },
    "deepfake": {
      "fine": true,
      "score": 0.9524966776371002
    },
    "liveness": {
      "fine": true,
      "score": 0.9612892089352414
    },
    "landmarks": [
      [
        288,
        604
      ],
      [
        435,
        604
      ],
      [
        367,
        685
      ],
      [
        303,
        762
      ],
      [
        422,
        763
      ]
    ],
    "demography": {
      "age": 31,
      "race": "white",
      "gender": "male"
    }
  }
}

Notes

  • status reflects lifecycle; nextStep is null when finished.

  • result shape depends on selected scopes and contains the aggregated outputs.

Last updated