{"openapi":"3.1.0","info":{"title":"ABBLEARN API","version":"1.0.0","description":"Read and manage a portal's people, courses, enrolments, results and certificates. Every request is made with a portal API key, created by an admin under Administration → API keys."},"servers":[{"url":"https://abblearn.com/api/v1"}],"security":[{"apiKey":[]}],"tags":[{"name":"Portal","description":"The portal the key belongs to."},{"name":"People","description":"Members of the portal."},{"name":"Courses","description":"Courses, sections and lessons."},{"name":"Enrolments","description":"Who is studying what, and how far they are."},{"name":"Results","description":"Graded assessment attempts."},{"name":"Certificates","description":"Certificates issued to learners."}],"paths":{"/portal":{"get":{"operationId":"getPortal","tags":["Portal"],"summary":"The portal: details, plan limits and current usage","x-ability":"tenant:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Portal"}}}}}},"401":{"$ref":"#/components/responses/Unauthorised"},"403":{"$ref":"#/components/responses/Forbidden"},"422":{"$ref":"#/components/responses/ValidationFailed"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/billing":{"get":{"operationId":"getBilling","tags":["Portal"],"summary":"Billing state, plan, trial and grace period","x-ability":"billing:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Billing"}}}}}},"401":{"$ref":"#/components/responses/Unauthorised"},"403":{"$ref":"#/components/responses/Forbidden"},"422":{"$ref":"#/components/responses/ValidationFailed"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/users":{"get":{"operationId":"listUsers","tags":["People"],"summary":"People in the portal","x-ability":"users:read","parameters":[{"name":"role","in":"query","description":"owner, admin, manager, instructor or learner","schema":{"type":"string"}},{"name":"status","in":"query","description":"active, invited or suspended","schema":{"type":"string"}},{"name":"email","in":"query","description":"Exact email address (case-insensitive)","schema":{"type":"string","format":"email"}},{"$ref":"#/components/parameters/PerPage"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"A page of results. Follow `meta.next_cursor` until it is null.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Member"}},"links":{"type":"object","properties":{"next":{"type":["string","null"]},"prev":{"type":["string","null"]}}},"meta":{"$ref":"#/components/schemas/CursorMeta"}}}}}},"401":{"$ref":"#/components/responses/Unauthorised"},"403":{"$ref":"#/components/responses/Forbidden"},"422":{"$ref":"#/components/responses/ValidationFailed"},"429":{"$ref":"#/components/responses/TooManyRequests"}}},"post":{"operationId":"inviteUser","tags":["People"],"summary":"Invite someone; they join when they accept the emailed invitation","x-ability":"users:write","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","role"],"properties":{"email":{"type":"string","format":"email"},"role":{"type":"string","enum":["admin","manager","instructor","learner"]},"name":{"type":"string","description":"Pre-fills the acceptance form."}}}}}},"responses":{"202":{"description":"Invitation sent.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Invitation"}}}}}},"401":{"$ref":"#/components/responses/Unauthorised"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/ValidationFailed"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/users/{user}":{"get":{"operationId":"getUser","tags":["People"],"summary":"One person","x-ability":"users:read","parameters":[{"name":"user","in":"path","required":true,"description":"The person's id","schema":{"type":"integer"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Member"}}}}}},"401":{"$ref":"#/components/responses/Unauthorised"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/ValidationFailed"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/courses":{"get":{"operationId":"listCourses","tags":["Courses"],"summary":"Courses in the portal","x-ability":"courses:read","parameters":[{"name":"status","in":"query","description":"draft, in_review, published or archived","schema":{"type":"string"}},{"$ref":"#/components/parameters/PerPage"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"A page of results. Follow `meta.next_cursor` until it is null.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Course"}},"links":{"type":"object","properties":{"next":{"type":["string","null"]},"prev":{"type":["string","null"]}}},"meta":{"$ref":"#/components/schemas/CursorMeta"}}}}}},"401":{"$ref":"#/components/responses/Unauthorised"},"403":{"$ref":"#/components/responses/Forbidden"},"422":{"$ref":"#/components/responses/ValidationFailed"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/courses/{course}":{"get":{"operationId":"getCourse","tags":["Courses"],"summary":"One course with its sections and lessons","x-ability":"courses:read","parameters":[{"name":"course","in":"path","required":true,"description":"The course id","schema":{"type":"integer"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Course"}}}}}},"401":{"$ref":"#/components/responses/Unauthorised"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/ValidationFailed"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/enrolments":{"get":{"operationId":"listEnrolments","tags":["Enrolments"],"summary":"Enrolments","x-ability":"enrolments:read","parameters":[{"name":"user_id","in":"query","description":"Only this person","schema":{"type":"integer"}},{"name":"course_id","in":"query","description":"Only this course","schema":{"type":"integer"}},{"name":"status","in":"query","description":"active, completed, expired, suspended or withdrawn","schema":{"type":"string"}},{"name":"updated_since","in":"query","description":"Only enrolments changed since this time (ISO 8601)","schema":{"type":"string","format":"date-time"}},{"$ref":"#/components/parameters/PerPage"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"A page of results. Follow `meta.next_cursor` until it is null.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Enrolment"}},"links":{"type":"object","properties":{"next":{"type":["string","null"]},"prev":{"type":["string","null"]}}},"meta":{"$ref":"#/components/schemas/CursorMeta"}}}}}},"401":{"$ref":"#/components/responses/Unauthorised"},"403":{"$ref":"#/components/responses/Forbidden"},"422":{"$ref":"#/components/responses/ValidationFailed"},"429":{"$ref":"#/components/responses/TooManyRequests"}}},"post":{"operationId":"createEnrolment","tags":["Enrolments"],"summary":"Enrol an active member on a published course","x-ability":"enrolments:write","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["course_id"],"description":"Identify the learner by `user_id` or `email`.","properties":{"course_id":{"type":"integer"},"user_id":{"type":"integer"},"email":{"type":"string","format":"email"},"due_at":{"type":"string","format":"date-time","description":"Optional deadline, in the future."}}}}}},"responses":{"201":{"description":"Enrolled.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Enrolment"}}}}}},"200":{"description":"Already studying the course; their current enrolment is returned.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Enrolment"}}}}}},"401":{"$ref":"#/components/responses/Unauthorised"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/ValidationFailed"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/enrolments/{enrolment}":{"get":{"operationId":"getEnrolment","tags":["Enrolments"],"summary":"One enrolment with progress through each lesson","x-ability":"progress:read","parameters":[{"name":"enrolment","in":"path","required":true,"description":"The enrolment id","schema":{"type":"integer"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Enrolment"}}}}}},"401":{"$ref":"#/components/responses/Unauthorised"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/ValidationFailed"},"429":{"$ref":"#/components/responses/TooManyRequests"}}},"patch":{"operationId":"withdrawEnrolment","tags":["Enrolments"],"summary":"Withdraw a learner (the only change allowed)","x-ability":"enrolments:write","parameters":[{"name":"enrolment","in":"path","required":true,"description":"The enrolment id","schema":{"type":"integer"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["withdrawn"]}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Enrolment"}}}}}},"401":{"$ref":"#/components/responses/Unauthorised"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/ValidationFailed"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/assessment-results":{"get":{"operationId":"listAssessmentResults","tags":["Results"],"summary":"Graded assessment attempts (answers are not included)","x-ability":"results:read","parameters":[{"name":"user_id","in":"query","description":"Only this person","schema":{"type":"integer"}},{"name":"course_id","in":"query","description":"Only this course","schema":{"type":"integer"}},{"name":"passed","in":"query","description":"true or false","schema":{"type":"boolean"}},{"$ref":"#/components/parameters/PerPage"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"A page of results. Follow `meta.next_cursor` until it is null.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AssessmentResult"}},"links":{"type":"object","properties":{"next":{"type":["string","null"]},"prev":{"type":["string","null"]}}},"meta":{"$ref":"#/components/schemas/CursorMeta"}}}}}},"401":{"$ref":"#/components/responses/Unauthorised"},"403":{"$ref":"#/components/responses/Forbidden"},"422":{"$ref":"#/components/responses/ValidationFailed"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/certificates":{"get":{"operationId":"listCertificates","tags":["Certificates"],"summary":"Certificates issued in the portal","x-ability":"certificates:read","parameters":[{"name":"user_id","in":"query","description":"Only this person","schema":{"type":"integer"}},{"name":"course_id","in":"query","description":"Only this course","schema":{"type":"integer"}},{"name":"status","in":"query","description":"issued, expired, revoked or superseded","schema":{"type":"string"}},{"$ref":"#/components/parameters/PerPage"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"A page of results. Follow `meta.next_cursor` until it is null.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Certificate"}},"links":{"type":"object","properties":{"next":{"type":["string","null"]},"prev":{"type":["string","null"]}}},"meta":{"$ref":"#/components/schemas/CursorMeta"}}}}}},"401":{"$ref":"#/components/responses/Unauthorised"},"403":{"$ref":"#/components/responses/Forbidden"},"422":{"$ref":"#/components/responses/ValidationFailed"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/certificates/{certificate}":{"get":{"operationId":"getCertificate","tags":["Certificates"],"summary":"One certificate","x-ability":"certificates:read","parameters":[{"name":"certificate","in":"path","required":true,"description":"The certificate id","schema":{"type":"integer"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Certificate"}}}}}},"401":{"$ref":"#/components/responses/Unauthorised"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/ValidationFailed"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}}},"webhooks":{"enrolment.created":{"post":{"summary":"A learner is enrolled on a course","parameters":[{"name":"ABBLEARN-Event-Id","in":"header","required":true,"description":"The event id (same as `id` in the body).","schema":{"type":"string"}},{"name":"ABBLEARN-Event-Type","in":"header","required":true,"description":"The event type.","schema":{"type":"string"}},{"name":"ABBLEARN-Timestamp","in":"header","required":true,"description":"Unix time the request was signed.","schema":{"type":"integer"}},{"name":"ABBLEARN-Signature","in":"header","required":true,"description":"`t={timestamp},v1={hex HMAC-SHA256 of \"{timestamp}.{raw body}\" using the endpoint secret}`.","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"2XX":{"description":"Received. Anything else (or no answer within 10 seconds) is retried."}}}},"enrolment.completed":{"post":{"summary":"A learner completes a course","parameters":[{"name":"ABBLEARN-Event-Id","in":"header","required":true,"description":"The event id (same as `id` in the body).","schema":{"type":"string"}},{"name":"ABBLEARN-Event-Type","in":"header","required":true,"description":"The event type.","schema":{"type":"string"}},{"name":"ABBLEARN-Timestamp","in":"header","required":true,"description":"Unix time the request was signed.","schema":{"type":"integer"}},{"name":"ABBLEARN-Signature","in":"header","required":true,"description":"`t={timestamp},v1={hex HMAC-SHA256 of \"{timestamp}.{raw body}\" using the endpoint secret}`.","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"2XX":{"description":"Received. Anything else (or no answer within 10 seconds) is retried."}}}},"enrolment.withdrawn":{"post":{"summary":"A learner is withdrawn from a course","parameters":[{"name":"ABBLEARN-Event-Id","in":"header","required":true,"description":"The event id (same as `id` in the body).","schema":{"type":"string"}},{"name":"ABBLEARN-Event-Type","in":"header","required":true,"description":"The event type.","schema":{"type":"string"}},{"name":"ABBLEARN-Timestamp","in":"header","required":true,"description":"Unix time the request was signed.","schema":{"type":"integer"}},{"name":"ABBLEARN-Signature","in":"header","required":true,"description":"`t={timestamp},v1={hex HMAC-SHA256 of \"{timestamp}.{raw body}\" using the endpoint secret}`.","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"2XX":{"description":"Received. Anything else (or no answer within 10 seconds) is retried."}}}},"certificate.issued":{"post":{"summary":"A certificate is issued","parameters":[{"name":"ABBLEARN-Event-Id","in":"header","required":true,"description":"The event id (same as `id` in the body).","schema":{"type":"string"}},{"name":"ABBLEARN-Event-Type","in":"header","required":true,"description":"The event type.","schema":{"type":"string"}},{"name":"ABBLEARN-Timestamp","in":"header","required":true,"description":"Unix time the request was signed.","schema":{"type":"integer"}},{"name":"ABBLEARN-Signature","in":"header","required":true,"description":"`t={timestamp},v1={hex HMAC-SHA256 of \"{timestamp}.{raw body}\" using the endpoint secret}`.","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"2XX":{"description":"Received. Anything else (or no answer within 10 seconds) is retried."}}}},"certificate.revoked":{"post":{"summary":"A certificate is revoked","parameters":[{"name":"ABBLEARN-Event-Id","in":"header","required":true,"description":"The event id (same as `id` in the body).","schema":{"type":"string"}},{"name":"ABBLEARN-Event-Type","in":"header","required":true,"description":"The event type.","schema":{"type":"string"}},{"name":"ABBLEARN-Timestamp","in":"header","required":true,"description":"Unix time the request was signed.","schema":{"type":"integer"}},{"name":"ABBLEARN-Signature","in":"header","required":true,"description":"`t={timestamp},v1={hex HMAC-SHA256 of \"{timestamp}.{raw body}\" using the endpoint secret}`.","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"2XX":{"description":"Received. Anything else (or no answer within 10 seconds) is retried."}}}},"billing.status_changed":{"post":{"summary":"The subscription status changes","parameters":[{"name":"ABBLEARN-Event-Id","in":"header","required":true,"description":"The event id (same as `id` in the body).","schema":{"type":"string"}},{"name":"ABBLEARN-Event-Type","in":"header","required":true,"description":"The event type.","schema":{"type":"string"}},{"name":"ABBLEARN-Timestamp","in":"header","required":true,"description":"Unix time the request was signed.","schema":{"type":"integer"}},{"name":"ABBLEARN-Signature","in":"header","required":true,"description":"`t={timestamp},v1={hex HMAC-SHA256 of \"{timestamp}.{raw body}\" using the endpoint secret}`.","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"2XX":{"description":"Received. Anything else (or no answer within 10 seconds) is retried."}}}},"billing.payment_failed":{"post":{"summary":"A subscription payment fails","parameters":[{"name":"ABBLEARN-Event-Id","in":"header","required":true,"description":"The event id (same as `id` in the body).","schema":{"type":"string"}},{"name":"ABBLEARN-Event-Type","in":"header","required":true,"description":"The event type.","schema":{"type":"string"}},{"name":"ABBLEARN-Timestamp","in":"header","required":true,"description":"Unix time the request was signed.","schema":{"type":"integer"}},{"name":"ABBLEARN-Signature","in":"header","required":true,"description":"`t={timestamp},v1={hex HMAC-SHA256 of \"{timestamp}.{raw body}\" using the endpoint secret}`.","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"2XX":{"description":"Received. Anything else (or no answer within 10 seconds) is retried."}}}},"ping":{"post":{"summary":"Test event","parameters":[{"name":"ABBLEARN-Event-Id","in":"header","required":true,"description":"The event id (same as `id` in the body).","schema":{"type":"string"}},{"name":"ABBLEARN-Event-Type","in":"header","required":true,"description":"The event type.","schema":{"type":"string"}},{"name":"ABBLEARN-Timestamp","in":"header","required":true,"description":"Unix time the request was signed.","schema":{"type":"integer"}},{"name":"ABBLEARN-Signature","in":"header","required":true,"description":"`t={timestamp},v1={hex HMAC-SHA256 of \"{timestamp}.{raw body}\" using the endpoint secret}`.","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"2XX":{"description":"Received. Anything else (or no answer within 10 seconds) is retried."}}}}},"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"Send `Authorization: Bearer abl_…`. Each endpoint needs one permission on the key (shown as `x-ability`)."}},"parameters":{"PerPage":{"name":"per_page","in":"query","description":"Results per page (1–100, default 25).","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},"Cursor":{"name":"cursor","in":"query","description":"The `next_cursor` from the previous page.","schema":{"type":"string"}},"IdempotencyKey":{"name":"Idempotency-Key","in":"header","description":"Any unique string. Repeating the request with the same key within 24 hours returns the first response (with `Idempotent-Replayed: true`) instead of acting again.","schema":{"type":"string","maxLength":255}}},"responses":{"Unauthorised":{"description":"Missing, unknown, revoked or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The key lacks the permission, or the portal is unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"Not found in this portal.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Conflict":{"description":"A request with this Idempotency-Key is still being processed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ValidationFailed":{"description":"The request was not valid (also returned when a plan limit is reached, under `errors.plan`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"TooManyRequests":{"description":"Rate limit reached (120 requests a minute per key). Wait for `Retry-After` seconds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","properties":{"message":{"type":"string"}}},"ValidationError":{"type":"object","properties":{"message":{"type":"string"},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}},"CursorMeta":{"type":"object","properties":{"path":{"type":"string"},"per_page":{"type":"integer"},"next_cursor":{"type":["string","null"]},"prev_cursor":{"type":["string","null"]}}},"Portal":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"url":{"type":"string"},"status":{"type":"string"},"locale":{"type":"string"},"timezone":{"type":"string"},"created_at":{"type":["string","null"],"format":"date-time"},"plan":{"type":["object","null"],"properties":{"code":{"type":"string"},"name":{"type":"string"},"limits":{"type":"object","description":"null means unlimited","properties":{"active_learners":{"type":["integer","null"]},"staff":{"type":["integer","null"]},"courses":{"type":["integer","null"]},"storage_mb":{"type":["integer","null"]}}}}},"usage":{"type":"object","properties":{"active_learners":{"type":"integer"},"instructors":{"type":"integer"},"courses":{"type":"integer"},"storage_mb":{"type":"integer"}}}}},"Billing":{"type":"object","properties":{"state":{"type":"string","enum":["trialing","active","past_due","restricted"]},"plan":{"type":["string","null"]},"trial_ends_at":{"type":["string","null"],"format":"date-time"},"grace_period_ends_at":{"type":["string","null"],"format":"date-time"},"subscription":{"type":["object","null"],"properties":{"status":{"type":"string"},"ends_at":{"type":["string","null"],"format":"date-time"}}}}},"Member":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"email":{"type":"string"},"role":{"type":"string"},"status":{"type":"string"},"job_title":{"type":["string","null"]},"department":{"type":["string","null"]},"external_id":{"type":["string","null"]},"joined_at":{"type":["string","null"],"format":"date-time"},"last_visit_at":{"type":["string","null"],"format":"date-time"}}},"Invitation":{"type":"object","properties":{"email":{"type":"string"},"role":{"type":"string"},"invitation_expires_at":{"type":["string","null"],"format":"date-time"}}},"Course":{"type":"object","properties":{"id":{"type":"integer"},"title":{"type":"string"},"summary":{"type":["string","null"]},"status":{"type":"string"},"visibility":{"type":"string"},"category":{"type":["string","null"]},"estimated_duration_minutes":{"type":["integer","null"]},"awards_certificate":{"type":"boolean"},"lessons_count":{"type":"integer"},"published_at":{"type":["string","null"],"format":"date-time"},"updated_at":{"type":["string","null"],"format":"date-time"},"sections":{"type":"array","description":"Only on GET /courses/{course}.","items":{"type":"object","properties":{"id":{"type":"integer"},"title":{"type":"string"},"lessons":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"title":{"type":"string"},"type":{"type":"string"},"is_required":{"type":"boolean"},"duration_seconds":{"type":["integer","null"]}}}}}}}}},"Enrolment":{"type":"object","properties":{"id":{"type":"integer"},"user":{"type":"object","properties":{"id":{"type":"integer"},"email":{"type":"string"}}},"course":{"type":"object","properties":{"id":{"type":"integer"},"title":{"type":"string"}}},"status":{"type":"string","enum":["active","completed","expired","suspended","withdrawn"]},"source":{"type":"string"},"progress_percent":{"type":"integer"},"is_overdue":{"type":"boolean"},"enrolled_at":{"type":["string","null"],"format":"date-time"},"started_at":{"type":["string","null"],"format":"date-time"},"due_at":{"type":["string","null"],"format":"date-time"},"completed_at":{"type":["string","null"],"format":"date-time"},"expires_at":{"type":["string","null"],"format":"date-time"},"last_visit_at":{"type":["string","null"],"format":"date-time"},"updated_at":{"type":["string","null"],"format":"date-time"},"lessons":{"type":"array","description":"Only on GET /enrolments/{enrolment}.","items":{"type":"object","properties":{"lesson_id":{"type":"integer"},"status":{"type":"string"},"progress_percent":{"type":"integer"},"time_spent_seconds":{"type":"integer"},"first_viewed_at":{"type":["string","null"],"format":"date-time"},"completed_at":{"type":["string","null"],"format":"date-time"}}}}}},"AssessmentResult":{"type":"object","properties":{"id":{"type":"integer"},"user":{"type":"object","properties":{"id":{"type":"integer"},"email":{"type":"string"}}},"assessment":{"type":"object","properties":{"id":{"type":"integer"},"title":{"type":["string","null"]},"course_id":{"type":["integer","null"]}}},"attempt":{"type":"integer"},"status":{"type":"string"},"score_percent":{"type":["number","null"]},"passed":{"type":"boolean"},"started_at":{"type":["string","null"],"format":"date-time"},"submitted_at":{"type":["string","null"],"format":"date-time"},"graded_at":{"type":["string","null"],"format":"date-time"}}},"Certificate":{"type":"object","properties":{"id":{"type":"integer"},"verification_code":{"type":"string"},"verification_url":{"type":"string"},"user_id":{"type":"integer"},"recipient_name":{"type":"string"},"course":{"type":"object","properties":{"id":{"type":"integer"},"title":{"type":"string"}}},"status":{"type":"string"},"score_percent":{"type":["number","null"]},"issued_at":{"type":["string","null"],"format":"date-time"},"expires_at":{"type":["string","null"],"format":"date-time"},"revoked_at":{"type":["string","null"],"format":"date-time"}}},"WebhookEvent":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Same on every retry and for every endpoint: use it to ignore repeats."},"type":{"type":"string","enum":["enrolment.created","enrolment.completed","enrolment.withdrawn","certificate.issued","certificate.revoked","billing.status_changed","billing.payment_failed","ping"]},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","description":"Holds `enrolment`, `certificate` or `billing`, in the same shape the API returns."}}}}}}