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

<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.
</Note>

## 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"`.
</Tip>

### Example

<CodeGroup>
  ```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()
  ```
</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 |
| `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.
</Note>

### 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](/error_codes) reference.
</Note>


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