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, all five Reports
(completions, enrollments, compliance, user activity, course performance) plus
async CSV/XLSX export, 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.
Prefer Postman? Import the ready-made Postman collection — every endpoint below with a pre-built environment, tests, and sample code in 20+ languages.
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 the full reports surface with async export) is live.
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):
- User enrollments sub-resource:
GET /users/{id}/enrollments(GET /users/{id}/transcriptis live — see Users). - Bulk user import:
POST /users/bulk. - OAuth-style token exchange:
POST /auth/token.
Until then:
- Completion events: subscribe to webhooks for push delivery, or poll
GET /completions(respecting rate limits). - Bulk user provisioning: use SCIM 2.0 provisioning from your IdP, or loop
POST /users.
Versioning
Every endpoint lives under /api/v1/. We add to v1 (new endpoints, new
optional parameters, new response fields) but never break it — anything breaking
goes in a new prefix, and a deprecated endpoint gets at least 12 months of
Deprecation / Sunset headers first.
Two things to build in from the start: ignore response fields you do not
recognise, and log the Deprecation header. Full rules in
Versioning & Deprecation.
Next Steps
- Postman Collection — Every endpoint importable, with sample code in your language
- Versioning & Deprecation — What may change, and how much warning you get
- 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