Raw examination questions by subject, exam type, and year — the foundation layer every other endpoint builds on.
The Questions endpoint returns examination questions sourced from WAEC, JAMB, NECO, POST-UTME, and state boards. Every question carries its options, correct answer, and exam context — subject, year, and exam type are normalised so you never have to clean the data yourself.
L1 is intentionally narrow. It does not return topic, difficulty, or explanation — that's 2.2 Metadata and 2.3 Explanations. You pay 1 credit per request regardless of how many questions a filtered call returns.
At least one filter — subject, examType, or year — is required on every call. This isn't a quirk, it's by design: unfiltered access is how datasets like this get scraped wholesale.
Pass your API key in the X-API-Key header on every request. Full setup is covered in 1.1 Authentication — the short version:
subjectstringone of threeSubject name, e.g. mathematicsexamTypeenumone of threewaec · neco · jamb · post_utme · stateyearintegerone of threeExamination year, 1990–2030topicL2stringnoFilter by topic — requires Developer+ tierdifficultyL2int 1–5noFilter by difficulty score — requires Developer+ tiercountrystringno2-letter ISO code, e.g. NGrandombooleannoRandom order, capped at 10 resultscursorstringnoPagination cursor from a previous responselimitint ≤50noResults per page — default 20curl "https://dev.aloc.com.ng/api/v1/questions?subject=mathematics&examType=jamb&year=2019" \
-H "X-API-Key: alc_live_7f3a91c2d8e4f1ab92dd"{
"data": [
{
"id": "f47ac10b-58cc...",
"text": "What is the value of x...",
"options": { "a": "3", "b": "5", "c": "7", "d": "10" },
"correctAnswer": "b",
"examType": "jamb",
"subject": "mathematics",
"year": 2019,
"country": "NG"
}
],
"pagination": { "nextCursor": "eyJpZCI6Mj...", "hasMore": true },
"meta": { "creditsUsed": 1, "tier": "growth" }
}Results page with an opaque cursor, not an offset. Pass pagination.nextCursor from one response as the cursor param on the next call. When hasMore is false, you're at the end of the result set.
There's no sequential offset mode and no plan tier unlocks one. Access is session and search-based by design — see 2.1.7 Exam sessions for the structured alternative.
Filtered list calls are fine for browsing. For an actual exam paper or practice test — where a candidate needs a fixed, non-repeating set of questions — use a session instead. It's the pattern the API expects for structured exams, and it's why sequential pagination doesn't exist on this endpoint: a session allocates the questions once, server-side, rather than letting a client page through the whole bank.
Allocate a set of questions for a subject and exam type. limit defaults to 40, capped at 50. The session — and every question in it — expires in 2 hours.
Fetch the questions allocated to that session. Same shape as a normal /questions response — 1 credit, billed once per session, not per question.
Calling GET /sessions/{id}/questions after the 2-hour window returns 403, not a stale result. Re-issue a new session rather than retrying the old ID.
30 req/min on Free, scaling with tier. Watch X-RateLimit-Remaining rather than counting locally — it's the source of truth.