> For the complete documentation index, see [llms.txt](https://docs.fraudcheck.co.za/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.fraudcheck.co.za/consumer-service/identity/enhanced-identity-verification.md).

# Identity Verification - Enhanced

The enhanced form of identity verification confirms a consumer's identity against official records and returns the official ID photograph along with key biographic details. Two variants are available: an on file variant for faster, cheaper lookups against credit bureau records, and an online variant that queries live records in real time.

## When to use this

Use this service to:

* Retrieve an official ID photograph for KYC documentation
* Verify a consumer's name and ID number during account opening
* Check deceased status to flag potential identity fraud
* Capture an official photograph for onboarding or face-match workflows

## How it works

Submit an ID number, first name, and surname in a single POST request. The service matches the details against identity records and returns a synchronous response containing the verification outcome, biographic data, and a base64-encoded ID photograph (if available). Choose the `onfile` endpoint for faster lookups against recent snapshot data, or the `online` endpoint for real-time lookups against live records. Results can also be retrieved later by transaction ID.

| Property              | Value                                                                              |
| --------------------- | ---------------------------------------------------------------------------------- |
| Response type         | `Synchronous`                                                                      |
| Typical response time | 2–4s (onfile faster than online)                                                   |
| Result retrieval      | Returned inline; also retrievable via `GET /enhanced-idv/results/{transaction_id}` |
| Consent required      | `Yes`                                                                              |
| Region                | South Africa                                                                       |

## Authentication

```http
Authorization: Bearer {your_access_token}
```

## Endpoints

```http
POST /enhanced-idv/verify/onfile
POST /enhanced-idv/verify/online
GET  /enhanced-idv/results/{transaction_id}
```

| Endpoint         | Data freshness                   |
| ---------------- | -------------------------------- |
| `/verify/onfile` | Recent snapshot records (faster) |
| `/verify/online` | Live records (real time)         |

## Request

### Headers

| Header          | Required | Value              |
| --------------- | -------- | ------------------ |
| `Authorization` | Yes      | `Bearer {token}`   |
| `Content-Type`  | Yes      | `application/json` |

### Body parameters

| Field                          | Type    | Required | Description                                         |
| ------------------------------ | ------- | -------- | --------------------------------------------------- |
| `IdentityNo`                   | string  | Yes      | 13-digit South African ID number                    |
| `FirstName`                    | string  | Yes      | Consumer's first name. Must match official records. |
| `LastName`                     | string  | Yes      | Consumer's surname. Must match official records.    |
| `ConsentObtainedByDataSubject` | boolean | Yes      | Must be `true`. Confirms POPIA consent.             |

### Example request

```json
{
  "IdentityNo": "8601015800086",
  "FirstName": "John",
  "LastName": "Smith",
  "ConsentObtainedByDataSubject": true
}
```

## Response

### Response fields

| Field                     | Type    | Description                                       |
| ------------------------- | ------- | ------------------------------------------------- |
| `success`                 | boolean | `true` if the request completed successfully      |
| `transaction_id`          | string  | Unique identifier for this verification           |
| `verification_passed`     | boolean | `true` if submitted details matched records       |
| `consumer_name`           | string  | Full name from official records                   |
| `id_number`               | string  | ID number from records                            |
| `deceased`                | boolean | `true` if the ID holder is marked as deceased     |
| `id_photo_available`      | boolean | Whether an official photograph was returned       |
| `message`                 | string  | Human-readable status message                     |
| `data.ha_names`           | string  | First name(s) from records                        |
| `data.ha_surname`         | string  | Surname from records                              |
| `data.ha_date_of_birth`   | string  | Date of birth (`YYYY-MM-DD`)                      |
| `data.ha_gender`          | string  | `M` or `F`                                        |
| `data.ha_nationality`     | string  | Nationality code                                  |
| `data.ha_marital_status`  | string  | Marital status                                    |
| `data.id_no_match_status` | string  | `Match` or `No Match`                             |
| `data.id_photo`           | string  | Base64-encoded JPEG of the official ID photograph |
| `data.id_photo_hash`      | string  | Integrity hash of the photograph                  |
| `data.id_photo_quality`   | string  | Quality assessment of the photograph              |

### Example response - verified

```json
{
  "success": true,
  "message": "ID verification completed successfully",
  "transaction_id": "d41d8cd98f00b204e9800998ecf8427e",
  "verification_passed": true,
  "consumer_name": "JOHN SMITH",
  "id_number": "8601015800086",
  "deceased": false,
  "id_photo_available": true,
  "data": {
    "ha_names": "JOHN",
    "ha_surname": "SMITH",
    "id_no_match_status": "Match",
    "ha_date_of_birth": "1986-01-15",
    "ha_gender": "M",
    "ha_nationality": "SA",
    "ha_marital_status": "Single",
    "id_photo": "base64_encoded_photo_data...",
    "id_photo_hash": "abc123def456...",
    "id_photo_quality": "Good"
  }
}
```

### Example response - ID not found

```json
{
  "success": false,
  "message": "ID not found in records",
  "transaction_id": "d41d8cd98f00b204e9800998ecf8427e",
  "verification_passed": false,
  "id_number": "8601015800086",
  "deceased": false,
  "id_photo_available": false,
  "data": { "id_no_match_status": "No Match" }
}
```

## Retrieving results later

Re-fetch a previously completed verification by transaction ID:

```http
GET /enhanced-idv/results/{transaction_id}
Authorization: Bearer {your_access_token}
```

## Errors

| HTTP | Code            | Meaning                              | Action                               |
| ---- | --------------- | ------------------------------------ | ------------------------------------ |
| 401  | `unauthorized`  | Token missing or expired             | Refresh your access token            |
| 403  | `forbidden`     | Account lacks access to this service | Contact your account manager         |
| 422  | `invalid_input` | Required field missing or invalid    | See `details.field`                  |
| 500  | `server_error`  | Unexpected error                     | Retry; contact support if persistent |

> An ID that cannot be found in records returns HTTP `200` with `success: false` and `verification_passed: false` - it is a successful API call with a negative result, not an error.

## Code examples

{% tabs %}
{% tab title="cURL" %}

```bash
BASE_URL="https://consumer-service-api.fraudcheckonline.co.za/consumer-service"

curl -X POST "$BASE_URL/enhanced-idv/verify/onfile" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "IdentityNo": "8601015800086",
    "FirstName": "John",
    "LastName": "Smith",
    "ConsentObtainedByDataSubject": true
  }'
```

{% endtab %}

{% tab title="Python" %}

```python
import base64, requests

BASE_URL = "https://consumer-service-api.fraudcheckonline.co.za/consumer-service"

response = requests.post(
    f"{BASE_URL}/enhanced-idv/verify/onfile",
    headers={
        "Authorization": f"Bearer {access_token}",
        "Content-Type": "application/json",
    },
    json={
        "IdentityNo": "8601015800086",
        "FirstName": "John",
        "LastName": "Smith",
        "ConsentObtainedByDataSubject": True,
    },
)
data = response.json()

if data["success"] and data["verification_passed"]:
    print(f"Verified: {data['consumer_name']}")
    if data["data"].get("id_photo"):
        with open("id_photo.jpg", "wb") as f:
            f.write(base64.b64decode(data["data"]["id_photo"]))
```

{% endtab %}

{% tab title="JavaScript (Node.js)" %}

```javascript
const BASE_URL = "https://consumer-service-api.fraudcheckonline.co.za/consumer-service";

const response = await fetch(`${BASE_URL}/enhanced-idv/verify/onfile`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${accessToken}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    IdentityNo: "8601015800086",
    FirstName: "John",
    LastName: "Smith",
    ConsentObtainedByDataSubject: true,
  }),
});
const data = await response.json();

if (data.success && data.data.id_photo) {
  const photoUrl = `data:image/jpeg;base64,${data.data.id_photo}`;
}
```

{% endtab %}
{% endtabs %}

## Compliance & consent

* Obtain explicit consent from the data subject before submitting a request.
* Set `ConsentObtainedByDataSubject` to `true` to confirm consent has been captured.
* Retain proof of consent and any retrieved photographs in line with POPIA requirements.

## FAQ

<details>

<summary>What's the difference between <code>onfile</code> and <code>online</code>?</summary>

`onfile` uses recent snapshot data and is faster. `online` queries live records in real time and reflects the latest information.

</details>

<details>

<summary>What format is the photograph?</summary>

A base64-encoded JPEG returned in `data.id_photo`. Decode it to obtain the binary image.

</details>

<details>

<summary>What does <code>deceased: true</code> mean?</summary>

The ID holder is flagged as deceased in records. Treat this as a strong fraud signal and route to manual review or rejection.

</details>

<details>

<summary>Why might <code>verification_passed</code> be <code>false</code> even when the ID exists?</summary>

Submitted name or surname did not match records. Initials, nicknames, or spelling variants are common causes.

</details>

<details>

<summary>What client timeout should I configure?</summary>

Up to 30 seconds.

</details>

## Changelog

| Date       | Version | Change           |
| ---------- | ------- | ---------------- |
| 2026-04-11 | v1.0    | Initial release. |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.fraudcheck.co.za/consumer-service/identity/enhanced-identity-verification.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
