extra.ekyc
Verification artefacts from the document scan and the liveness check.
{ "extra": { "ekyc": { "face_compare": { "status": "match", "score": 88.09 }, "liveness": { "url": "https://app.uppass.io/api/ekyc/YOUR_APPLICATION_SLUG/result/image/?q=SIGNED_TOKEN_REDACTED&exp=1787738816", "attempts": [ { "attempt": 1, "id": 100012, "created_at": "2026-08-26T09:51:32.007437+00:00", "status": "success", "message": "", "images": [ { "url": "https://app.uppass.io/api/ekyc/YOUR_APPLICATION_SLUG/result/image/?q=SIGNED_TOKEN_REDACTED&exp=1787738816", "action": "idle" } ] } ] }, "identity_document": { "type": "passport", "url": "https://app.uppass.io/api/ekyc/YOUR_APPLICATION_SLUG/result/image/?q=SIGNED_TOKEN_REDACTED&exp=1787738816", "face_image_url": "https://app.uppass.io/api/ekyc/YOUR_APPLICATION_SLUG/result/image/?q=SIGNED_TOKEN_REDACTED&exp=1787738816", "attempts": [ { "attempt": 1, "id": 100013, "created_at": "2026-08-26T09:51:21.926040+00:00", "type": "passport", "url": "https://app.uppass.io/api/ekyc/YOUR_APPLICATION_SLUG/result/image/?q=SIGNED_TOKEN_REDACTED&exp=1787738816", "status": "success", "message": "" } ] } } }}Three independent objects:
| Field | Type | Notes |
|---|---|---|
face_compare | object | Similarity between the liveness selfie and the document portrait. |
liveness | object | Facial liveness check. url is the best frame across all attempts; attempts
carries one entry per try. |
identity_document | object | The accepted document scan, the portrait cropped from it, and one entry per scan attempt. |
Signed image URLs
Section titled “Signed image URLs”Every url and face_image_url in this object is a signed, short-lived URL on
app.uppass.io:
https://app.uppass.io/api/ekyc/{slug}/result/image/?q=<signed-token>&exp=1787738493exp is a Unix timestamp.
There are three assets to retain per application:
| Asset | Path |
|---|---|
| Document scan | extra.ekyc.identity_document.url |
| Portrait cropped from the document | extra.ekyc.identity_document.face_image_url |
| Best liveness frame | extra.ekyc.liveness.url |
Individual attempts carry their own URLs if you want to retain rejected captures too.
face_compare
Section titled “face_compare”Similarity between the liveness selfie and the portrait on the document.
| Field | Type | Notes |
|---|---|---|
score | numberfloat | Similarity score, 0–100. |
status | string |
score: |
{ "status": "match", "score": 88.09}status is set from score, and other_status.ekyc follows it:
score |
face_compare.status |
other_status.ekyc |
|---|---|---|
| 70 or above | match |
pass |
| 61–69 | need_review |
need_review |
| 60 or below | not_match |
fail |
need_review means the document and liveness checks passed but the faces were not a
confident match — route it to a person.
liveness
Section titled “liveness”The facial liveness check, with one entry per attempt.
| Field | Type | Notes |
|---|---|---|
url | stringuri | Signed, short-lived URL for a captured image, on the app.uppass.io host. |
attempts | array<LivenessAttempt> | One entry per attempt, in order. More than one entry means the applicant retried — worth recording even when the last attempt succeeded. |
id | integer | Internal attempt identifier. |
attempt | integer | 1-based counter. More than one entry means the applicant retried. |
status | string |
|
message | string | Reserved for a failure reason. Empty on failed attempts as well as successful ones — do not rely on it for diagnostics. |
created_at | stringdate-time | When this attempt was captured. |
images | array<object> | Frames captured during this attempt. |
{ "url": "https://app.uppass.io/api/ekyc/YOUR_APPLICATION_SLUG/result/image/?q=SIGNED_TOKEN_REDACTED&exp=1787738816", "attempts": [ { "attempt": 1, "id": 100012, "created_at": "2026-08-26T09:51:32.007437+00:00", "status": "success", "message": "", "images": [ { "url": "https://app.uppass.io/api/ekyc/YOUR_APPLICATION_SLUG/result/image/?q=SIGNED_TOKEN_REDACTED&exp=1787738816", "action": "idle" } ] } ]}url at the top of the object is the best frame across all attempts. Use it unless
you specifically need per-attempt frames.
Reading attempts
Section titled “Reading attempts”attempts is ordered, and attempt is a 1-based counter. More than one entry means
the applicant retried, which is a signal worth recording even when the final attempt
succeeded.
attempts[0] attempt: 1 status: "fail"attempts[1] attempt: 2 status: "success"images[].action names the action captured — idle for a passive check. Additional
actions appear when the flow is configured for active liveness.
identity_document
Section titled “identity_document”The document scan.
| Field | Type | Notes |
|---|---|---|
type | string |
|
url | stringuri | Signed, short-lived URL for a captured image, on the app.uppass.io host. |
face_image_url | stringuri | Signed, short-lived URL for a captured image, on the app.uppass.io host. |
attempts | array<DocumentAttempt> | One entry per scan attempt, in order. |
id | integer | Internal attempt identifier. Quote it to support when reporting a scan problem. |
attempt | integer | 1-based counter. |
type | string |
|
url | stringuri | Signed, short-lived URL for a captured image, on the app.uppass.io host. |
status | string |
|
message | string | Reserved for a failure reason. Empty on failed attempts as well as successful ones — use status instead. |
created_at | stringdate-time | When this attempt was captured. |
{ "type": "passport", "url": "https://app.uppass.io/api/ekyc/YOUR_APPLICATION_SLUG/result/image/?q=SIGNED_TOKEN_REDACTED&exp=1787738816", "face_image_url": "https://app.uppass.io/api/ekyc/YOUR_APPLICATION_SLUG/result/image/?q=SIGNED_TOKEN_REDACTED&exp=1787738816", "attempts": [ { "attempt": 1, "id": 100013, "created_at": "2026-08-26T09:51:21.926040+00:00", "type": "passport", "url": "https://app.uppass.io/api/ekyc/YOUR_APPLICATION_SLUG/result/image/?q=SIGNED_TOKEN_REDACTED&exp=1787738816", "status": "success", "message": "" } ]}type echoes the document actually scanned, which is the value to trust — not what
you requested at creation:
type |
Document |
|---|---|
front_card |
National ID, front face |
passport |
Passport data page |
It also determines which keys appear in answers.
When these objects are absent
Section titled “When these objects are absent”extra.ekyc is present on any flow with a document or liveness step. On a flow
without one — a name-screening or KYB flow — it is omitted entirely, not empty.
Guard every access:
extra?.ekyc?.face_compare?.score