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

# Document Verification

> Extract identity details from a photo of a document using OCR — no face match, no liveness.

The Document Verification endpoint extracts identity details from a photo of a document using OCR. Unlike the checks under [Data Verification](/v3/kyc/nigeria/BVN), which look up an ID number against a government database, this endpoint reads the details directly off an uploaded image — useful as a fallback when a number-lookup check is unavailable, or when your flow already collects a document photo.

No face match, no liveness check — this endpoint only performs OCR extraction.

## Supported Documents

Which `document_type` values are valid depends on the document's `country`.

| Country       | Supported `document_type` values                                                               |
| ------------- | ---------------------------------------------------------------------------------------------- |
| Nigeria       | `national_id`, `passport`, `drivers_license`, `voters_card`, `cac_certificate`, `utility_bill` |
| Kenya         | `kenya_id`, `passport`                                                                         |
| Ghana         | `passport`                                                                                     |
| Canada        | `passport`                                                                                     |
| USA           | `passport`                                                                                     |
| Côte d'Ivoire | `passport`                                                                                     |

`passport` is the only type valid across every supported country. All other types are specific to the country listed. Kenya's national ID uses its own value, `kenya_id` — it is not interchangeable with `national_id`, which is Nigeria's NIN slip/card.

<Note>
  `document_front` and `document_back` are optional per document type — recommended for two-sided documents (`national_id`, `kenya_id`, `drivers_license`), where extraction may be less complete with only the front supplied.
</Note>

## Endpoint

```
POST /api/onboarding/document_verification
```

## Request

### Headers

| Header           | Value                 | Required |
| ---------------- | --------------------- | -------- |
| `x-access-token` | Your API secret key   | Yes      |
| `Content-Type`   | `multipart/form-data` | Yes      |

### Body Parameters

| Parameter        | Type   | Required | Description                                                          |
| ---------------- | ------ | -------- | -------------------------------------------------------------------- |
| `document_type`  | string | Yes      | The kind of document being submitted — see Supported Documents above |
| `country`        | string | Yes      | Country the document was issued in — see Supported Documents above   |
| `document_front` | file   | Yes      | Front of the document. JPG or PNG, max 5MB                           |
| `document_back`  | file   | No       | Back of the document. JPG or PNG, max 5MB                            |

### Example

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://adhere-api.smartcomply.com/api/onboarding/document_verification" \
    -H "x-access-token: YOUR_SECRET_KEY" \
    -F "document_type=passport" \
    -F "country=nigeria" \
    -F "document_front=@/path/to/passport.jpg"
  ```

  ```javascript Node.js theme={null}
  const formData = new FormData();
  formData.append("document_type", "passport");
  formData.append("country", "nigeria");
  formData.append("document_front", fs.createReadStream("/path/to/passport.jpg"));

  const response = await fetch(
    "https://adhere-api.smartcomply.com/api/onboarding/document_verification",
    {
      method: "POST",
      headers: { "x-access-token": "YOUR_SECRET_KEY" },
      body: formData,
    }
  );
  const data = await response.json();
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      "https://adhere-api.smartcomply.com/api/onboarding/document_verification",
      headers={"x-access-token": "YOUR_SECRET_KEY"},
      data={"document_type": "passport", "country": "nigeria"},
      files={"document_front": open("/path/to/passport.jpg", "rb")},
  )
  data = response.json()
  ```
</CodeGroup>

## Response

### 200 OK

| Field                | Type    | Description                                                                                                                      |
| -------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `status`             | string  | `"success"` on a successful extraction                                                                                           |
| `data.full_name`     | string  | Extracted full name                                                                                                              |
| `data.first_name`    | string  | Extracted first name                                                                                                             |
| `data.last_name`     | string  | Extracted last name                                                                                                              |
| `data.date_of_birth` | string  | Date of birth in `YYYY-MM-DD` format                                                                                             |
| `data.gender`        | string  | Extracted gender, where present on the document                                                                                  |
| `data.id_number`     | string  | The document's own number (passport number, NIN, license number, etc.)                                                           |
| `data.document_type` | string  | Echoes the `document_type` that was submitted                                                                                    |
| `data.expiry_date`   | string  | Document expiry date, where the document carries one                                                                             |
| `data.is_expired`    | boolean | Whether `expiry_date` has already passed                                                                                         |
| `data.photo`         | string  | Base64-encoded face photo extracted from the document. `null` for `cac_certificate` and `utility_bill`, which don't carry a face |
| `message`            | string  | Human-readable result summary                                                                                                    |

```json theme={null}
{
  "status": "success",
  "data": {
    "valid": true,
    "first_name": "TUNDE",
    "last_name": "AYODELE",
    "full_name": "AYODELE TUNDE",
    "date_of_birth": "2002-02-16",
    "id_number": "A12345678",
    "id_type": "passport",
    "document_type": "passport",
    "expiry_date": "2030-01-01",
    "is_expired": false,
    "photo": "/9j/4AAQSkZJRgABAQAAAQABAAD..."
  },
  "message": "Document details retrieved successfully"
}
```

<Note>
  Not every field is present on every document type — `cac_certificate` and `utility_bill` never populate `photo`, and fields that genuinely aren't visible or present on the document (e.g. `gender` on some documents) come back absent rather than guessed.
</Note>

### 400 Bad Request

Returned for invalid input (unsupported `document_type`/`country`, wrong file type, file too large) or when the document itself fails OCR's own quality checks (blurry, wrong document type, glare, etc.) — `message` carries the specific reason in either case.

```json theme={null}
{
  "status": "failed",
  "data": [],
  "message": "ID photo is too blurry — please retake in good lighting with a steady hand"
}
```

### 401 Unauthorized

Returned when the `x-access-token` header is missing or invalid.

```json theme={null}
{
  "status": "failed",
  "message": "Authentication credentials were not provided."
}
```

<Note>
  For a full list of error codes, see the [Error Codes](/error_codes) reference.
</Note>


## OpenAPI

````yaml POST /api/onboarding/document_verification
openapi: 3.0.3
info:
  title: Adhere API
  description: >-
    Identity verification, credit checks, transaction monitoring, and loan fraud
    detection across Africa.
  version: 3.0.0
servers:
  - url: https://adhere-api.smartcomply.com
    description: Production
security:
  - ApiKeyAuth: []
tags:
  - name: Nigeria KYC
  - name: Kenya KYC
  - name: Ghana KYC
  - name: Rwanda KYC
  - name: Uganda KYC
  - name: Document Verification
  - name: Biometrics
  - name: Individual Credit
  - name: Business Credit
  - name: Transaction Monitoring
  - name: Transaction Screening
  - name: Transaction KYC
  - name: Loan Fraud
  - name: User Journey
paths:
  /api/onboarding/document_verification:
    post:
      tags:
        - Document Verification
      summary: Document Verification
      description: >
        Extract identity details from a photo of a document using OCR — no face
        match, no liveness. Fallback for the number-lookup checks (Passport,
        Driver's License, NIN with Face, VNIN, Voter's ID) while those are
        unavailable. Which document_type values are valid depends on country —
        see the Supported Documents table on this page.
      operationId: documentVerification
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required:
                - document_type
                - country
                - document_front
              properties:
                document_type:
                  type: string
                  enum:
                    - national_id
                    - passport
                    - drivers_license
                    - voters_card
                    - kenya_id
                    - cac_certificate
                    - utility_bill
                  description: >
                    The kind of document being submitted. Which values are valid
                    depends on country — passport works for every supported
                    country; the rest are country-specific.
                  example: passport
                country:
                  type: string
                  enum:
                    - nigeria
                    - kenya
                    - ghana
                    - canada
                    - usa
                    - cote d'ivoire
                  description: Country the document was issued in.
                  example: nigeria
                document_front:
                  type: string
                  format: binary
                  description: Front of the document. JPG or PNG, max 5MB.
                document_back:
                  type: string
                  format: binary
                  description: >
                    Back of the document. Optional for every type, but
                    recommended for two-sided documents (national_id, kenya_id,
                    drivers_license) — extraction may be less complete without
                    it.
      responses:
        '200':
          description: Document details extracted successfully
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
components:
  responses:
    BadRequest:
      description: Bad Request
      content:
        application/json:
          schema:
            type: object
            properties:
              status:
                type: string
                example: failed
              data:
                type: array
                items: {}
              message:
                type: string
    Unauthorized:
      description: Unauthorized
      content:
        application/json:
          schema:
            type: object
            properties:
              status:
                type: string
                example: failed
              message:
                type: string
                example: Authentication credentials were not provided.
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-access-token
      description: Your Adhere API secret key

````