> 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/driver-licence-verification.md).

# Driver's Licence Verification

Verifies a **South African-issued** driver's licence  and Professional Driving Permit against the issuing authority's records. The licence holder does not need to be a South African citizen, a foreign national holding a valid **SA-issued licence** can be verified too, but the licence itself must have been issued in South Africa. \
\
This verification is **asynchronous.** the initial call only submits the check; the result becomes available in 24 - 48 Hours

## When to use this

Use this service to:

* Confirm that a submitted driver's licence number, type, and holder identity are valid and on record
* Retrieve licence class, restrictions, issue date, and expiry date for a verified licence
* Verifying a Professional Driving Permit

## How it works

Submit the licence holder's Identity number, name, licence type, and licence number in a single POST request. The request is validated and forwarded for verification; the transaction is created immediately with a `PENDING` result while it's processed.

Poll `GET /driver-licence/status/{transaction_id}` until `results_available` is `true`, then call `GET /driver-licence/results/{transaction_id}` to retrieve the verified licence details.

| Property              | Value                                                                                              |
| --------------------- | -------------------------------------------------------------------------------------------------- |
| Response type         | `Asynchronous`                                                                                     |
| Typical response time | Submission is immediate; result availability in 24 - 48 Hours                                      |
| Result retrieval      | `GET /driver-licence/status/{transaction_id}`, then `GET /driver-licence/results/{transaction_id}` |
| Consent required      | `Yes`                                                                                              |
| Region                | South Africa (SA-issued licences only, regardless of the holder's nationality)                     |

***

## Authentication

All requests require a Bearer token in the `Authorization` header.

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

***

## Endpoints

```http
POST /driver-licence/verify
GET  /driver-licence/status/{transaction_id}
GET  /driver-licence/results/{transaction_id}
```

## 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. If the value does not pass SA ID validation, it is treated as a foreign/passport document and `BirthDate` becomes required.                          |
| `FirstName`                    | string  | Yes         | Licence holder's first name                                                                                                                                                            |
| `LastName`                     | string  | Yes         | Licence holder's surname                                                                                                                                                               |
| `LicenseType`                  | string  | Yes         | One of: `card`, `temporary`, `learners`                                                                                                                                                |
| `LicenseNumber`                | string  | Yes         | The licence number to verify                                                                                                                                                           |
| `ConsentObtainedByDataSubject` | boolean | Yes         | Confirms POPIA consent. Requests without confirmed consent are rejected.                                                                                                               |
| `BirthDate`                    | string  | Conditional | Required only when `IdentityNo` fails SA ID validation (e.g. a passport number)                                                                                                        |
| `CellNo`                       | string  | No          | Licence holder's contact number                                                                                                                                                        |
| `CountryCode`                  | string  | No          | Numeric key for the licence holder's own country/nationality (not the licence's country of issue, which is always South Africa for this service). Defaults to South Africa if omitted. |
| `CostCenter`                   | integer | No          | Client-side cost centre reference, recorded against this transaction for billing/audit purposes                                                                                        |

### Example request

```json
{
  "IdentityNo": "*************",
  "FirstName": "John",
  "LastName": "Smith",
  "LicenseType": "card",
  "LicenseNumber": "**********",
  "CellNo": "0821234567",
  "ConsentObtainedByDataSubject": true
}
```

***

## Response

### POST /driver-licence/verify

Submitting a request never returns a final verification outcome — it confirms the check was accepted for processing.

| Field              | Type    | Description                                         |
| ------------------ | ------- | --------------------------------------------------- |
| `success`          | boolean | `true` if the submission was accepted               |
| `message`          | string  | Human-readable confirmation                         |
| `transaction_id`   | string  | Unique identifier — use this to poll status/results |
| `screening_result` | string  | Always `PENDING` at submission time                 |

```json
{
  "success": true,
  "message": "Driver licence verification submitted successfully.",
  "transaction_id": "d41d8cd98f00b204e9800998ecf8427e",
  "screening_result": "PENDING"
}
```

### GET /driver-licence/status/{transaction\_id}

Poll this endpoint to check whether a result is ready yet.

| Field               | Type    | Description                                                                             |
| ------------------- | ------- | --------------------------------------------------------------------------------------- |
| `transaction_id`    | string  | The transaction being checked                                                           |
| `screening_result`  | string  | `null` while pending; otherwise the current screening result                            |
| `is_complete`       | boolean | `true` once verification processing has finished                                        |
| `results_available` | boolean | Same as `is_complete` — call `GET /driver-licence/results/{transaction_id}` once `true` |
| `message`           | string  | `"Check is still being processed."` or `"Check is complete. Results are available."`    |

### GET /driver-licence/results/{transaction\_id}

Returns the full verified licence record once processing is complete. Also returns whatever partial data exists if called before completion.

| Field                        | Type    | Description                                              |
| ---------------------------- | ------- | -------------------------------------------------------- |
| `success`                    | boolean | `true` if the transaction was found                      |
| `transaction_id`             | string  | The transaction identifier                               |
| `screening_result`           | string  | Current screening result                                 |
| `received_datetime`          | string  | When the original request was received                   |
| `data.first_name`            | string  | Submitted first name                                     |
| `data.last_name`             | string  | Submitted surname                                        |
| `data.identity_no`           | string  | Submitted ID number                                      |
| `data.license_type`          | string  | Submitted licence type                                   |
| `data.license_number`        | string  | Submitted licence number                                 |
| `data.normalized_validity`   | string  | `VALID`, `INVALID`, or `UNKNOWN`                         |
| `data.parsed_license_class`  | string  | Licence class/code, parsed from the supplier response    |
| `data.parsed_issued_date`    | string  | Licence issue date, parsed from the supplier response    |
| `data.parsed_expiry_date`    | string  | Licence expiry date, parsed from the supplier response   |
| `data.parsed_license_number` | string  | Licence number, parsed from the supplier response        |
| `data.parsed_license_type`   | string  | Licence type/category, parsed from the supplier response |
| `data.license_restrictions`  | string  | Any restrictions recorded against the licence            |
| `data.comments`              | string  | Free-text comments recorded by the back-office verifier  |

### Example: completed result

```json
{
  "success": true,
  "message": "Driver licence transaction fetched successfully",
  "transaction_id": "d41d8cd98f00b204e9800998ecf8427e",
  "screening_result": "ACCEPT",
  "received_datetime": "2026-09-01T09:12:03",
  "data": {
    "product_name": "Drivers License Verification South Africa",
    "first_name": "John",
    "last_name": "Smith",
    "identity_no": "*************",
    "license_type": "card",
    "license_number": "**********",
    "comments": "Verified against eNaTIS",
    "license_restrictions": "None",
    "parsed_license_class": "EB",
    "parsed_issued_date": "2019-03-14",
    "parsed_expiry_date": "2029-03-14",
    "parsed_license_number": "**********",
    "parsed_license_type": "Card",
    "normalized_validity": "VALID"
  }
}
```

***

## Errors

| HTTP | Code           | Meaning                                                                                             | Action                                                              |
| ---- | -------------- | --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- |
| 422  | invalid\_input | `LicenseType` is not one of `card`/`temporary`/`learners`, or `CountryCode` is not a recognised key | Correct the field and resubmit                                      |
| 422  | missing\_field | `BirthDate` missing when `IdentityNo` is not a valid SA ID number                                   | Supply `BirthDate` for passport/foreign document submissions        |
| 401  | unauthorized   | Token expired or invalid                                                                            | Refresh the access token                                            |
| 403  | forbidden      | Transaction exists but belongs to a different account                                               | Confirm you're querying with the account that submitted the request |
| 404  | not\_found     | Transaction does not exist                                                                          | Check the `transaction_id`                                          |

***

## Code examples

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

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

# 1. Submit
curl -X POST "$BASE_URL/driver-licence/verify" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "IdentityNo": "*************",
    "FirstName": "John",
    "LastName": "Smith",
    "LicenseType": "card",
    "LicenseNumber": "**********",
    "ConsentObtainedByDataSubject": true
  }'

# 2. Poll status
curl "$BASE_URL/driver-licence/status/$TRANSACTION_ID" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

# 3. Fetch result once results_available is true
curl "$BASE_URL/driver-licence/results/$TRANSACTION_ID" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

{% endtab %}

{% tab title="Python" %}

```python
import requests

BASE_URL = "https://consumer-service-api.fraudcheckonline.co.za/consumer-service"
headers = {"Authorization": f"Bearer {access_token}", "Content-Type": "application/json"}

submit = requests.post(
    f"{BASE_URL}/driver-licence/verify",
    headers=headers,
    json={
        "IdentityNo": "*************",
        "FirstName": "John",
        "LastName": "Smith",
        "LicenseType": "card",
        "LicenseNumber": "**********",
        "ConsentObtainedByDataSubject": True,
    },
)
transaction_id = submit.json()["transaction_id"]

status = requests.get(f"{BASE_URL}/driver-licence/status/{transaction_id}", headers=headers)
if status.json()["results_available"]:
    result = requests.get(f"{BASE_URL}/driver-licence/results/{transaction_id}", headers=headers)
    print(result.json())
```

{% endtab %}
{% endtabs %}

***

## Compliance & consent

Explicit consent must be obtained from the licence holder before submitting a verification request.

`ConsentObtainedByDataSubject` must be set to `true` for all requests. Requests without confirmed consent are rejected.

Proof of consent should be retained in line with POPIA and internal compliance requirements.

***

## FAQ

<details>

<summary>Why doesn't the initial POST return a result?</summary>

Verification is asynchronous — the verification supplier and Fraudcheck's back office process the check after submission. Poll `GET /driver-licence/status/{transaction_id}` until `results_available` is `true`, then fetch `GET /driver-licence/results/{transaction_id}`.

</details>

<details>

<summary>How long does processing take?</summary>

Typically 24-48 hours, depending on back-office processing volume. Poll the status endpoint rather than assuming a fixed delay.

</details>

<details>

<summary>What if the licence holder doesn't have a South African ID number?</summary>

Submit the passport/foreign document number in `IdentityNo` and supply `BirthDate` — this is required whenever `IdentityNo` doesn't pass SA ID checksum validation.

</details>

<details>

<summary>Can this verify a driver's licence issued by another country?</summary>

No. This service only verifies licences issued in South Africa. The licence holder can be a foreign national (a passport-holding non-citizen with an SA-issued licence is supported via `BirthDate`), but the licence itself must be SA-issued  `CountryCode` records the holder's own nationality, not the country whose registry is being checked.

</details>

***

## Changelog

| Date       | Version | Change           |
| ---------- | ------- | ---------------- |
| 2026-09-22 | 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/driver-licence-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.
