{"openapi":"3.1.0","info":{"title":"EvalenceAI Learn public API","version":"1.0.0","description":"Read the catalogue, enrol students by email and read their progress. Authenticate with an API key issued by a platform administrator: `Authorization: Bearer lak_…`. Each key carries scopes and a per-minute request budget."},"servers":[{"url":"https://learn.fillatech.et/api/public/v1"}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"An API key. Scopes: `catalog:read` (Read the catalogue and course outlines), `enrolments:write` (Enrol students by email), `progress:read` (Read a student's progress and certificate)."}},"schemas":{"Problem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"trace_id":{"type":"string"}}},"CourseCard":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"title":{"type":"string"},"subtitle":{"type":"string","nullable":true},"level":{"type":"string"},"language":{"type":"string"},"priceCents":{"type":"integer"},"currency":{"type":"string"},"lessonCount":{"type":"integer"},"totalDurationSec":{"type":"integer"},"ratingAvg":{"type":"number","nullable":true},"ratingCount":{"type":"integer"},"listPriceCents":{"type":"integer"},"url":{"type":"string"}}},"Course":{"allOf":[{"$ref":"#/components/schemas/CourseCard"},{"type":"object","properties":{"description":{"type":"string","nullable":true},"instructor":{"type":"string","nullable":true},"objectives":{"type":"array","items":{"type":"string"}},"sections":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"lessons":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"type":{"type":"string"},"durationSec":{"type":"integer"},"isPreview":{"type":"boolean"}}}}}}}}}]},"Enrolment":{"type":"object","properties":{"id":{"type":"string"},"courseId":{"type":"string"},"student":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"created":{"type":"boolean"}}},"status":{"type":"string"},"created":{"type":"boolean"},"enrolledAt":{"type":"string","format":"date-time"}}},"Progress":{"type":"object","properties":{"courseId":{"type":"string"},"student":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"}}},"status":{"type":"string"},"progressPct":{"type":"integer"},"lessonsCompleted":{"type":"integer"},"lessonsTotal":{"type":"integer"},"lastActivityAt":{"type":"string","format":"date-time","nullable":true},"completedAt":{"type":"string","format":"date-time","nullable":true},"certificate":{"type":"object","nullable":true,"properties":{"code":{"type":"string"},"issuedAt":{"type":"string","format":"date-time"},"verifyUrl":{"type":"string"}}}}}}},"paths":{"/catalog":{"get":{"summary":"Published courses","description":"Scope `catalog:read`. Full-text search with `q`; 24 per page.","parameters":[{"name":"q","in":"query","schema":{"type":"string"}},{"name":"page","in":"query","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"Courses","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/CourseCard"}},"total":{"type":"integer"},"page":{"type":"integer"},"pageSize":{"type":"integer"}}}}}}}},"401":{"description":"No valid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key lacks the scope","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"The key's per-minute budget is spent; see retryAfterSec","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/courses/{slug}":{"get":{"summary":"A course with its outline","description":"Scope `catalog:read`.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The course","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Course"}}}}}},"401":{"description":"No valid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key lacks the scope","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"RFC 7807 problem","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"The key's per-minute budget is spent; see retryAfterSec","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/enrolments":{"post":{"summary":"Enrol a student by email","description":"Scope `enrolments:write`. An account is created for an unknown email (the student is emailed a setup link); an existing enrolment is returned unchanged.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email"],"properties":{"email":{"type":"string","format":"email"},"name":{"type":"string"},"courseId":{"type":"string"},"slug":{"type":"string"}}}}}},"responses":{"200":{"description":"Already enrolled","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Enrolment"}}}}}},"201":{"description":"Enrolled","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Enrolment"}}}}}},"401":{"description":"No valid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key lacks the scope","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"RFC 7807 problem","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"RFC 7807 problem","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"The key's per-minute budget is spent; see retryAfterSec","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/progress":{"get":{"summary":"A student's progress in a course","description":"Scope `progress:read`.","parameters":[{"name":"email","in":"query","required":true,"schema":{"type":"string"}},{"name":"courseId","in":"query","schema":{"type":"string"}},{"name":"slug","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Progress","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Progress"}}}}}},"401":{"description":"No valid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key lacks the scope","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"RFC 7807 problem","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"The key's per-minute budget is spent; see retryAfterSec","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}}}}