Developers · Updated October 21, 2026

Cubite API reference: REST endpoints, scopes, webhooks

Cubite LMS ships a headless REST API, HMAC-signed webhooks and a hosted MCP server in its Growth plan at $290 a month or $2,900 a year; the plan highlight reads "Headless API, webhooks and MCP server". This page is the endpoint index: every public route under /api/v1 with the scope it needs, generated from the same registry the admin API keys card shows, plus the authentication, error, rate-limit and webhook conventions as the code implements them.

Request and response schemas and an OpenAPI document are later steps, not on this page yet. The worked example is the SureCart integration post linked below.

Authentication

Create a key in Admin, under your site's Integrations tab, with the scopes it needs. The secret is shown once. Send it in the X-Cubite-Key header on every request to https://cubite.io/api/v1/...; the key, not the host, selects the site it acts on.

A key can carry a source IP allowlist (single IPs or CIDR ranges); a request from elsewhere gets 403. A credential approved for several sites picks the site per request with the X-Cubite-Site header; a site outside the grant is refused. The header's value is the site's id.

Authorization: Bearer tokens are accepted only by the MCP endpoint, which uses OAuth 2.1 with dynamic client registration; the REST routes take the key header only. Keys and tokens are stored as hashes.

Enroll a learner (the worked example)
curl -X POST https://cubite.io/api/v1/enrollments \
  -H "X-Cubite-Key: ck_..." \
  -H "Content-Type: application/json" \
  -d '{"email":"learner@example.com","courseId":"...","redirectTo":"/course/foo/courseware","sendInvite":true}'

The SureCart post walks through this call end to end: SureCart to Cubite enrollment with Ottokit.

Limits and conventions

  • Rate limits per key and minute: 120 writes (POST, PUT, PATCH, DELETE) and 600 reads; a 429 carries Retry-After, X-RateLimit-Limit and X-RateLimit-Remaining.
  • Bodies and responses are JSON. A failed request returns a JSON object with an error string; the common statuses are below. Others appear where they fit: 409 when a slug or name is already taken or a course still has enrolled learners, 413 when an upload exceeds its cap, 415 for a file type the media route refuses, 422 when a certificate cannot be issued or every learner in a bulk enrollment fails, and 502 when a provider upload fails.
  • List endpoints such as GET /api/v1/pages take limit and offset query parameters and return total, limit and offset beside the items.
  • A :write scope also satisfies the matching :read route, with one exception: forms:write reads form templates but not form responses, which need forms:read. The deprecated POST /api/v1/magic-link is not listed; use POST /api/v1/users/invite.
  • Write calls (POST, PUT, PATCH, DELETE) are recorded in an audit trail with the key, site, method, path and source IP; reads are not logged. Admin shows each key's last-used time beside the key.

Errors

StatusWhenBody
400The body is malformed or a required field is missing.{ "error": "<what is missing or invalid>" }
401No key, or a key that is unknown, revoked or expired.{ "error": "Missing X-Cubite-Key header" }, "Invalid API key", "API key revoked" or "API key expired"
403The key lacks the route's scope, its IP allowlist excludes the caller, the X-Cubite-Site header names a site outside the grant, or the credential is a list-only MCP catalog key.{ "error": "Key missing required scope: courses:write" }
404The object is not on the key's site.{ "error": "<object> not found" }
429The key passed 120 writes or 600 reads in a minute.{ "error": "Rate limit exceeded for this API key. Retry later." } with Retry-After, X-RateLimit-Limit and X-RateLimit-Remaining headers

Scopes (37)

A key carries only the scopes you give it. Scopes marked sensitive reach learner personal data, payment data or visitor search terms, create accounts, accept executable content or rewrite the emails learners receive; the consent screen shows them with emphasis when an assistant connection is approved.

ScopeGrantsSensitive
pages:readView pages and blog posts
pages:writeCreate and edit pages and blog posts
enrollments:readView enrollmentsYes
enrollments:writeEnroll and unenroll learnersYes
users:readView usersYes
users:writeCreate, invite and manage usersYes
courses:readView courses and their content
courses:writeCreate and edit courses and their content
site:readView site settings
site:writeEdit site settings, theme and homepage
question-banks:readView question banks
question-banks:writeManage question banks and questions
media:writeUpload media (images and files)
media:readView the site's video library
members:readView site membersYes
members:writeManage site members and rolesYes
groups:readView groups and cohortsYes
groups:writeManage groups and cohortsYes
learning-paths:readView learning pathsYes
learning-paths:writeManage learning pathsYes
packages:readView uploaded xAPI/SCORM packages
packages:writeUpload xAPI/SCORM packages (executable content)Yes
reports:readView aggregate analytics and reports
search-console:readView Google Search Console performance and SEO opportunitiesYes
certificates:readView issued certificatesYes
certificates:writeIssue, revoke and re-render certificatesYes
discussions:readView course discussions and the moderation queueYes
discussions:writePost, moderate and manage course discussionsYes
grading:readView assignment, open-response and quiz submissions to gradeYes
grading:writeGrade submissions and override scores and completionsYes
forms:readView form responses and form templatesYes
forms:writeCreate and delete reusable form templates
announcements:readView site announcements
announcements:writeCreate, edit and publish site announcements
payments:readView sales revenue and payment reconciliationYes
email-templates:writeEdit the site's transactional email copyYes
webhooks:readView webhook subscriptions and their delivery logYes

Endpoints (121 rows, 24 resources)

Method, path and the scope a key needs. Segments written :id, :qid, :courseId or :packageId are path parameters. The same table is shown in Admin beside your keys; both read one registry, checked against the route files by a script (npm run check:api-registry) that fails when a route has no row.

Pages and blog posts

/api/v1/pages
  • GET/api/v1/pages
    pages:read
  • POST/api/v1/pages
    pages:write
  • GET/api/v1/pages/:id
    pages:read
  • PATCH · DELETE/api/v1/pages/:id
    pages:write

Courses and content

/api/v1/courses
  • GET/api/v1/courses
    courses:read
  • POST/api/v1/courses
    courses:write
  • GET/api/v1/courses/:id
    courses:read
  • PATCH · DELETE/api/v1/courses/:id
    courses:write
  • GET/api/v1/courses/:id/content
    courses:read
  • PUT/api/v1/courses/:id/content
    courses:write
  • GET/api/v1/courses/:id/versions
    courses:read
  • POST/api/v1/courses/:id/duplicate
    courses:write

Site settings and homepage

/api/v1/site
  • GET/api/v1/site
    site:read
  • PATCH/api/v1/site
    site:write
  • GET/api/v1/site/homepage
    site:read
  • PUT/api/v1/site/homepage
    site:write

Question banks

/api/v1/question-banks
  • GET/api/v1/question-banks
    question-banks:read
  • POST/api/v1/question-banks
    question-banks:write
  • PATCH · DELETE/api/v1/question-banks/:id
    question-banks:write
  • GET/api/v1/question-banks/:id/questions
    question-banks:read
  • POST/api/v1/question-banks/:id/questions
    question-banks:write
  • PATCH · DELETE/api/v1/question-banks/:id/questions/:qid
    question-banks:write
  • GET · POST/api/v1/question-banks/tags
    question-banks:read/write
  • DELETE/api/v1/question-banks/tags/:id
    question-banks:write

Media

/api/v1/media
  • POST/api/v1/media
    media:write

Video library

/api/v1/videos
  • GET/api/v1/videos
    media:read

SCORM and xAPI packages

/api/v1/packages
  • GET/api/v1/packages/:packageId
    packages:read
  • PATCH/api/v1/packages/:packageId
    packages:write
  • GET/api/v1/packages
    packages:read
  • POST/api/v1/packages
    packages:write

Users

/api/v1/users
  • GET/api/v1/users
    users:read
  • POST/api/v1/users
    users:write
  • GET/api/v1/users/:id
    users:read
  • PUT/api/v1/users/:id
    users:write
  • POST/api/v1/users/invite
    users:write

Enrollments

/api/v1/enrollments
  • GET/api/v1/enrollments
    enrollments:read
  • POST · PUT · DELETE/api/v1/enrollments
    enrollments:write

Course applications

/api/v1/applications
  • GET/api/v1/applications
    enrollments:read
  • PATCH/api/v1/applications/:id
    enrollments:write

Learner transcript

/api/v1/transcript
  • GET/api/v1/transcript
    members:read

Site members and roles

/api/v1/members
  • GET/api/v1/members
    members:read
  • POST · DELETE/api/v1/members
    members:write

Groups and cohorts

/api/v1/groups
  • GET/api/v1/groups
    groups:read
  • POST/api/v1/groups
    groups:write
  • PATCH · DELETE/api/v1/groups/:id
    groups:write
  • GET/api/v1/groups/:id/members
    groups:read
  • POST · DELETE/api/v1/groups/:id/members
    groups:write
  • GET/api/v1/groups/:id/leaders
    groups:read
  • POST · DELETE/api/v1/groups/:id/leaders
    groups:write

Learning paths

/api/v1/learning-paths
  • GET/api/v1/learning-paths
    learning-paths:read
  • POST/api/v1/learning-paths
    learning-paths:write
  • GET/api/v1/learning-paths/:id
    learning-paths:read
  • PATCH · DELETE/api/v1/learning-paths/:id
    learning-paths:write
  • POST/api/v1/learning-paths/:id/enroll
    learning-paths:write
  • GET/api/v1/learning-paths/:id/learners
    learning-paths:read
  • PUT/api/v1/learning-paths/:id/steps
    learning-paths:write
  • GET/api/v1/learning-paths/:id/prerequisites
    learning-paths:read
  • PUT/api/v1/learning-paths/:id/prerequisites
    learning-paths:write

Reports

/api/v1/reports
  • GET/api/v1/reports/overview
    reports:read
  • GET/api/v1/reports/courses
    reports:read
  • GET/api/v1/reports/learners
    members:read
  • GET/api/v1/reports/completion-funnel
    reports:read
  • GET/api/v1/reports/item-analysis
    reports:read
  • GET/api/v1/reports/score-distribution
    reports:read
  • GET/api/v1/reports/cohort-comparison
    reports:read
  • GET/api/v1/reports/credits
    reports:read
  • GET/api/v1/reports/page-views
    reports:read
  • GET/api/v1/reports/at-risk
    members:read
  • GET/api/v1/reports/access-expiry
    members:read
  • GET/api/v1/reports/grading-sla
    members:read
  • GET/api/v1/reports/ecommerce
    payments:read
  • GET/api/v1/reports/paid-not-enrolled
    payments:read

Google Search Console

/api/v1/search-console
  • GET/api/v1/search-console/overview
    search-console:read
  • GET/api/v1/search-console/queries
    search-console:read
  • GET/api/v1/search-console/pages
    search-console:read
  • GET/api/v1/search-console/opportunities
    search-console:read
  • GET/api/v1/search-console/status
    search-console:read

Certificates

/api/v1/certificates
  • GET/api/v1/certificates
    certificates:read
  • POST/api/v1/certificates
    certificates:write
  • GET/api/v1/certificates/:id
    certificates:read
  • DELETE/api/v1/certificates/:id
    certificates:write
  • POST/api/v1/certificates/rerender
    certificates:write
  • GET/api/v1/certificates/config
    certificates:read

Discussions

/api/v1/discussions
  • GET/api/v1/discussions
    discussions:read
  • POST/api/v1/discussions
    discussions:write
  • GET/api/v1/discussions/threads/:id
    discussions:read
  • PATCH · DELETE/api/v1/discussions/threads/:id
    discussions:write
  • POST · PATCH · DELETE/api/v1/discussions/threads/:id/replies
    discussions:write
  • GET/api/v1/discussions/moderation
    discussions:read
  • PATCH/api/v1/discussions/moderation
    discussions:write
  • GET/api/v1/discussions/topics
    discussions:read
  • POST · PATCH · DELETE/api/v1/discussions/topics
    discussions:write
  • GET/api/v1/discussions/prompts
    discussions:read
  • POST · DELETE/api/v1/discussions/prompts
    discussions:write
  • GET/api/v1/discussions/moderators
    discussions:read
  • POST · DELETE/api/v1/discussions/moderators
    discussions:write

Grading

/api/v1/grading
  • GET/api/v1/grading/assignments
    grading:read
  • GET/api/v1/grading/assignments/:id
    grading:read
  • POST/api/v1/grading/assignments/:id/grade
    grading:write
  • GET/api/v1/grading/open-responses
    grading:read
  • GET/api/v1/grading/open-responses/:id
    grading:read
  • POST/api/v1/grading/open-responses/:id/assess
    grading:write
  • GET/api/v1/grading/quiz-attempts
    grading:read
  • GET/api/v1/grading/quiz-attempts/:id/review
    grading:read
  • POST/api/v1/grading/quiz-attempts/:id/override
    grading:write
  • GET/api/v1/grading/courses/:courseId/learners
    grading:read
  • POST/api/v1/grading/courses/:courseId/completion-override
    grading:write

Forms

/api/v1/forms
  • GET/api/v1/forms/responses
    forms:read
  • GET/api/v1/forms/templates
    forms:read
  • POST/api/v1/forms/templates
    forms:write
  • GET/api/v1/forms/templates/:id
    forms:read
  • DELETE/api/v1/forms/templates/:id
    forms:write

Announcements

/api/v1/announcements
  • GET/api/v1/announcements
    announcements:read
  • POST/api/v1/announcements
    announcements:write
  • GET/api/v1/announcements/:id
    announcements:read
  • PATCH · DELETE/api/v1/announcements/:id
    announcements:write

Email templates

/api/v1/email-templates
  • GET/api/v1/email-templates
    site:read
  • PATCH/api/v1/email-templates
    email-templates:write

Webhooks

/api/v1/webhooks
  • GET/api/v1/webhooks
    webhooks:read
  • GET/api/v1/webhooks/:id/deliveries
    webhooks:read

Webhooks

Subscriptions are created in Admin, under the same Integrations tab, with a URL, the event types to receive (or * for all) and a signing secret, yours or one Cubite generates and shows once. Each delivery is an HTTP POST with a JSON body and three headers:

  • X-Cubite-Event: the event type
  • X-Cubite-Signature: sha256=<hex HMAC-SHA256 of the raw body, keyed with the secret>
  • X-Cubite-Delivery-Id: the delivery's id

Verify by recomputing the HMAC over the raw request body with your secret and comparing it to the header in constant time; reject anything else. Deliveries and their status are readable through GET /api/v1/webhooks and GET /api/v1/webhooks/:id/deliveries (scope webhooks:read).

Event types (17)

  • enrollment.created
  • course.completed
  • certificate.issued
  • quiz.passed
  • quiz.failed
  • form.submitted
  • assignment.submitted
  • assignment.passed
  • assignment.failed
  • assignment.returned
  • open_response.submitted
  • open_response.self_assessed
  • open_response.peer_assessed
  • open_response.staff_assessed
  • open_response.passed
  • open_response.failed
  • open_response.retried

Frequently asked questions

Does Cubite LMS have a public API?
Yes. Cubite LMS exposes a headless REST API under /api/v1 (121 endpoint rows on this page), HMAC-signed webhooks and a hosted MCP server with 137 tools, all included in the Growth plan at $290 a month or $2,900 a year.
How do I authenticate?
Create an API key in Admin, under your site's Integrations tab, with the scopes it needs, and send it in the X-Cubite-Key header on every request. A request without the header gets 401 Missing X-Cubite-Key header. Authorization: Bearer tokens are accepted only by the MCP endpoint, which uses OAuth 2.1.
Which scopes exist?
37 scopes, listed on this page with the permission each grants, such as courses:read, enrollments:write and reports:read. A :write scope also satisfies the matching :read route, with one exception: forms:write reads form templates but not form responses, which need forms:read. Keys carry only the scopes you give them, and a key can be limited to an IP allowlist.
How are webhooks signed?
Each delivery is a POST with a JSON body and three headers: X-Cubite-Event (the event type), X-Cubite-Signature (sha256= followed by the hex HMAC-SHA256 of the raw body, keyed with the subscription's secret) and X-Cubite-Delivery-Id. Verify by recomputing the HMAC over the raw body and comparing it in constant time.
Is there an OpenAPI document?
Not yet. This page is the endpoint index with the auth, error, rate-limit and webhook conventions; a request-and-response reference and an OpenAPI document are the next steps.

Building an integration? Tell us what it has to do

A 30-minute call on your data flow, or email amir@cubite.io with the endpoints you need and the system on the other side.

Support

How can we help?

Send us a message and we'll get back to you shortly.

We typically respond within 24 hours

Cubite API reference: REST endpoints, scopes, webhooks | Cubite