AS
ALOC Stationdeveloper docs
DOCS/API REFERENCE/QUESTIONS
v1.0.0
FOLIO
VERIFIED
folio 2.1 — api reference

Questions API

Raw examination questions by subject, exam type, and year — the foundation layer every other endpoint builds on.

L1 · 1 creditFree tier+GET /v1/questions

2.1.0Overview

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.

note

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.

2.1.1Authentication

Pass your API key in the X-API-Key header on every request. Full setup is covered in 1.1 Authentication — the short version:

X-API-Key: alc_live_7f3a91c2d8e4f1ab92dd

2.1.2Endpoint

GET/questions
https://dev.aloc.com.ng/api/v1 — production base URL

2.1.3Query parameters

PARAMTYPEREQUIREDDESCRIPTION
subjectstringone of threeSubject name, e.g. mathematics
examTypeenumone of threewaec · neco · jamb · post_utme · state
yearintegerone of threeExamination year, 1990–2030
topicL2stringnoFilter by topic — requires Developer+ tier
difficultyL2int 1–5noFilter by difficulty score — requires Developer+ tier
countrystringno2-letter ISO code, e.g. NG
randombooleannoRandom order, capped at 10 results
cursorstringnoPagination cursor from a previous response
limitint ≤50noResults per page — default 20

2.1.4Example request

curl "https://dev.aloc.com.ng/api/v1/questions?subject=mathematics&examType=jamb&year=2019" \ -H "X-API-Key: alc_live_7f3a91c2d8e4f1ab92dd"

2.1.5Example response

200 OK · 340ms
{
  "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" }
}
RESPONSE LEDGER
X-RateLimit-Limit600
X-RateLimit-Remaining587
X-RateLimit-Reset1750593600
X-Credits-Used1
X-Credits-Remaining41,229

2.1.6Pagination

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.

caution

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.

2.1.7Exam sessions

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.

1
POST/assessments/sessions

Allocate a psychometrically balanced examination paper. count defaults to 40. The session expires in 2 hours for secure, anti-scraping delivery.

{ "sessionId": "3d606754-7713...", "totalQuestions": 40, "expiresAt": "2026-08-30T18:50:00Z" }
2
GET/assessments/sessions/{id}/questions

Fetch the questions allocated to that session. Billed once per assessment assembly, not per individual question.

{ "data": [ { ... }, { ... } ] }
caution

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.

2.1.8Reading Comprehension & Passages

For English Language and Literature subjects, questions based on reading passages include dedicated fields to allow clean UI rendering on frontend applications:

FIELDTYPEDESCRIPTION
hasPassagebooleanReturned as true for English/Literature comprehension questions. Omitted for non-passage and non-English subjects.
sectionstring | nullContains the full reading comprehension passage text. Render this block at the top or side-by-side with the question.
categorystring | nullPassage group identifier (e.g. passage-a, passage-b) linking consecutive questions belonging to the same passage.
tip

When building exam sessions via POST /sessions, passage groups are automatically preserved in order so students see all questions for a passage grouped together. Pass excludePassages: true if you want grammar/vocabulary questions only.

2.1.9Errors

400bad_requestMissing required filter — pass subject, examType, or year
401unauthorizedMissing or invalid API key
403forbiddenParam requires a higher tier, or the session has expired
404not_foundQuestion or session ID doesn't exist
429rate_limitedToo many requests — see Retry-After header

2.1.10Rate limits

30 req/min on Free, scaling with tier. Watch X-RateLimit-Remaining rather than counting locally — it's the source of truth.