Complete documentation for the Cosqool Partner API v1.0. Enroll students, stream educational video content, and track learning progress, all from your platform.
Getting Started
Authentication, base URL and workflow overview
Endpoints
Full reference for the 8 original endpoints
Partner additions
Catalogue search, flat course, per-item delivery, item progress, reason codes, webhooks
Errors & Rate Limits
Status codes, retry logic and error schema
All requests must include an Authorization header with your Partner API key using the Api-Key scheme.
Request Header
Authorization: Api-Key sk_partner_live_your_key_here
⚠️ Security
Never expose your API key in client-side (frontend) code. All Partner API calls must be server-to-server. Use this sandbox from your backend or a secure environment only.
Discover Courses
Call GET /courses/{grade_slug}/{semester_slug}/ (or POST /courses/search) to find course IDs, then GET /courses/{course_id}/ for the flat course with an id on every item.
Enroll a Student
Call POST /enrollments/ with course_id, transaction_id and external_student_id (everything else is optional). Store the returned enrollment_id.
Stream Video Content
Call GET /students/{sid}/courses/{cid}/videos/{item_id}/ for one item's hls_url (or the v1 GET /enrollments/{id}/videos/ for every video). Each call re-checks the enrollment; `signed` tells you whether the stream URL itself is signed (false today: the manifest URL does not expire on the provider side, so re-request rather than store it).
Track Progress
Call POST /students/{sid}/courses/{cid}/progress/ per completed item and read GET …/progress/ — progress_pct (metric edumatch_item_completion_v1) is the authoritative course progress. The v1 …/complete/ counter and GET /students/{sid}/progress/ are legacy video counters.
/courses/{grade_slug}/{semester_slug}/Returns all published courses for a given grade and semester. This is Step 1 of the integration workflow — use it to discover valid course_id values before enrolling students.
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| grade_slug | path | string | Required | Grade identifier e.g. grade-10, grade-1 … grade-12 |
| semester_slug | path | string | Required | Semester identifier: semester-1 or semester-2 |
| subject | query | string | Optional | Filter by subject name (Arabic or English). Case-insensitive. |
Example Response
{
"grade_id": 10,
"semester_id": 2,
"count": 3,
"courses": [
{
"course_id": 142,
"title_en": "Physics — Grade 10 Term 2",
"title_ar": "الفيزياء — الصف العاشر الفصل الثاني",
"subject_id": 5,
"subject_en": "Physics",
"subject_ar": "فيزياء",
"grade_id": 10,
"semester_id": 2,
"last_updated": "2025-09-01T08:00:00Z"
}
]
}Additive endpoints on Partner API v1. Nothing above changes; every failure of these and of the original endpoints carries a stable code next to detail. Search, flat course and enrollment live on Catalog & Enrollment; delivery and progress on Video & Progress.
All errors return a consistent JSON object: a human-readable detail (a field map on validation errors) and a stable code — see the reason-code table above.
Error Response
{ "detail": "No active enrollment found for this student and course.", "code": "enrollment_not_found" }| Code | Meaning | Action |
|---|---|---|
| 200 OK | Request succeeded (or idempotent replay) | Proceed normally |
| 201 Created | New resource created | Store returned ID |
| 400 Bad Request | Invalid or missing request parameters | Fix payload and retry |
| 401 Unauthorized | Missing or malformed Authorization header | Check your API key format |
| 403 Forbidden | Valid key but insufficient permissions | Contact Cosqool support |
| 404 Not Found | Resource doesn't exist (intentionally vague for security) | Verify course/enrollment IDs |
| 429 Too Many Requests | Rate limit exceeded (60 requests per minute per key) | Wait for Retry-After header duration |
| 500 Server Error | Unexpected server-side failure | Retry with exponential backoff; contact support if persistent |
60
requests per minute per key
429
with Retry-After when exceeded — no daily cap
When the limit is exceeded, the API returns 429 Too Many Requests with a Retry-After header indicating the number of seconds to wait. Implement exponential backoff with a maximum of 3 retries for 429 and 500 errors.