Verify a record
/verificationsVerify a student's record
issuer plus the identifiers that registry asks for. If the record exists, the response returns the candidate's name, school, and full subject-by-subject results.Verification is a paid feature. You need a live API key, and every live lookup is billed per request under your partner agreement (contact us for rates). The public trial key is free and answers only from sandbox demo records — see “Try it” below.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
issuerrequired | body | string | Registry codename — picking one switches which fields apply below. |
national_idrequired | body | string | NESA — the candidate's 16-digit Rwandan national ID. |
exam_numberrequired | body | string | NESA — index number printed on the examination slip. |
levelrequired | body | string | NESA — which national examination to check. |
index_numberrequired | body | string | UNEB — centre/candidate index number. |
levelrequired | body | string | UNEB — which examination to check. |
yearrequired | body | string | UNEB — examination year. |
index_numberrequired | body | string | KNEC — candidate index number. |
examinationrequired | body | string | KNEC — which examination to check. |
yearrequired | body | string | KNEC — examination year. |
404 means the registry holds no record matching the identifiers — the credential could not be confirmed. A 400 lists which fields the chosen registry requires.Example response
{
"code": 200,
"result": "authentic",
"issuer": {
"code": "NESA",
"name": "National Examination and School Inspection Authority",
"country": "Rwanda"
},
"record": {
"id": "sandbox-rec-nesa-alevel",
"candidate": {
"full_name": "John Doe",
"gender": "male",
"date_of_birth": "2005-08-14"
},
"level": "A-Level",
"year": 2024,
"school": "Lycée de Kigali",
"combination": "PCB (Physics, Chemistry, Biology)",
"subjects": [
{
"subject": "Physics",
"grade": "B"
},
{
"subject": "Chemistry",
"grade": "A"
},
{
"subject": "Biology",
"grade": "A"
},
{
"subject": "General Paper",
"grade": "B"
},
{
"subject": "Entrepreneurship",
"grade": "C"
}
],
"aggregate": "52 / 60"
}
}curl -X POST 'https://api.uapply.africa/api/v1/verifications' \
-H 'Authorization: Bearer YOUR_KEY' \
-H 'Content-Type: application/json' \
-d '{"issuer":"NESA","national_id":"1200580012345678","exam_number":"100123456","level":"A-Level"}'
Supported registries
Each issuing body is identified by its codename and asks for its own set of
identifiers. Discover them programmatically with
GET /verifications/issuers, or use this table:
| Codename | Registry | Country | Required fields |
|---|---|---|---|
NESA | National Examination and School Inspection Authority | Rwanda | national_id, exam_number, level (P-Level / O-Level / A-Level) |
UNEB | Uganda National Examinations Board | Uganda | index_number, level (PLE / UCE / UACE), year |
KNEC | Kenya National Examinations Council | Kenya | index_number, examination (KCPE / KCSE), year |
More registries are added as integrations land — the issuers endpoint is
always the source of truth.
What comes back
The record's shape follows how the registry reports results:
- NESA A-Level — subject combination (e.g. PCB), per-subject grades, and the aggregate.
- NESA O-Level — per-subject grades and the division.
- UNEB UACE/UCE/PLE — per-subject grades and the points aggregate.
- KNEC KCSE/KCPE — per-subject grades and the mean grade.
Candidate names are returned, not requested — that's the point: you confirm the identifiers you were given, and the registry tells you who they belong to.
Try it with the trial key
The trial key (uap_sandbox_000000000000) is free and resolves to demo
records seeded by the UAPPLY admin — every demo candidate is a John Doe. These
lookups all return a match:
# NESA · A-Level (also try exam_number 200654321 with level O-Level)
curl -X POST "https://api.uapply.africa/api/v1/verifications" \
-H "Authorization: Bearer uap_sandbox_000000000000" \
-H "Content-Type: application/json" \
-d '{"issuer":"NESA","national_id":"1200580012345678","exam_number":"100123456","level":"A-Level"}'
# UNEB · UACE
curl -X POST "https://api.uapply.africa/api/v1/verifications" \
-H "Authorization: Bearer uap_sandbox_000000000000" \
-H "Content-Type: application/json" \
-d '{"issuer":"UNEB","index_number":"U0010/123","level":"UACE","year":"2024"}'
# KNEC · KCSE
curl -X POST "https://api.uapply.africa/api/v1/verifications" \
-H "Authorization: Bearer uap_sandbox_000000000000" \
-H "Content-Type: application/json" \
-d '{"issuer":"KNEC","index_number":"20406001001","examination":"KCSE","year":"2023"}'
Any other identifiers return 404 Record not found. Swap in your uap_live_
key to query real registries — and remember those lookups are billed.
Errors
| Status | Meaning |
|---|---|
400 | Unknown issuer codename, or missing/invalid registry fields (the response lists them). |
401 | The API key is missing or invalid. |
404 | The registry has no record matching the supplied identifiers. |
{
"code": 404,
"error": "Record not found",
"message": "NESA has no record matching the supplied identifiers.",
"issuer": { "code": "NESA", "name": "National Examination and School Inspection Authority", "country": "Rwanda" }
}