> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vu-one.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Read KYC Results from Identity Verifications

> Query verification status and OCR-extracted document data after a user completes an identity verification through Identity Link.

After a user completes an Identity Link flow, VU extracts structured data from the captured identity document and makes it available through the verification API. This guide covers the full verification lifecycle, all query endpoints, and the extracted data fields you can use for KYC and onboarding decisions.

## Verification lifecycle

A verification progresses through the following states:

| Status | Meaning |
| - | - |
| `pending` | The link was created but the user has not yet started the flow. |
| `started` | The user opened the link and began the verification process. |
| `expired` | The link or the verification session exceeded its time limit. |
| `success` | The user completed all required steps and the document was successfully processed. |
| `failed` | The verification could not be completed, for example because of a rejected document or failed liveness check. |

## Verification steps

During a `FULL FLOW`, the user moves through these operational steps:

| Step | Description |
| - | - |
| `NEW_OPERATION` | The verification session was initialized. |
| `ADD_FRONT` | The user captured the front side of the identity document. |
| `ADD_BACK` | The user captured the back side of the identity document. |
| `END_OPERATION` | The verification session concluded, either successfully or with a failure. |

## Get verification details

Retrieve the full verification record including extracted document data and geolocation:

```bash theme={null}
curl -X GET https://api.identity.vu-one.com/api/v1/verifications/6ba7b810-9dad-11d1-80b4-00c04fd430c8 \
  -H "Authorization: Bearer <token>"
```

```json theme={null}
{
  "_id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
  "linkId": "550e8400-e29b-41d4-a716-446655440000",
  "companyId": "9f1c2b3a-4d5e-6f70-8192-a3b4c5d6e7f8",
  "userName": "jane.doe@example.com",
  "termsAndConditions": true,
  "images": {
    "addFront": "1f2e3d4c-5b6a-7980-9102-a3b4c5d6e7f8",
    "addBack": "2a3b4c5d-6e7f-8091-a2b3-c4d5e6f70819",
    "register": ["3b4c5d6e-7f80-91a2-b3c4-d5e6f7081920"]
  },
  "errorMessage": null,
  "step": "END_OPERATION",
  "detectedDocumentCountry": "ARG",
  "status": "success",
  "data": {
    "firstNames": "JANE",
    "lastNames": "DOE",
    "name": "DOE, JANE",
    "adult": true,
    "nationality": "ARG",
    "gender": "F",
    "birthDate": "1990-05-15",
    "dateOfIssue": "2015-03-10",
    "dateOfExpiry": "2025-03-10",
    "idNumber": "12345678",
    "ocrRaw": "...",
    "barcodeRaw": "..."
  },
  "expiresAt": "2026-08-23T14:00:00Z",
  "createdAt": "2026-08-22T14:00:00Z",
  "updatedAt": "2026-08-22T14:35:22Z",
  "geolocation": { }
}
```

<Note>
  The verification identifier is `_id`. All OCR-extracted document fields live inside the `data` object, not at the root of the response.
</Note>

### Extracted data fields

| Field | Type | Description |
| - | - | - |
| `firstNames` | string | Given names as read from the document. |
| `lastNames` | string | Surnames as read from the document. |
| `name` | string | Full name when available. |
| `adult` | boolean | Whether the document holder is an adult based on birth date. |
| `nationality` | string | Nationality code or name. |
| `gender` | string | Gender as printed on the document. |
| `birthDate` | string | Date of birth. |
| `dateOfIssue` | string | Document issue date. |
| `dateOfExpiry` | string | Document expiry date. |
| `idNumber` | string | Document identification number. |
| `ocrRaw` | string | Raw OCR text read from the document. |
| `barcodeRaw` | string | Raw barcode payload, when the document carries one. |

## Lightweight status polling

`GET /verifications/{id}/status` is a **public** endpoint: it takes no Bearer token. Instead it requires the `linkId` query parameter, which proves the caller is the intended end user rather than anyone who guessed the verification id.

```bash theme={null}
curl -X GET "https://api.identity.vu-one.com/api/v1/verifications/6ba7b810-9dad-11d1-80b4-00c04fd430c8/status?linkId=550e8400-e29b-41d4-a716-446655440000"
```

Response:

```json theme={null}
"success"
```

To also receive the `operationGuid` and the resolved `method`, add the `include` parameter. `linkId` is still required:

```bash theme={null}
curl -X GET "https://api.identity.vu-one.com/api/v1/verifications/6ba7b810-9dad-11d1-80b4-00c04fd430c8/status?linkId=550e8400-e29b-41d4-a716-446655440000&include=operationGuid"
```

```json theme={null}
{
  "status": "success",
  "operationGuid": "op-abc123",
  "method": "DOCUMENT"
}
```

| Field | Description |
| - | - |
| `status` | Current verification status. |
| `operationGuid` | OM operation identifier, for correlating client-side telemetry. `null` when not yet assigned. |
| `method` | Branch resolved server-side and persisted once: `FACE` for the adaptive selfie-only branch, `DOCUMENT` for the full ID and face flow, `null` while unresolved. |

<Warning>
  Omitting `linkId`, or passing one that does not match the verification, returns **403**. This parameter became mandatory in version 2.2.0.
</Warning>

## List verifications

### Get last 100 verifications

```bash theme={null}
curl -X GET https://api.identity.vu-one.com/api/v1/verifications \
  -H "Authorization: Bearer <token>"
```

The response is a paginated object:

```json theme={null}
{
  "total": 248,
  "page": 1,
  "data": [ ]
}
```

### Verifications from the last hour

```bash theme={null}
curl -X GET https://api.identity.vu-one.com/api/v1/verifications/last-hour \
  -H "Authorization: Bearer <token>"
```

### Paginated verifications

```bash theme={null}
curl -X GET https://api.identity.vu-one.com/api/v1/verifications/20/1 \
  -H "Authorization: Bearer <token>"
```

Where `20` is the page size (max `100`) and `1` is the page number.

## Related verifications for the same client

`GET /verifications/{id}/related` returns every other verification for the same client, meaning the same company and the same `externalUserId` on its link, newest first.

```bash theme={null}
curl -X GET https://api.identity.vu-one.com/api/v1/verifications/6ba7b810-9dad-11d1-80b4-00c04fd430c8/related \
  -H "Authorization: Bearer <token>"
```

```json theme={null}
[
  {
    "_id": "8c9d0e1f-2a3b-4c5d-6e7f-8091a2b3c4d5",
    "createdAt": "2026-06-01T10:12:00Z",
    "status": "success",
    "dataExpired": false
  }
]
```

| Field | Description |
| - | - |
| `_id` | Identifier of the related verification. |
| `createdAt` | Creation timestamp. |
| `status` | Final status. |
| `dataExpired` | `true` once retention has anonymized that row. Render it as a DATA EXPIRED tag rather than the now-hashed identity fields. |

<Note>
  The list is empty when the anchor verification's link has no `externalUserId` to match on.
</Note>

## Verification images

```bash theme={null}
# List every image on a verification
curl -X GET https://api.identity.vu-one.com/api/v1/verifications/6ba7b810-9dad-11d1-80b4-00c04fd430c8/images \
  -H "Authorization: Bearer <token>"

# Fetch one image by id
curl -X GET https://api.identity.vu-one.com/api/v1/verifications/images/1f2e3d4c-5b6a-7980-9102-a3b4c5d6e7f8 \
  -H "Authorization: Bearer <token>"
```

The image ids come from the verification's `images` object: `addFront`, `addBack`, and the `register` array of selfie frames.

## Public flow endpoints

The three endpoints below are called by the user's device during the flow, without a token. All of them require the verification to still be attached to an active link and to be in `pending` or `started` status.

### Report geolocation

Every location field travels **nested inside the `geolocation` object**.

```bash theme={null}
curl -X PATCH https://api.identity.vu-one.com/api/v1/verifications \
  -H "Content-Type: application/json" \
  -d '{
    "verificationId": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
    "geolocation": {
      "ip": "190.191.192.193",
      "accuracyRadius": 5,
      "city": "Buenos Aires",
      "country": "AR",
      "latitude": -34.6037,
      "longitude": -58.3816,
      "subdivisions": "CABA",
      "accuracy": 10,
      "source": "gps",
      "permission": "granted",
      "sample": "best_of_session",
      "capturedAt": "2026-08-22T14:32:00Z",
      "deviceLatitude": -34.6037,
      "deviceLongitude": -58.3816
    }
  }'
```

<Warning>
  `tier`, `policy`, `ipDistanceKm`, and `serverIp` are **not** accepted properties: all four are derived server-side and the request is rejected with **400** if a client sends any of them.
</Warning>

Two further validations return **400**:

* Declaring a device `source` (`gps`, `wifi`, or `cell`) without `deviceLatitude` and `deviceLongitude`. Nothing downstream can use either half alone.
* A `capturedAt` more than 24 hours from the server's clock.

### Report an error

```bash theme={null}
curl -X PATCH https://api.identity.vu-one.com/api/v1/verifications/error \
  -H "Content-Type: application/json" \
  -d '{
    "verificationId": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
    "errorCode": "CAMERA_PERMISSION_DENIED",
    "errorMessage": "The user denied camera access"
  }'
```

### Identify a user mid-flow

`PATCH /verifications/identify` covers an adaptive link created without an `externalUserId`. It backfills the link's `externalUserId` from the supplied email and re-resolves the adaptive branch.

```bash theme={null}
curl -X PATCH https://api.identity.vu-one.com/api/v1/verifications/identify \
  -H "Content-Type: application/json" \
  -d '{
    "verificationId": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
    "email": "jane.doe@example.com"
  }'
```

```json theme={null}
{
  "status": "started",
  "operationGuid": "op-abc123",
  "method": "FACE"
}
```

Rules for this endpoint:

* Repeating the same email is always a no-op and answers **200**.
* An identifier the API supplied at link creation can never be overwritten: a different email answers **409** with `identifierAlreadyBound`.
* An identifier this endpoint itself set, meaning one typed by the person, is freely correctable: a different email is accepted and the branch is re-resolved.
* An invalid or missing email answers **400**.

## Manual feedback override

If an automated result needs human review, submit feedback through `POST /verifications/feedback`:

```bash theme={null}
curl -X POST https://api.identity.vu-one.com/api/v1/verifications/feedback \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "verificationId": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
    "overrideStatus": "success",
    "reasonId": "4c5d6e7f-8091-a2b3-c4d5-e6f708192021"
  }'
```

| Field | Type | Description |
| - | - | - |
| `verificationId` | uuid | Verification to correct. |
| `overrideStatus` | string | Status that overrides the automated result. |
| `reasonId` | uuid | Reason identifier, taken from the reasons list. |

List available feedback reasons, each returning `_id` and `reason`. Use that `_id` as the `reasonId`:

```bash theme={null}
curl -X GET https://api.identity.vu-one.com/api/v1/verification-feedback/reasons \
  -H "Authorization: Bearer <token>"
```

## Geolocation reference

`geolocation` pairs a reported location with a measure of how much to trust it. It is absent until a location has been reported, and `tier` is always present alongside coordinates: never a bare lat/lng.

| Field | Type | Description |
| - | - | - |
| `ip` | string | IP the fingerprint service attributed to the client. Client-declared. |
| `accuracyRadius` | number | Radius of the IP-derived confidence area, in **kilometres**. |
| `latitude` | string | IP-derived latitude, serialised as a string. |
| `longitude` | string | IP-derived longitude, serialised as a string. |
| `country` | string | Country. |
| `city` | string | City. |
| `subdivisions` | string | State or province subdivision. |
| `accuracy` | number | W3C `coords.accuracy`: the device's own 95%-confidence radius, in **metres**. Only present for a device fix. |
| `source` | string | Which mechanism produced the fix: `gps`, `wifi`, `cell`, `ip`, or `none`. |
| `tier` | string | How precise the position actually is, derived server-side from `accuracy` alone: `precise` (≤100 m), `approximate` (≤5 km), `coarse` (>5 km or IP-derived), `unknown` (no position to grade). |
| `permission` | string | Browser permission state observed during capture: `granted`, `denied`, or `prompt`. |
| `sample` | string | Which sample was reported. `best_of_session` is the tightest fix seen before the flow started. |
| `capturedAt` | date-time | When the device took the sample. Client-declared. |
| `deviceLatitude` | number | Device (GPS/WiFi/cell) latitude, serialised as a **number**, unlike the IP-derived pair. |
| `deviceLongitude` | number | Device (GPS/WiFi/cell) longitude, serialised as a **number**. |
| `policy` | string | Authenticated GET only. The `locationPermission` policy in force when this result was captured: `never`, `optional`, or `required`. |
| `ipDistanceKm` | number | Authenticated GET only. Server-computed distance between the device fix and the IP-derived position. `null` when there is no device fix to compare. |
| `serverIp` | string | Authenticated GET only. The request IP the server observed on the geolocation PATCH, distinct from the client-declared `ip`. |

<Warning>
  `policy`, `ipDistanceKm`, and `serverIp` are returned **only** by the authenticated GET endpoints. They are absent from the public PATCH responses and from webhooks. Returning these anti-fraud signals to an unauthenticated caller would let it calibrate a spoofed location against the check meant to catch it.
</Warning>

<Note>
  `source` is **inferred**, not measured: the W3C Geolocation API does not expose its provider, so `gps`, `wifi`, and `cell` are deduced client-side from altitude, speed, and accuracy bands. Only `ip` and `none` are certain. Being client-declared, all values are falsifiable — the server-side `ipDistanceKm` is the cross-check.
</Note>

## Next steps

* Understand how liveness detection protects against spoofing in the [Liveness](/en/identity-link/liveness) guide.
* Receive automatic notifications for every status change by configuring [Webhooks](/en/identity-link/webhooks).
* Review common errors when querying verifications on the [Errors](/en/identity-link/errors) page.


## Related topics

- [Identity Link Webhooks: Verification Lifecycle Events](/en/identity-link/webhooks.md)
- [Identity Link API: Integration Guide](/en/identity-link/introduction.md)
- [VU Technical Documentation](/en/index.md)
- [Quickstart: your first identity verification](/en/quickstart.md)
- [Create and Manage Verification Links](/en/identity-link/links.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.