Service API · API Docs · eKYC Platform

Full verification

POST/portal/ekyc/full_verification

Synchronously runs a complete eKYC dossier — ID Verification then Selfie Verification — in a single request, and returns the full application result.

Request

MethodPOST
Path/portal/ekyc/full_verification
Content-Typeapplication/json
Auth requiredYes — JWT access token

The endpoint imports the ID/selfie assets you already hold, runs the configured ID and selfie checks in sequence (waiting for each), drives the application to a terminal state so the configured Post-check / AML / Government checks run, and returns the full TS-native result — the same shape as Application detail.

This is the Service-API (JWT-authed) equivalent of the Platform Onboard API: same request/response shape, but not the same execution path. The lender is resolved from your JWT access token (like API Vision Score), and the server then generates an encrypted_token on your behalf and drives the request through the same underlying Onboard pipeline. That extra internal step is why this endpoint has two failure modes the Onboard API doesn't (see Failure codes): it can fail to generate that token (500), or fail while calling the underlying pipeline with it (502).

Use this when you already hold a user's ID/selfie assets (e.g. captured on another channel or by another vendor) and want to re-check them through the TrustVision pipeline in one call, without driving Init / Verify ID / Verify Selfie separately.

Note: the request blocks until all checks finish (ID + selfie run sequentially), so allow a generous client timeout.

Send the JWT access token in the Authorization header.

NameTypeRequiredDescription
card_typestringRequired for IDCard type to verify (e.g. vn.national_id). Must be within card_types when that is provided.
image1objectRequired for IDID front: { "base64": "<base64>", "metadata": "<string>", "qr_code": [{"result": "...", "from_image_type": "..."}] }.
image2objectOptionalID back: same structure as image1.
qrsarrayOptionalStandalone QR images: [{ "base64": "<base64>", "metadata": "<string>" }].
selfiesarrayRequired for selfieFrontal selfie image(s): [{ "base64" \| "id", "metadata" }]. The last element is the primary selfie used for face compare. An element with id references a pre-uploaded image (see Upload image).
selfie_typestringOptionalSelfie / liveness type (e.g. passive, passive_v2, flash).
videosarrayOptionalLiveness video frames: [{ "id"?, "metadata"?, "frames": [{ "base64", "label", "index", "metadata"? }] }] (≤ 10). Required for passive/flash liveness to pass — a still-only selfie gives the engine nothing to score.
flow_idstringOptionalRoutes the request to the lender config mapped to this flow via the encryption key's flow_lender_config_mapping. Falls back to the lender's active config.
card_typesstringOptionalComma-separated allowed card types (e.g. vn.national_id,vn.passport).
langstringOptionalLanguage code (e.g. vi, en).
client_metadataobjectOptionalOptional prepared metadata (e.g. applicant identity PII: applicant_name, id_number, dob, gender, phone_number, email), already encrypted by you. JSON ≤ 8 KB. Stored raw and echoed back raw only — never decrypted, and never fed into any check or the verdict.

At least one of image1 (ID) or selfies (selfie) must be present — supply only one group for an ID-only or selfie-only re-check. Put liveness frames in videos, not in selfies.

The body is identical to the Platform Onboard API minus encrypted_token — authentication is handled by the JWT, so no token is sent in the body.

JSON
{
  "card_type": "vn.national_id",
  "image1": {
    "base64": "<base64_string>",
    "metadata": "{\"frame_index\":0}",
    "qr_code": [{ "result": "...", "from_image_type": "front" }]
  },
  "image2": {
    "base64": "<base64_string>"
  },
  "selfies": [
    { "base64": "<base64_string>", "metadata": "{\"frame_index\":0}" }
  ],
  "selfie_type": "passive",
  "videos": [
    {
      "frames": [
        { "base64": "<base64_string>", "label": "frontal", "index": 0 }
      ]
    }
  ],
  "flow_id": "full_verification",
  "card_types": "vn.national_id,vn.passport",
  "lang": "vi",
  "client_metadata": {
    "applicant_name": "<already-encrypted>",
    "id_number": "<already-encrypted>"
  }
}

Response

The endpoint blocks until all checks complete, then returns the full result — the same TS-native shape as Application detail (overall verdict plus each module's status). Conditional blocks (ekyc_ocr / ekyc_face / id_tampering / file_ids / form_data / client_metadata) appear only when the corresponding data exists.

Success (200):

JSON
{
  "data": {
    "verdict": "approve",
    "application_id": 10,
    "application_unique_token": "ad083945-...",
    "application_user_id": "0123456789",
    "ekyc_ocr": {
      "card_info": {},
      "process_status": "success",
      "sanity_check_status": "success"
    },
    "ekyc_face": {
      "compare_status": "matched",
      "compare_score": 0.98,
      "liveness_status": "live",
      "search_face_status": "not_found"
    },
    "id_tampering": { "score": 0.01, "verdict": "genuine" },
    "client_metadata": {
      "applicant_name": "<already-encrypted>",
      "id_number": "<already-encrypted>"
    },
    "access_token": "<JWT>"
  },
  "message": "onboard completed",
  "time": "2026-01-01T00:00:00Z",
  "verdict": "success"
}

Response data fields:

FieldDescription
data.verdictOverall application verdict: approve, review, reject, or pending.
ekyc_ocr / ekyc_face / id_tamperingPer-module results + status (same as Application detail). Present only when run.
client_metadataThe prepared metadata you supplied, echoed back raw (omitted if none).
access_tokenJWT to re-pull Application detail for this application later.

See Application detail for the full field reference, and The application result for the verdict, file_ids and form_data mappings.

Dedupe / indexing-only mode: when enabled for the lender (client_custom_settings.onboard_dedupe_only), the endpoint runs only face index/search, leaves data.verdict as pending, and returns the match result on data.ekyc_face.search_face_result / search_face_status (the Post-check / AML / verdict pipeline is skipped).

Failure codes

NameDescriptionStatus codeResponse Body
Bad RequestInvalid parameters / missing config400{"data":{},"message":"eKYC platform URL not configured","verdict":"failure"} / relayed invalid_parameters / missing_parameters
UnauthorizedInvalid authentication token401{"data":{},"message":"authorization header is missing","time":"2024-10-31T07:50:22Z","verdict":"missing_authorization"}
Token ExpiredToken expired. Client should login again401{"data":{},"message":"Provided token is expired","time":"2024-10-31T07:50:22Z","verdict":"expired_token"}
Not FoundEncryption key or lender not found / inactive404{"data":{},"message":"...","verdict":"record_not_found"}
Too Many RequestsAnother submission for the same user is in progress, or rate limit reached429{"data":{},"message":"...","verdict":"limit_exceeded"}
Internal Server ErrorCannot create encrypted token500{"data":{},"message":"cannot create encrypted token","verdict":"failure"}
Bad GatewayUpstream platform call failed (transport)502{"data":{},"message":"platform onboard failed: ...","verdict":"failure"}