API ReferenceGetting Started

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

  1. Sign in to your EmbayLMS tenant.
  2. Navigate to Settings -> Integrations -> API Keys (the API Keys tab of the unified Integrations menu).
  3. Click Create API Key.
  4. Name it Quickstart Test and select the read scope (available scopes are read, write, admin — the live read endpoints only need read).
  5. 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_0000000000000000000000000000

See 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, and GET /completions.

Next Steps