> 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/education/matric-verification.md).

# Matric Verification

Matric Verification confirms a South African consumer's secondary school qualification against official education records. Use it for employment screening, background checks, bursary eligibility, and detecting fraudulent education credentials.

Two variants are available depending on when the qualification was obtained:

| Variant       | Endpoint                                | Use for                                                                           |
| ------------- | --------------------------------------- | --------------------------------------------------------------------------------- |
| **Pre-1992**  | `/matric-verification/pre-1992/verify`  | Senior Certificate qualifications obtained before 1992                            |
| **Post-1992** | `/matric-verification/post-1992/verify` | National Senior Certificate and related qualifications obtained from 1992 onwards |

The Post-1992 variant additionally requires a `Qualification` field naming the specific certificate type.

The service is **asynchronous**: the initial request returns immediately with a `PENDING` status and a transaction ID. The final result is produced in the background and retrieved using that transaction ID.

## When to use this

Use this service to:

* Verify a matric qualification claim during pre-employment screening
* Check the validity of secondary education credentials
* Detect fraudulent education claims on CVs and applications
* Support compliance for roles with minimum education requirements

## How it works

Submit the consumer's name, ID number, and (for Post-1992) the qualification type in a single POST request to the appropriate variant endpoint. The service immediately accepts the request, creates a tracking transaction, and returns a `transaction_id` with `screening_result: "PENDING"`. The actual verification is processed in the background. Once complete, fetch the final result using the transaction endpoint.

| Property              | Value                                                    |
| --------------------- | -------------------------------------------------------- |
| Response type         | `Asynchronous`                                           |
| Typical response time | Immediate ack; final result usually within a few minutes |
| Result retrieval      | Poll `GET /transactions/{transaction_id}`                |
| Consent required      | `Yes`                                                    |
| Region                | South Africa                                             |

***

## Authentication

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

***

## Endpoints

{% tabs %}
{% tab title="Pre-1992" %}

```http
POST /matric-verification/pre-1992/verify
```

{% endtab %}

{% tab title="Post-1992" %}

```http
POST /matric-verification/post-1992/verify
```

{% endtab %}
{% endtabs %}

***

## 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                                                 |
| `LastName`                     | string  | Yes                | Consumer's surname                                                    |
| `ConsentObtainedByDataSubject` | boolean | Yes                | Must be `true`. Confirms POPIA consent.                               |
| `Qualification`                | string  | **Post-1992 only** | The qualification type. Must match one of the supported values below. |
| `SecondName`                   | string  | No                 | Middle name                                                           |
| `BirthDate`                    | string  | No                 | Date of birth (`YYYY-MM-DD`). Derived from `IdentityNo` if omitted.   |
| `ReferenceNo`                  | string  | No                 | Your internal reference, echoed in audit logs                         |

### Supported `Qualification` values (Post-1992)

* `Senior Certificate`
* `National Senior Certificate`
* `National Technical Certificate N1-N4`
* `National Certificate Vocational`
* `General Education and Training Certificate for Adults (GETC: ABET)`
* `General Education and Training Certificate for Adults (GETCA) - NQF 1`
* `National Senior Certificate for Adults (NASCA) - NQF 4`

Submitting any other value will return an HTTP 422 error listing the allowed values.

### Example request

{% tabs %}
{% tab title="Pre-1992" %}

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

{% endtab %}

{% tab title="Post-1992" %}

```json
{
  "IdentityNo": "9501015800086",
  "FirstName": "Jane",
  "LastName": "Doe",
  "Qualification": "National Senior Certificate",
  "ConsentObtainedByDataSubject": true
}
```

{% endtab %}
{% endtabs %}

***

## Response (initial acknowledgement)

The initial response confirms the request was accepted. The verification itself runs in the background.

### Response fields

| Field                  | Type   | Description                                                              |
| ---------------------- | ------ | ------------------------------------------------------------------------ |
| `transaction_id`       | string | Unique identifier for this request. Use it to retrieve the final result. |
| `screening_result`     | string | Initial status - always `PENDING` on the first response                  |
| `response_description` | string | Human-readable status message                                            |

### Example response - accepted

```json
{
  "transaction_id": "d41d8cd98f00b204e9800998ecf8427e",
  "screening_result": "PENDING",
  "response_description": "Request accepted and is being processed."
}
```

***

## Retrieving the final result

Once the verification has been processed in the background, fetch the final result using the transaction ID:

```http
GET /transactions/{transaction_id}
Authorization: Bearer {your_access_token}
```

The `screening_result` will transition from `PENDING` to one of:

| Result   | Meaning                                               |
| -------- | ----------------------------------------------------- |
| `ACCEPT` | The matric qualification was verified against records |
| `REVIEW` | A partial match was found that requires manual review |
| `REJECT` | The qualification could not be verified               |
| `FAILED` | The verification could not be completed               |

**Recommended polling:** every 5 seconds, up to 2 minutes. If the result is still `PENDING` after 2 minutes, switch to a longer interval with exponential backoff.

***

## 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 `Qualification` not in the allowed list | See `details.allowed_values` or `details.missing_fields` |
| 500  | `server_error`  | Unexpected error                                                   | Contact support                                          |

***

## Code examples

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

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

# Pre-1992
curl -X POST "$BASE_URL/matric-verification/pre-1992/verify" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "IdentityNo": "8601015800086",
    "FirstName": "John",
    "LastName": "Smith",
    "ConsentObtainedByDataSubject": true
  }'

# Post-1992
curl -X POST "$BASE_URL/matric-verification/post-1992/verify" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "IdentityNo": "9501015800086",
    "FirstName": "Jane",
    "LastName": "Doe",
    "Qualification": "National Senior Certificate",
    "ConsentObtainedByDataSubject": true
  }'
```

{% endtab %}

{% tab title="Python" %}

```python
import time
import requests

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

# Submit a Post-1992 verification
response = requests.post(
    f"{BASE_URL}/matric-verification/post-1992/verify",
    headers=headers,
    json={
        "IdentityNo": "9501015800086",
        "FirstName": "Jane",
        "LastName": "Doe",
        "Qualification": "National Senior Certificate",
        "ConsentObtainedByDataSubject": True,
    },
)
transaction_id = response.json()["transaction_id"]
print(f"Submitted, transaction_id={transaction_id}")

# Poll for the final result
for _ in range(24):  # up to 2 minutes
    time.sleep(5)
    result = requests.get(f"{BASE_URL}/transactions/{transaction_id}", headers=headers).json()
    if result["screening_result"] != "PENDING":
        print(f"Final result: {result['screening_result']}")
        break
```

{% endtab %}

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

```javascript
const BASE_URL = "https://consumer-service-api.fraudcheckonline.co.za/consumer-service";
const headers = {
  Authorization: `Bearer ${accessToken}`,
  "Content-Type": "application/json",
};

// Submit a Pre-1992 verification
const submit = await fetch(`${BASE_URL}/matric-verification/pre-1992/verify`, {
  method: "POST",
  headers,
  body: JSON.stringify({
    IdentityNo: "8601015800086",
    FirstName: "John",
    LastName: "Smith",
    ConsentObtainedByDataSubject: true,
  }),
});
const { transaction_id } = await submit.json();

// Poll for the final result
for (let i = 0; i < 24; i++) {
  await new Promise(r => setTimeout(r, 5000));
  const res = await fetch(`${BASE_URL}/transactions/${transaction_id}`, { headers });
  const result = await res.json();
  if (result.screening_result !== "PENDING") {
    console.log(`Final result: ${result.screening_result}`);
    break;
  }
}
```

{% 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 the `transaction_id` for each verification in line with POPIA requirements.

***

## FAQ

<details>

<summary>Which variant should I use?</summary>

Use **Pre-1992** for Senior Certificate qualifications obtained before 1992. Use **Post-1992** for National Senior Certificate and other modern qualifications obtained from 1992 onwards. If the consumer is unsure, their year of completion is a reliable guide.

</details>

<details>

<summary>Why does Post-1992 need a <code>Qualification</code> field?</summary>

Multiple qualification types fall under the Post-1992 framework (NSC, NCV, GETC, NASCA, etc.). The field tells the service which records to check.

</details>

<details>

<summary>Why is the result <code>PENDING</code> on the first response?</summary>

This service is asynchronous. The initial response confirms the request was accepted; the actual verification runs in the background and the final result becomes available shortly afterwards.

</details>

<details>

<summary>Do I need to provide <code>BirthDate</code>?</summary>

No. If omitted, it is derived from the South African ID number.

</details>

<details>

<summary>What does each final result mean?</summary>

`ACCEPT` = qualification verified. `REVIEW` = partial match needing manual review. `REJECT` = qualification could not be verified. `FAILED` = the verification could not complete; retry the request.

</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/education/matric-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.
