> ## 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.

# Kenya National ID

> Extract identity details from a Kenyan national ID card.

Verify a customer's Kenyan national ID card by uploading a photo — no manual ID entry required. We read the details and compare the face on the document with a selfie. No liveness check is needed.

> [!NOTE]
>
> This is a two-sided document — supply both `document_front` and `document_back` for the most complete extraction. Kenya has two ID card generations in circulation: the older laminated design and the newer "Maisha Card." Fields specific to the Maisha Card (`serial_number`, `place_of_issue`, expiry date) will come back empty on an older card — that's expected, not an error.

> [!NOTE]
>
> `selfie_image` is required — the face extracted from the document is compared against it. This is a still-image comparison (not liveness).

## Endpoint

```
POST /api/onboarding/document_verification/kenya/kenya_id
```

## 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_front` | file | Yes | Front of the ID card. JPG, PNG or single-page PDF, max 10MB |
| `document_back` | file | No | Back of the ID card. JPG, PNG or single-page PDF, max 10MB |
| `selfie_image` | file | Yes | A selfie to compare against the document's face photo. JPG or PNG, max 5MB |

> [!TIP]
>
> A scanned document can be uploaded as a single-page PDF, for example `-F "document_front=@/path/to/scan.pdf"`.

### Example

```bash cURL theme={null}
curl -X POST "https://adhere-api.smartcomply.com/api/onboarding/document_verification/kenya/kenya_id" \
  -H "x-access-token: YOUR_SECRET_KEY" \
  -F "document_front=@/path/to/id_front.jpg" \
  -F "document_back=@/path/to/id_back.jpg" \
  -F "selfie_image=@/path/to/selfie.jpg"
```

```javascript Node.js theme={null}
const formData = new FormData();
formData.append("document_front", fs.createReadStream("/path/to/id_front.jpg"));
formData.append("document_back", fs.createReadStream("/path/to/id_back.jpg"));
formData.append("selfie_image", fs.createReadStream("/path/to/selfie.jpg"));

const response = await fetch(
  "https://adhere-api.smartcomply.com/api/onboarding/document_verification/kenya/kenya_id",
  {
    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/kenya/kenya_id",
    headers={"x-access-token": "YOUR_SECRET_KEY"},
    files={
        "document_front": open("/path/to/id_front.jpg", "rb"),
        "document_back": open("/path/to/id_back.jpg", "rb"),
        "selfie_image": open("/path/to/selfie.jpg", "rb"),
    },
)
data = response.json()
```

## 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 |
| `data.id_number` | string | The ID number |
| `data.document_type` | string | `"kenya_id"` |
| `data.document_country` | string | The country that issued the document, as a two-letter country code: `"KE"` |
| `data.expiry_date` | string | Maisha Card expiry date — only present on third-generation cards |
| `data.issue_date` | string | Date of issue |
| `data.place_of_issue` | string | Only present on third-generation "Maisha Card" IDs |
| `data.serial_number` | string | Separate 9-digit card serial number — only present on third-generation "Maisha Card" IDs |
| `data.photo` | string | Base64-encoded face photo extracted from the document |
| `data.extra_fields` | object | Other fields printed on the card — see below |
| `data.face_match` | object | Result of comparing the document's face against `selfie_image` — see below |
| `data.face_match.attempted` | boolean | Whether a comparison was actually run |
| `data.face_match.verified` | boolean \| null | `true`/`false` if the comparison ran; `null` if it couldn't (see Face Match Notes) |
| `data.face_match.decision` | string | `"MATCH"` or `"NO_MATCH"` |
| `data.face_match.confidence_percentage` | number | Match confidence, 0–100 |
| `data.face_match.compare_mode` | string | `"COMPARISON_NO_LIVENESS"` means the two photos were compared without a liveness check |
| `data.face_match.selfie_image` | string | URL of the uploaded selfie |
| `message` | string | Human-readable result summary |

```json theme={null}
{
  "status": "success",
  "data": {
    "valid": true,
    "first_name": "WANJIRU",
    "last_name": "KAMAU",
    "full_name": "KAMAU WANJIRU",
    "date_of_birth": "1995-03-10",
    "id_number": "34567890",
    "document_type": "kenya_id",
    "document_country": "KE",
    "issue_date": "2019-05-14",
    "place_of_issue": "NAIROBI",
    "serial_number": "123456789",
    "photo": "/9j/4AAQSkZJRgABAQAAAQABAAD...",
    "extra_fields": {
      "district_of_birth": "NAIROBI",
      "district": "NAIROBI",
      "division": "CENTRAL",
      "location": "NAIROBI CENTRAL",
      "sub_location": "CBD",
      "barcode_number": "12345678",
      "mrz_line1": "IDKEN3456789012<<<<<<<<<<<<<<<",
      "mrz_line2": "9503109F2905147KEN<<<<<<<<<<<8",
      "mrz_line3": "KAMAU<<WANJIRU<<<<<<<<<<<<<<<<"
    },
    "face_match": {
      "attempted": true,
      "verified": true,
      "decision": "MATCH",
      "confidence_percentage": 92.4,
      "compare_mode": "COMPARISON_NO_LIVENESS",
      "selfie_image": "https://.../selfie.jpg"
    }
  },
  "message": "Document details retrieved successfully"
}
```

> [!NOTE]
>
> **Extra Fields** — `extra_fields` carries whatever else the card printed beyond the fields listed above: `district_of_birth`, and — only when `document_back` was supplied — `district`, `division`, `location`, `sub_location`, `barcode_number`, and the three MRZ lines (`mrz_line1`/`mrz_line2`/`mrz_line3`, exactly as printed, including `<` fill characters — not decoded). Only fields actually present on the card are included.

> [!NOTE]
>
> **Face Match Notes** — if the comparison service itself fails, `attempted` reflects whether a comparison was actually run and `verified` comes back `null` with a `reason` field explaining why — this is different from `verified: false`, which means the comparison ran and the faces didn't match. A face-match problem never blocks the underlying document data — the rest of `data` is still returned.

### 400 Bad Request

```json theme={null}
{
  "status": "failed",
  "data": [],
  "message": "This document is not supported for the selected ID type — please upload the correct document."
}
```

### 401 Unauthorized

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

> [!NOTE]
>
> For a full list of error codes, see the [Error Codes](https://docs.smartcomply.com/error_codes.md) reference.


## OpenAPI

````yaml POST /api/onboarding/document_verification/kenya/kenya_id
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/kenya/kenya_id:
    post:
      tags:
        - Document Verification
      summary: Document Verification — Kenya ID
      description: >
        Extract identity details from a Kenyan ID card (older laminated design
        or newer Maisha Card), plus a required face match against a selfie.
        Fields specific to the Maisha Card (serial_number, place_of_issue,
        expiry date) come back empty on an older card — that's expected, not an
        error. document_type and country are fixed by this URL — no need to send
        them in the request body.
      operationId: documentVerificationKenyaId
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required:
                - document_front
              properties:
                document_front:
                  type: string
                  format: binary
                  description: Front of the ID card. JPG, PNG or single-page PDF, max 10MB.
                document_back:
                  type: string
                  format: binary
                  description: >
                    Back of the card. Optional, but recommended — extraction may
                    be less complete without it. JPG, PNG or single-page PDF,
                    max 10MB.
                selfie_image:
                  type: string
                  format: binary
                  description: >
                    A selfie to compare against the face extracted from the
                    document. JPG or PNG, max 5MB. Required.
      responses:
        '200':
          $ref: '#/components/responses/DocumentVerificationSuccess'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
components:
  responses:
    DocumentVerificationSuccess:
      description: Document details extracted successfully
      content:
        application/json:
          schema:
            type: object
            properties:
              status:
                type: string
                example: success
              data:
                type: object
                properties:
                  valid:
                    type: boolean
                  first_name:
                    type: string
                  last_name:
                    type: string
                  full_name:
                    type: string
                  date_of_birth:
                    type: string
                  gender:
                    type: string
                  nationality:
                    type: string
                  address:
                    type: string
                  id_number:
                    type: string
                  serial_number:
                    type: string
                  id_type:
                    type: string
                  document_type:
                    type: string
                  document_country:
                    type: string
                    description: >
                      Passports only. The country that issued the passport, as
                      an two-letter country code, for example RW.
                  expiry_date:
                    type: string
                  issue_date:
                    type: string
                  is_expired:
                    type: boolean
                    description: >
                      Always false on a 200. An expired document fails the check
                      with a 400; its details are still returned in data, with
                      is_expired true.
                  photo:
                    type: string
                    description: >-
                      Base64-encoded face photo extracted from the document.
                      Absent for document types with no face photo
                      (cac_certificate, utility_bill).
                  extra_fields:
                    type: object
                    description: >-
                      Every other field read from the document that doesn't have
                      its own dedicated field above. Varies by document_type and
                      country.
                  face_match:
                    type: object
                    description: Present only when selfie_image was supplied.
                    properties:
                      attempted:
                        type: boolean
                      verified:
                        type: boolean
                        nullable: true
                        description: >-
                          true/false if the comparison ran; null if it couldn't
                          (see reason).
                      decision:
                        type: string
                        enum:
                          - MATCH
                          - NO_MATCH
                        description: The comparison's verdict.
                      confidence_percentage:
                        type: number
                      compare_mode:
                        type: string
                        example: COMPARISON_NO_LIVENESS
                        description: >
                          COMPARISON_NO_LIVENESS: the two photos are compared;
                          no liveness check is run on the selfie.
                      selfie_image:
                        type: string
                        description: URL of the uploaded selfie.
                      reason:
                        type: string
                        description: >-
                          Present when verified is null — explains why the
                          comparison couldn't run or complete.
              message:
                type: string
                example: Document details retrieved successfully
    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

````

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