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

# Passport

> Verify a passport from any country.

Verify a customer's passport from any country by uploading a photo of the data page. We read the details, confirm which country issued the passport, and compare the face on the passport with a selfie.

> [!NOTE]
>
> Passport is single-sided. Only `document_front` is needed.

> [!NOTE]
>
> `country` is optional. Send it when you know which country issued the passport. Leave it out and we detect the country from the passport itself.

## Supported countries

You can verify a passport from any country, including Nigeria, Kenya, Ghana, Côte d'Ivoire, Canada, United States, United Kingdom, Australia, Burundi, China, Congo, Ethiopia, Gambia, India, Indonesia, Japan, Rwanda, Sierra Leone, Somalia, South Africa, South Sudan, Tanzania, Togo, Uganda, Zimbabwe and other countries.

## Endpoint

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

## 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 | Photo or scan of the passport data page. JPG, PNG or single-page PDF, max 10MB |
| `selfie_image` | file | Yes | A selfie to compare against the face on the passport. JPG or PNG, max 5MB |
| `country` | string | No | The country that issued the passport, as a two-letter country code, for example `RW`. Leave it out to have it detected |

> [!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/passport" \
  -H "x-access-token: YOUR_SECRET_KEY" \
  -F "document_front=@/path/to/passport.jpg" \
  -F "selfie_image=@/path/to/selfie.jpg" \
  -F "country=RW"
```

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

const response = await fetch(
  "https://adhere-api.smartcomply.com/api/onboarding/document_verification/passport",
  {
    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/passport",
    headers={"x-access-token": "YOUR_SECRET_KEY"},
    data={"country": "RW"},  # optional
    files={
        "document_front": open("/path/to/passport.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.nationality` | string | Extracted nationality |
| `data.id_number` | string | The passport number |
| `data.document_type` | string | `"passport"` |
| `data.document_country` | string | The country that issued the passport, as a two-letter country code, for example `"RW"` |
| `data.expiry_date` | string | Passport expiry date |
| `data.is_expired` | boolean | Always `false` on a 200. An expired passport fails the check (see [Expired passports](#expired-passports)) |
| `data.photo` | string | Base64-encoded face photo extracted from the passport |
| `data.extra_fields` | object | Other fields read from the data page, such as `place_of_birth`, `place_of_issue`, `issuing_authority`, and `mrz_line1`/`mrz_line2` when the machine-readable zone was legible |
| `data.face_match` | object | Result of comparing the face on the passport with `selfie_image` |
| `data.face_match.attempted` | boolean | Whether a comparison was run |
| `data.face_match.verified` | boolean \| null | `true` or `false` if the comparison ran; `null` if it couldn't run |
| `data.face_match.decision` | string | `"MATCH"` or `"NO_MATCH"` |
| `data.face_match.confidence_percentage` | number | Match confidence, 0 to 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": "Nassra Nassor",
    "last_name": "Ngarango",
    "full_name": "Nassra Nassor Ngarango",
    "date_of_birth": "1990-05-20",
    "gender": "F",
    "nationality": "TANZANIAN",
    "id_number": "TAE661142",
    "document_type": "passport",
    "document_country": "TZ",
    "expiry_date": "2033-11-08",
    "is_expired": false,
    "photo": "/9j/4AAQSkZJRgABAQAAAQABAAD...",
    "extra_fields": {
      "place_of_birth": "KINONDONI",
      "place_of_issue": "PCO, DAR ES SALAAM",
      "issuing_authority": "PCO, DAR ES SALAAM",
      "mrz_line1": "P<TZANGARANGO<<NASSRA<NASSOR<<<<<<<<<<<<<<<<",
      "mrz_line2": "TAE6611429TZA9005204F3311086<<<<<<<<<<<<<<06"
    },
    "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]
>
> **Face match:** `verified: false` with `decision: "NO_MATCH"` means the comparison ran and the faces didn't match. `verified: null` with a `reason` means the comparison couldn't run, for example because no face was found in the selfie. A face-match problem never blocks the passport data: the rest of `data` is still returned.

### 400 Bad Request

The passport wasn't issued by the `country` you sent:

```json theme={null}
{
  "status": "failed",
  "data": {
    "error_code": "VERIFICATION_FAILED"
  },
  "message": "Document Verification - Passport check failed: This document wasn't issued by the country you chose. Please upload a document from that country"
}
```

Passports from this country can't be verified:

```json theme={null}
{
  "status": "failed",
  "data": [],
  "message": "Passports from this country can't be verified."
}
```

The photo can't be read, for example because part of the passport is cut off:

```json theme={null}
{
  "status": "failed",
  "data": {
    "error_code": "VERIFICATION_FAILED"
  },
  "message": "Document Verification - Passport check failed: Part of the document is cut off in the photo. Please retake with all edges and corners fully visible."
}
```

### Expired passports

An expired passport fails the check. The extracted details are still returned in `data`, with `is_expired: true`:

```json theme={null}
{
  "status": "failed",
  "data": {
    "first_name": "Nassra Nassor",
    "last_name": "Ngarango",
    "id_number": "TAE661142",
    "document_type": "passport",
    "document_country": "TZ",
    "expiry_date": "2021-11-08",
    "is_expired": true
  },
  "message": "Document Verification - Passport check failed: Document has expired."
}
```

### 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/passport
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/passport:
    post:
      tags:
        - Document Verification
      summary: Document Verification — Global Passport
      description: >
        Verify a passport from any country, plus a required face match against a
        selfie. Send country when you know which country issued the passport;
        leave it out and the country is detected from the passport. The issuing
        country is returned as document_country.
      operationId: documentVerificationGlobalPassport
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required:
                - document_front
                - selfie_image
              properties:
                document_front:
                  type: string
                  format: binary
                  description: >
                    Photo or scan of the passport data page. JPG, PNG or
                    single-page PDF, max 10MB.
                selfie_image:
                  type: string
                  format: binary
                  description: >
                    A selfie to compare against the face on the passport. JPG or
                    PNG, max 5MB.
                country:
                  type: string
                  example: RW
                  description: >
                    Optional. The country that issued the passport, as an
                    two-letter country code. Leave it out to have it detected.
      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.