Testing with fixture NINs
RandaVerify runs a single production environment at https://api.randaverify.com/v1. Customers integrate and test against the same endpoints they’ll use in live traffic, there is no separate staging URL.
What makes safe integration testing possible is fixture NINs: a small reserved set of 11-digit values that short-circuit upstream NIMC. They return deterministic mock records (or a deterministic 404), do not consume a wallet unit, do not require an active subscription, and do not store anything against your billable usage. Same code path, same response shape, same error semantics, just no real NIMC call and no charge.
Fixture catalogue
Section titled “Fixture catalogue”| NIN | Scenario | What it tests |
|---|---|---|
12345678901 | Happy path: full bio | Your UI binds every field correctly; your success branch debits the right amount of units in your local mirror; your slip render fills every cell. |
12345678902 | Sparse bio: name + DOB + gender only | Your UI handles missing phone, missing address, missing image, missing maiden name gracefully. (Common in production for older NIN registrations.) |
99999999999 | Not found: HTTP 404 | Your error handling for invalid / non-existent NINs. Returns the same 404 NIN not found shape NIMC sends in production. |
Happy path
Section titled “Happy path”curl -X POST https://api.randaverify.com/v1/verify-nin \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"nin": "12345678901", "reason": "corporate"}'Expected response:
{ "data": { "transaction_id": "430000000000000000001", "nin": "12345678901", "fname": "SUMAILA", "mname": "MEMUNAT", "lname": "AKOWE", "dob": "19 AUG 1989", "gender": "F", "phone": "08012345678", "residenceAdress": "123 SAMPLE STREET", "residenceTown": "LAGOS", "residenceState": "LAGOS", "stateOfOrigin": "KOGI", "lgaOfOrigin": "ANKPA", "image": "<base64 JPEG, small grey placeholder; decodes cleanly>" }}The image field returns a valid base64-encoded JPEG (a “FIXTURE NIN” placeholder, not a real photo) so your decode + slip-rendering code can be exercised end-to-end. The transaction_id is stable per fixture, so a CI smoke test can pin it.
Sparse-bio path
Section titled “Sparse-bio path”curl -X POST https://api.randaverify.com/v1/verify-nin \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"nin": "12345678902", "reason": "corporate"}'Expected response, note empty strings for the fields NIMC didn’t return. transaction_id is still present because NIMC always emits one regardless of how much bio is available, but image is empty (sparse-bio records often have no photo):
{ "data": { "transaction_id": "430000000000000000002", "nin": "12345678902", "fname": "ADAEZE", "mname": "", "lname": "NWOSU", "dob": "03 MAR 1995", "gender": "F", "phone": "", "residenceAdress": "", "residenceTown": "", "residenceState": "", "image": "" }}Not-found path
Section titled “Not-found path”curl -i -X POST https://api.randaverify.com/v1/verify-nin \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"nin": "99999999999", "reason": "corporate"}'Expected response:
HTTP/1.1 404 Not FoundContent-Type: application/json
{"detail": "NIN not found"}Use this fixture to confirm your portal surfaces a sensible error message to the end user rather than crashing or showing a blank slip.
Behaviour that’s identical between test mode and live mode
Section titled “Behaviour that’s identical between test mode and live mode”- Authentication flow, password rotation, and token lifetime (60 min)
- Reason validation (
/v1/nimc-reasonsreturns the same NIMC list) - Error code structure, status codes, and
detailstrings - Rate-limit thresholds and 429 responses
- Response shape: your binding code does not need a separate code path for test mode
Behaviour that differs
Section titled “Behaviour that differs”| Aspect | Live (real NIN) | Test (fixture NIN) |
|---|---|---|
| Upstream NIMC | Real NIMC call | Bypassed entirely |
| Unit debit | 1 unit deducted on 200 | 0 units deducted, ever |
| Subscription gate | Required (your org must be active) | Bypassed |
| Storage | Recorded in your org’s transaction history | Recorded with amount: 0 and a fixture: true flag in details |
Wallet units_before / units_after | Visibly decrement | Unchanged |
Wiring fixture NINs into your CI
Section titled “Wiring fixture NINs into your CI”A reasonable pattern: have a smoke-test job in your CI that hits production with a fixture NIN on every deploy of your own service. It costs you nothing and catches regressions in your integration before customers do.
# LoginTOKEN=$(curl -sS -X POST https://api.randaverify.com/v1/login \ -d "username=$RANDAVERIFY_USER&password=$RANDAVERIFY_PASS" \ | jq -r .access_token)
# Happy pathRESULT=$(curl -sS -X POST https://api.randaverify.com/v1/verify-nin \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"nin": "12345678901", "reason": "corporate"}')
echo "$RESULT" | jq -e '.data.lname == "AKOWE"' > /dev/null \ && echo "happy-path smoke passed" \ || { echo "happy-path smoke failed: $RESULT"; exit 1; }
# Not-found pathSTATUS=$(curl -sS -o /dev/null -w "%{http_code}" -X POST https://api.randaverify.com/v1/verify-nin \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"nin": "99999999999", "reason": "corporate"}')
[ "$STATUS" = "404" ] \ && echo "not-found smoke passed" \ || { echo "expected 404, got $STATUS"; exit 1; }Run as a non-blocking check or a hard deploy gate, your call.