Academic Reference Data
Resolve the faculty_id and department_id claims you receive at sign-in to human-readable names by reading Campus One's faculty and department catalog.
Academic Reference Data API
When a student signs in with the academic scope, Campus One returns faculty_id and department_id claims. These are stable Campus One identifiers — not display names. To show "Faculty of Engineering" instead of fac_eng, or to match the student into your own faculties / departments tables, you need the catalog those IDs come from.
These two read-only endpoints expose that catalog so your app can map the IDs once and keep its own tables in sync.
GET /api/apps/faculties— every faculty, each with its departments nested.GET /api/apps/departments— a flat list of every department, each carrying itsfacultyIdandfacultyName.
Authentication & Authorization
These are standard Connected App API routes and use the same Bearer auth as every other /api/apps/* endpoint.
- Required scope:
academic - Method: Bearer Token Authentication
- Header format:
Authorization: Bearer <access_token> - Admin prerequisite: the
permAcademicflag must be enabled for your app (it is on by default) under Permissions in the developer dashboard.
The token must carry the academic scope — the same scope that delivers the faculty_id / department_id claims you are resolving. A token without it returns 403. See Permissions & Scopes.
[!NOTE] This catalog is platform-wide reference data, not per-student data, so the response is identical for every authorized user. The response is cached server-side for one hour, so changes to the catalog (rare) may take up to an hour to appear.
REST API Reference
List faculties
GET /api/apps/faculties
Returns every faculty ordered by name, each with its departments nested (also ordered by name). Use this when you want the faculty → department hierarchy in a single call.
Headers
| Header | Type | Description |
|---|---|---|
Authorization | string | Required. Bearer <access_token> containing the academic scope. |
List departments
GET /api/apps/departments
Returns a flat list of every department ordered by name. Each row includes facultyId and facultyName, so you can resolve a student's department_id to a name (and its parent faculty) without joining anything client-side.
Headers
| Header | Type | Description |
|---|---|---|
Authorization | string | Required. Bearer <access_token> containing the academic scope. |
Example Integration
A typical flow: at sign-in you receive department_id in the claims; you call GET /api/apps/departments once, build a Map<id, name>, and cache it.
# Faculties with nested departments
curl https://auth.campusone.com.ng/api/apps/faculties \
-H "Authorization: Bearer c1_act_abc123xyz"
# Flat department list
curl https://auth.campusone.com.ng/api/apps/departments \
-H "Authorization: Bearer c1_act_abc123xyz"// Build a lookup from department_id -> { name, faculty } once, then reuse it
// to resolve the `department_id` claim you get at sign-in.
const loadDepartments = async (accessToken) => {
const response = await fetch(
'https://auth.campusone.com.ng/api/apps/departments',
{ headers: { Authorization: `Bearer ${accessToken}` } }
);
if (!response.ok) {
const err = await response.json();
throw new Error(`Failed to load departments: ${err.message ?? err.error}`);
}
const departments = await response.json();
return new Map(
departments.map((d) => [d.id, { name: d.name, faculty: d.facultyName }])
);
};
const byId = await loadDepartments(accessToken);
const dept = byId.get(claims.department_id); // { name, faculty }import requests
headers = {"Authorization": "Bearer c1_act_abc123xyz"}
res = requests.get(
"https://auth.campusone.com.ng/api/apps/departments",
headers=headers,
)
res.raise_for_status()
# department_id -> { "name", "faculty" }
by_id = {
d["id"]: {"name": d["name"], "faculty": d["facultyName"]}
for d in res.json()
}
dept = by_id.get(claims["department_id"])Response Schemas
[!NOTE] The live, always-accurate schemas are published at the interactive API reference. The examples below are illustrative.
GET /api/apps/faculties → 200 OK
An array of faculties, each with its departments nested.
[
{
"id": "fac_eng",
"name": "Faculty of Engineering",
"slug": "engineering",
"createdAt": "2026-01-10T08:00:00.000Z",
"departments": [
{
"id": "dept_cs",
"name": "Computer Science",
"slug": "computer-science",
"maxLevel": 400,
"facultyId": "fac_eng",
"createdAt": "2026-01-10T08:00:00.000Z"
}
]
}
]GET /api/apps/departments → 200 OK
A flat array of departments, each carrying its parent faculty.
[
{
"id": "dept_cs",
"name": "Computer Science",
"slug": "computer-science",
"maxLevel": 400,
"facultyId": "fac_eng",
"facultyName": "Faculty of Engineering"
}
][!TIP]
maxLevelis the highest level a student in that department can reach (e.g.400or500). Thefinal_yearclaim istrueonce a student'slevelequals their department'smaxLevel.
Error responses
A 401 (authentication) is rejected at the gateway and returns { "error": "..." }. A 403 (authorization) comes from the endpoint and returns the richer { code, status, message } object. See Status Codes & Errors for the canonical reference.
{ "defined": false, "code": "FORBIDDEN", "status": 403, "message": "Token lacks 'academic' scope" }| Status | Body | Cause |
|---|---|---|
200 | array | Request succeeded; body is the faculty or department list. |
401 | { error } | Bearer token missing, malformed, expired, revoked, or not bound to a user. |
403 | { code, status, message } | Token lacks the academic scope, or the app's permAcademic flag is disabled. |