Getting Started
This guide walks through the most common API tasks in under 15 minutes. By the end you will have created an API key, listed your users, pulled enrollments with filters, and retrieved audit-grade completion records.
The public API covers reads and writes: Users (list, create,
update, deactivate), Enrollments (list, create, update,
cancel — including POST /enrollments/bulk), Courses and
modules, Groups and membership, tranche-1 Reports
(/reports/completions, /reports/enrollments), Completions,
the public GET /plans catalog, and the LTI 1.3 launch endpoints.
A few surfaces remain planned — see
What’s still planned below.
Prerequisites: Admin access to your EmbayLMS tenant.
Base URL: all requests go to your tenant’s subdomain:
https://{your-subdomain}.embaylms.com/api/v1/Step 1: Create Your First API Key
- Sign in to your EmbayLMS tenant.
- Navigate to Settings -> Integrations -> API Keys (the API Keys tab of the unified Integrations menu).
- Click Create API Key.
- Name it
Quickstart Testand select thereadscope (available scopes areread,write,admin— the live read endpoints only needread). - Click Create and copy the key — it is shown only once.
Your key looks like: ems_live_0000000000000000000000000000
Store it in an environment variable:
export EMBAYLMS_API_KEY=ems_live_0000000000000000000000000000See Authentication for security best practices.
Step 2: Make Your First API Call — List Users
curl
curl "https://{your-subdomain}.embaylms.com/api/v1/users?role=learner&per_page=5" \
-H "Authorization: Bearer $EMBAYLMS_API_KEY"Node.js
const apiKey = process.env.EMBAYLMS_API_KEY;
const response = await fetch(
'https://{your-subdomain}.embaylms.com/api/v1/users?role=learner&per_page=5',
{ headers: { 'Authorization': `Bearer ${apiKey}` } }
);
const { data, meta } = await response.json();
console.log(`Found ${meta.total} learners`);
data.forEach(user => console.log(`- ${user.first_name} ${user.last_name}`));Example Response
{
"data": [
{
"id": "a3f2c1d0-4e5b-6789-abcd-ef0123456789",
"email": "jane.doe@acme.com",
"first_name": "Jane",
"last_name": "Doe",
"role": "learner",
"is_active": true,
"external_id": "EMP-00412",
"created_at": "2026-01-15T09:00:00Z"
}
],
"meta": { "page": 1, "per_page": 5, "total": 342 },
"error": null
}Every response uses the same { data, meta, error } envelope. Note a user’s
id — you can use it to filter enrollments in Step 3.
See Users for the full endpoint reference.
Step 3: List Enrollments
Pull enrollments across the tenant, filtered by status and/or user:
curl
curl "https://{your-subdomain}.embaylms.com/api/v1/enrollments?status=active&user_id=YOUR_USER_ID" \
-H "Authorization: Bearer $EMBAYLMS_API_KEY"Supported filters: status (active, completed, dropped, expired,
waitlisted, pending_approval), user_id, course_id, plus page /
per_page pagination.
Example Response
{
"data": [
{
"id": "d6e5f4a3-7b8c-9012-defa-123456789012",
"user_id": "a3f2c1d0-4e5b-6789-abcd-ef0123456789",
"course_id": "e7f6a5b4-8c9d-0123-efab-234567890123",
"status": "active",
"due_date": "2026-09-01T00:00:00Z",
"completed_at": null,
"source": "native",
"created_at": "2026-05-01T08:00:00Z"
}
],
"meta": { "page": 1, "per_page": 50, "total": 23 },
"error": null
}See Enrollments for the full endpoint reference.
Step 4: Pull Completion Records
The Completions endpoint is the audit-grade record of who finished what and
when — including historical completions imported from a previous LMS
(source: "import"). Use it for compliance reporting and BI syncs.
curl
curl "https://{your-subdomain}.embaylms.com/api/v1/completions?per_page=100" \
-H "Authorization: Bearer $EMBAYLMS_API_KEY"Node.js — page through everything
async function fetchAllCompletions() {
const all = [];
let page = 1;
while (true) {
const response = await fetch(
`https://{your-subdomain}.embaylms.com/api/v1/completions?page=${page}&per_page=200`,
{ headers: { 'Authorization': `Bearer ${process.env.EMBAYLMS_API_KEY}` } }
);
const { data, meta } = await response.json();
all.push(...data);
if (page * meta.per_page >= meta.total) break;
page++;
}
return all;
}See Completions for the full endpoint reference.
Bonus: The Public Plans Catalog
GET /api/v1/plans is the one endpoint that needs no authentication — it
serves the canonical subscription-tier catalog (pricing, caps, capabilities):
curl "https://{your-subdomain}.embaylms.com/api/v1/plans"See Plans.
What’s still planned
The write/management API (users, enrollments including bulk, courses, groups,
and reports tranche-1) is live — it shipped as LMS-571/LMS-573/LMS-574.
The following surfaces are still planned and not yet implemented (calls to
them return 404 today; their doc sections document the planned contract so you
can design ahead — do not build production integrations against them until
release):
- Reports tranche-2:
/reports/compliance,/reports/user-activity,/reports/course-performance, and async report export. - User sub-resources:
GET /users/{id}/enrollments,GET /users/{id}/transcript. - Bulk user import:
POST /users/bulk. - OAuth-style token exchange:
POST /auth/token. - Outbound webhook delivery for event push.
Until then:
- Completion events: poll
GET /completions(respecting rate limits) instead of webhooks. - Bulk user provisioning: use SCIM 2.0 provisioning from your IdP, or loop
POST /users. - Advanced reporting: build on
/reports/completions,/reports/enrollments,GET /enrollments, andGET /completions.
Next Steps
- Authentication — Key format, rotation, and scopes
- Pagination & Filtering — Page through large result sets
- Rate Limits — Stay under limits with backoff strategies
- Errors — Handle every error type correctly
- LTI 1.3 — Launch EmbayLMS content from an external platform