Build on the
Academic Identity Network
SchoolCore is not just a school management platform — it is the identity infrastructure for academic records. Every student on SchoolCore has one permanent ID that follows them across every school they ever attend.
As a developer, you can integrate SchoolCore into your existing school management platform. Your students get SchoolCore IDs. Their records are stored on SchoolCore permanently. Your platform keeps all its users and functionality — you simply add SchoolCore as the identity and records layer underneath.
Every request to the SchoolCore API must include your API key. Your API key is generated when your developer account is approved. Keep it secret — it identifies you on every request and is used to attribute pin revenue to your account.
// POST request — API key in request body const response = await fetch('https://api.schoolcore.ng/.netlify/functions/verifyStudent', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ apiKey: 'SC_API_YOUR_KEY_HERE', studentId: 'BFA-2026-0042' }) }); const data = await response.json(); console.log(data);
// POST request — API key in request body $ch = curl_init('https://api.schoolcore.ng/.netlify/functions/verifyStudent'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([ 'apiKey' => 'SC_API_YOUR_KEY_HERE', 'studentId' => 'BFA-2026-0042' ])); curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']); $response = json_decode(curl_exec($ch), true);
import requests response = requests.post( 'https://api.schoolcore.ng/.netlify/functions/verifyStudent', json={ 'apiKey': 'SC_API_YOUR_KEY_HERE', 'studentId': 'BFA-2026-0042' } ) data = response.json()
Every result pin your schools generate through the SchoolCore API costs ₦850. SchoolCore splits this revenue 50/50 with you — the developer. Your schools generate pins, students pay for pins to unlock results, and your earnings accumulate in your developer account automatically.
This is lifetime revenue. As long as a school is connected to your platform and generating pins, you earn 30% of every pin sold — indefinitely.
| Parameter | Type | Required | Description |
|---|---|---|---|
| apiKey | string | Required | Your SchoolCore developer API key |
| studentId | string | Required | The student's SchoolCore ID (e.g. BFA-2026-0042) |
{
"verified": true,
"studentId": "BFA-2026-0042",
"name": "Adaeze Mbachu",
"gender": "Female",
"photoUrl": "https://storage.googleapis.com/...",
"currentSchoolId": "SCH-BRIGHTFUTURE-001",
"schoolHistory": ["SCH-GREENFIELD-001", "SCH-BRIGHTFUTURE-001"],
"schoolCount": 2,
"status": "active"
}| Parameter | Type | Required | Description |
|---|---|---|---|
| apiKey | string | Required | Your SchoolCore developer API key |
| studentId | string | Required | The student's SchoolCore ID |
| schoolId | string | Required | Your school's ID on SchoolCore (provided in your developer dashboard) |
| className | string | Required | The class the student is enrolling in (e.g. "SS2") |
| armName | string | Optional | The arm or stream within the class (e.g. "Gold") |
| admissionNumber | string | Optional | The student's admission number at your school |
{
"enrolled": true,
"studentId": "BFA-2026-0042",
"studentName": "Adaeze Mbachu",
"schoolId": "SCH-BRIGHTFUTURE-001",
"className": "SS2",
"enrolledAt": 1750000000000,
"message": "Student successfully enrolled"
}| Parameter | Type | Required | Description |
|---|---|---|---|
| apiKey | string | Required | Your API key |
| studentId | string | Required | The student's SchoolCore ID |
| includeSubjects | boolean | Optional | Include subject-level breakdown in each result. Default: false |
{
"studentId": "BFA-2026-0042",
"studentName": "Adaeze Mbachu",
"totalResults": 6,
"results": [
{
"session": "2025/2026",
"term": "Third Term",
"schoolName": "Bright Future Academy",
"className": "SS2",
"total": 874,
"average": 87.4,
"overallGrade": "A",
"position": 1,
"verificationCode": "SC-K7M2-P9X1-R4Q8",
"publishedAt": 1750000000000
}
]
}Submit a student's final processed result to SchoolCore. This is the most important endpoint. The result must be fully processed by your system before calling this endpoint — SchoolCore only accepts final completed results, not raw scores.
① Entered all CA and Exam scores per subject
② Calculated totals per subject
③ Calculated the class average
④ Calculated class positions for all students
⑤ Assigned grades based on your grading system
⑥ Had the principal/admin review and approve
⑦ Shown a preview to the administrator
SchoolCore does not receive raw scores. Only publish the final approved result.
| Parameter | Type | Required | Description |
|---|---|---|---|
| apiKey | string | Required | Your API key |
| studentId | string | Required | The student's SchoolCore ID |
| schoolId | string | Required | Your school's SchoolCore ID |
| session | string | Required | Academic session (e.g. "2025/2026") |
| term | string | Required | Term name (e.g. "Third Term", "First Semester") |
| className | string | Required | The student's class (e.g. "SS2") |
| subjects | array | Required | Array of subject result objects (see structure below) |
| total | number | Required | Sum of all subject totals |
| average | number | Required | Average score across all subjects (1 decimal place) |
| overallGrade | string | Required | Overall grade (e.g. "A", "B", "C") |
| position | number | Required | Student's position in class |
| classSize | number | Optional | Total number of students in the class |
| teacherRemark | string | Optional | Class teacher's remark |
| principalRemark | string | Optional | Principal's comment |
| conductRating | string | Optional | Conduct rating (e.g. "Excellent", "Good") |
| nextTermBegins | string | Optional | Next term start date (e.g. "September 15, 2026") |
{
"name": "Mathematics", // Subject name — required
"caScore": 35, // Continuous Assessment score
"examScore": 55, // Exam score
"total": 90, // caScore + examScore — required
"grade": "A", // Grade letter — required
"remark": "Excellent" // Grade remark
}const result = await fetch('https://api.schoolcore.ng/.netlify/functions/publishResult', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ apiKey: 'SC_API_YOUR_KEY_HERE', studentId: 'BFA-2026-0042', schoolId: 'SCH-BRIGHTFUTURE-001', session: '2025/2026', term: 'Third Term', className: 'SS2', total: 874, average: 87.4, overallGrade: 'A', position: 1, classSize: 42, teacherRemark: 'An exceptional student.', principalRemark: 'Outstanding performance.', conductRating: 'Excellent', nextTermBegins: 'September 15, 2026', subjects: [ { name: 'Mathematics', caScore: 35, examScore: 55, total: 90, grade: 'A', remark: 'Excellent' }, { name: 'English Language', caScore: 32, examScore: 50, total: 82, grade: 'A', remark: 'Excellent' }, { name: 'Physics', caScore: 30, examScore: 52, total: 82, grade: 'A', remark: 'Excellent' } ] }) }); const { verificationCode, resultId } = await result.json(); console.log('Published! Code:', verificationCode);
{
"published": true,
"resultId": "RES_API_ABC123",
"studentId": "BFA-2026-0042",
"verificationCode": "SC-K7M2-P9X1-R4Q8",
"message": "Result published and permanently stored on SchoolCore",
"publishedAt": 1750000000000
}| Parameter | Type | Required | Description |
|---|---|---|---|
| apiKey | string | Required | Your API key |
| studentId | string | Required | The student's SchoolCore ID |
| session | string | Optional | Filter by session (e.g. "2025/2026"). Returns all sessions if omitted. |
| Parameter | Type | Required | Description |
|---|---|---|---|
| verificationCode | string | Required | The verification code from the result slip (e.g. SC-K7M2-P9X1-R4Q8) |
{
"verified": true,
"studentName": "Adaeze Mbachu",
"studentId": "BFA-2026-0042",
"schoolName": "Bright Future Academy",
"session": "2025/2026",
"term": "Third Term",
"className": "SS2",
"overallGrade": "A",
"average": 87.4,
"issuedAt": 1750000000000,
"source": "schoolcore",
"tamperProof": true
}| Parameter | Type | Required | Description |
|---|---|---|---|
| apiKey | string | Required | Your API key |
| studentId | string | Required | The student's SchoolCore ID |
| pin | string | Required | The scratch pin the student purchased (XXXX-XXXXXX-XXXX) |
{
"unlocked": true,
"studentId": "BFA-2026-0042",
"session": "2025/2026",
"term": "Third Term",
"result": {
"total": 874,
"average": 87.4,
"overallGrade": "A",
"position": 1,
"subjects": [ /* full subjects array */ ]
},
"verificationCode": "SC-K7M2-P9X1-R4Q8",
"permanentlyStored": true,
"message": "Result unlocked and permanently saved to student account"
}| Parameter | Type | Required | Description |
|---|---|---|---|
| apiKey | string | Required | Your API key |
| schoolId | string | Required | The school's SchoolCore ID |
| session | string | Required | Academic session these pins are for |
| term | string | Required | Term these pins are for |
| quantity | number | Required | Number of pins to generate (max 500 per request) |
{
"generated": true,
"quantity": 200,
"totalValue": 20000,
"yourRevenue": 10000,
"schoolcoreRevenue": 10000,
"pins": [
"ABCD-EFGHJK-LMNP",
"QRST-UVWXYZ-2345",
// ... all 200 pins
],
"balanceAfter": 47000,
"message": "200 pins generated. ₦10,000 credited to your account"
}| Parameter | Type | Required | Description |
|---|---|---|---|
| apiKey | string | Required | Your API key |
| pin | string | Required | The pin code to check |
{
"valid": true,
"used": false,
"session": "2025/2026",
"term": "Third Term",
"schoolId": "SCH-BRIGHTFUTURE-001"
}{
"totalEarned": 87500,
"totalPaid": 50000,
"balance": 37500,
"totalPinsGenerated": 1750,
"schoolsConnected": 14,
"currency": "NGN",
"lastActivity": 1750000000000
}| Parameter | Type | Required | Description |
|---|---|---|---|
| apiKey | string | Required | Your API key |
| amount | number | Required | Amount to withdraw in Naira (min ₦5,000, max = available balance) |
| withdrawPin | string | Required | Your 4-digit security PIN set in the developer portal |
{
"submitted": true,
"requestId": "WD-2026-0042",
"amount": 20000,
"status": "pending",
"expectedBy": "Within 6-12 hours",
"balancePending": 20000,
"balanceAvailable": 17500
}error field describing what went wrong and a code field for programmatic handling.{
"error": "Student not found",
"code": "STUDENT_NOT_FOUND",
"status": 404
}| HTTP Status | Error Code | Description |
|---|---|---|
| 401 | INVALID_API_KEY | The API key provided does not exist or has been revoked. |
| 403 | ACCOUNT_SUSPENDED | Your developer account has been suspended. Contact support. |
| 404 | STUDENT_NOT_FOUND | No student exists with the provided student ID. |
| 409 | ALREADY_ENROLLED | The student is already enrolled as active in this school. |
| 409 | RESULT_EXISTS | A result already exists for this student/session/term combination. |
| 410 | PIN_ALREADY_USED | The scratch pin has already been used to unlock a result. |
| 404 | PIN_NOT_FOUND | The pin does not exist in the SchoolCore system. |
| 404 | VERIFICATION_CODE_NOT_FOUND | No result matches the provided verification code. |
| 400 | INSUFFICIENT_BALANCE | Withdrawal amount exceeds available balance. |
| 400 | BELOW_MINIMUM_WITHDRAWAL | Withdrawal amount is below the minimum of ₦5,000. |
| 400 | INVALID_WITHDRAW_PIN | The 4-digit security PIN is incorrect. |
| 400 | MISSING_REQUIRED_FIELD | One or more required fields are missing from the request body. |
| 429 | RATE_LIMIT_EXCEEDED | Too many requests. Wait before retrying. See rate limits section. |
| 500 | SERVER_ERROR | Internal server error. Try again after a few seconds. Contact support if persistent. |
| Endpoint | Limit | Window |
|---|---|---|
| /verifyStudent | 500 requests | Per hour |
| /enrollStudent | 200 requests | Per hour |
| /publishResult | 100 requests | Per hour |
| /generatePins | 50 requests | Per hour |
| /verifyCode | Unlimited | Public endpoint |
| /unlockResult | 200 requests | Per hour |
API Key:
SC_API_TEST_KEY_12345Test Student ID:
TEST-2026-0001Test School ID:
SCH-TEST-001Test Pin:
TEST-SANDBOX-XXXX
/verifyStudent to confirm it's valid before saving./publishResult with the complete processed data. SchoolCore stores it permanently./generatePins. The pins are created, your account is credited 30% of the batch value. Students use pins to unlock results — in your app or on SchoolCore directly.const SC_API = 'https://api.schoolcore.ng/.netlify/functions'; const API_KEY = process.env.SCHOOLCORE_API_KEY; // Helper function async function scCall(endpoint, data) { const res = await fetch(`${SC_API}/${endpoint}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ apiKey: API_KEY, ...data }) }); return res.json(); } // ─── Step 1: Verify student on enrollment ─── async function enrollStudent(schoolcoreId, className) { const check = await scCall('verifyStudent', { studentId: schoolcoreId }); if (!check.verified) throw new Error('Invalid SchoolCore ID'); // Save to your own database await db.students.create({ schoolcoreId, name: check.name, className }); // Link on SchoolCore await scCall('enrollStudent', { studentId: schoolcoreId, schoolId: 'SCH-YOUR-SCHOOL-001', className }); return check.name; } // ─── Step 2: Publish result after approval ─── async function publishResult(processedResult) { const { verificationCode } = await scCall('publishResult', { studentId: processedResult.schoolcoreId, schoolId: 'SCH-YOUR-SCHOOL-001', session: processedResult.session, term: processedResult.term, className: processedResult.className, subjects: processedResult.subjects, total: processedResult.total, average: processedResult.average, overallGrade: processedResult.grade, position: processedResult.position, classSize: processedResult.classSize, teacherRemark: processedResult.teacherRemark, principalRemark: processedResult.principalRemark }); // Print verificationCode on student's result slip return verificationCode; } // ─── Step 3: Generate pins for a school ─── async function orderPins(schoolId, quantity) { const { pins, yourRevenue } = await scCall('generatePins', { schoolId, session: '2025/2026', term: 'Third Term', quantity }); console.log(`Generated ${pins.length} pins. Your revenue: ₦${yourRevenue}`); return pins; // Array of pin codes to distribute to students }
class SchoolCoreAPI { private string $apiKey; private string $baseUrl = 'https://api.schoolcore.ng/.netlify/functions'; public function __construct(string $apiKey) { $this->apiKey = $apiKey; } private function call(string $endpoint, array $data): array { $payload = array_merge(['apiKey' => $this->apiKey], $data); $ch = curl_init("{$this->baseUrl}/{$endpoint}"); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode($payload), CURLOPT_HTTPHEADER => ['Content-Type: application/json'] ]); return json_decode(curl_exec($ch), true); } public function verifyStudent(string $studentId): array { return $this->call('verifyStudent', ['studentId' => $studentId]); } public function publishResult(array $resultData): array { return $this->call('publishResult', $resultData); } public function generatePins(string $schoolId, int $qty): array { return $this->call('generatePins', [ 'schoolId' => $schoolId, 'quantity' => $qty, 'session' => '2025/2026', 'term' => 'Third Term' ]); } } // Usage $sc = new SchoolCoreAPI($_ENV['SCHOOLCORE_API_KEY']); $student = $sc->verifyStudent('BFA-2026-0042'); if ($student['verified']) { echo "Found: {$student['name']}"; }
import requests import os class SchoolCoreAPI: BASE_URL = 'https://api.schoolcore.ng/.netlify/functions' def __init__(self, api_key=None): self.api_key = api_key or os.environ['SCHOOLCORE_API_KEY'] def _call(self, endpoint, data): response = requests.post( f'{self.BASE_URL}/{endpoint}', json={'apiKey': self.api_key, **data} ) return response.json() def verify_student(self, student_id): return self._call('verifyStudent', {'studentId': student_id}) def publish_result(self, result_data): return self._call('publishResult', result_data) def generate_pins(self, school_id, quantity): return self._call('generatePins', { 'schoolId': school_id, 'quantity': quantity, 'session': '2025/2026', 'term': 'Third Term' }) # Usage sc = SchoolCoreAPI() student = sc.verify_student('BFA-2026-0042') if student['verified']: print(f"Found: {student['name']}")