Summary and recommendation
The TalentLMS REST API is available at `https://[your-domain].talentlms.com/api/v1` and authenticates via HTTP Basic Auth using the account-wide API key as the username with an empty password (Base64-encoded as `apikey:`).
There is no scoped token or per-user credential system;
the key carries full admin-level access.
All request bodies must be `application/x-www-form-urlencoded` - sending JSON payloads will produce errors without a clear diagnostic message.
Pagination uses `page` and `per_page` parameters (default 20, max 1000).
No official rate limit thresholds, rate-limit headers, or `Retry-After` signals are documented;
implement conservative request pacing for any bulk operation.
Webhooks are not natively supported;
event-driven patterns require polling or a third-party automation layer.
SCIM 2.0 is available on all paid plans but requires SAML 2.0 SSO to be configured first.
The SCIM endpoint is IdP-specific and generated within the admin UI - it is not a static public URL.
Supported IdPs include Okta, Microsoft Entra ID, and OneLogin.
Integrating TalentLMS into an identity graph via SCIM enables automated provisioning and deprovisioning across the full user lifecycle without direct REST API calls for routine operations.
API quick reference
| Has user API | Yes |
| Auth method | HTTP Basic Auth (API key as username, empty password) |
| Base URL | Official docs |
| SCIM available | Yes |
| SCIM plan required | All paid plans (Core and above); SSO must be configured as a prerequisite |
Authentication
Auth method: HTTP Basic Auth (API key as username, empty password)
Setup steps
- Log in to TalentLMS as an Administrator.
- Navigate to Account & Settings > Basic Settings.
- Locate the API key field and copy your API key.
- When making requests, use HTTP Basic Auth: set the API key as the username and leave the password blank.
- Encode credentials as Base64 for the Authorization header: Authorization: Basic base64(apikey:)
User object / data model
| Field | Type | Description | On create | On update | Notes |
|---|---|---|---|---|---|
| id | integer | Unique user identifier | auto-assigned | read-only | System-generated |
| login | string | Username for login | required | optional | Must be unique |
| first_name | string | User's first name | required | optional | |
| last_name | string | User's last name | required | optional | |
| string | User's email address | required | optional | Must be unique | |
| password | string | User's password | required | optional | Write-only; not returned in responses |
| role | string | User role in the system | optional | optional | Values: learner-admin, instructor, learner (default: learner) |
| status | string | Account status | optional | optional | Values: active, inactive |
| bio | string | User biography text | optional | optional | |
| timezone | string | User's timezone | optional | optional | e.g., America/New_York |
| language | string | Preferred interface language | optional | optional | ISO language code |
| level | integer | Gamification level | read-only | read-only | System-managed |
| points | integer | Gamification points | read-only | read-only | System-managed |
| last_updated | datetime | Timestamp of last profile update | auto-assigned | auto-updated | ISO 8601 format |
| avatar | string (URL) | URL to user avatar image | optional | optional | |
| custom_field_1..custom_field_N | string | Custom user profile fields | optional | optional | Field names depend on account configuration; use field key from admin settings |
Core endpoints
List all users
- Method: GET
- URL:
https://[domain].talentlms.com/api/v1/users - Watch out for: Returns a flat array; use page and per_page for pagination. Default page_size is 20.
Request example
GET /api/v1/users?page=1&per_page=20
Authorization: Basic base64(apikey:)
Response example
[
{
"id": 1,
"login": "jdoe",
"first_name": "John",
"last_name": "Doe",
"email": "jdoe@example.com",
"role": "learner",
"status": "active"
}
]
Get a single user by ID
- Method: GET
- URL:
https://[domain].talentlms.com/api/v1/users/:id - Watch out for: Can also look up by email using /users/email:[email] instead of numeric ID.
Request example
GET /api/v1/users/42
Authorization: Basic base64(apikey:)
Response example
{
"id": 42,
"login": "jdoe",
"first_name": "John",
"last_name": "Doe",
"email": "jdoe@example.com",
"role": "learner",
"status": "active"
}
Create a user
- Method: POST
- URL:
https://[domain].talentlms.com/api/v1/users - Watch out for: Request body must be form-encoded, not JSON. login and email must be unique across the account.
Request example
POST /api/v1/users
Content-Type: application/x-www-form-urlencoded
first_name=John&last_name=Doe&email=jdoe@example.com&login=jdoe&password=Secret123
Response example
{
"id": 43,
"login": "jdoe",
"first_name": "John",
"last_name": "Doe",
"email": "jdoe@example.com",
"role": "learner",
"status": "active"
}
Update a user
- Method: PUT
- URL:
https://[domain].talentlms.com/api/v1/users/:id - Watch out for: Uses PUT, not PATCH; only fields included in the body are updated. Omitting a field does not clear it.
Request example
PUT /api/v1/users/43
Content-Type: application/x-www-form-urlencoded
first_name=Jonathan&status=inactive
Response example
{
"id": 43,
"login": "jdoe",
"first_name": "Jonathan",
"status": "inactive"
}
Delete a user
- Method: DELETE
- URL:
https://[domain].talentlms.com/api/v1/users/:id - Watch out for: Deletion is permanent and removes all user data including course progress. Consider deactivating (status=inactive) instead.
Request example
DELETE /api/v1/users/43
Authorization: Basic base64(apikey:)
Response example
{
"id": "43",
"message": "Operation completed successfully"
}
Enroll user in a course
- Method: POST
- URL:
https://[domain].talentlms.com/api/v1/addusertocourse - Watch out for: This is a separate endpoint, not nested under /users. Role in course defaults to learner unless role parameter is specified.
Request example
POST /api/v1/addusertocourse
Content-Type: application/x-www-form-urlencoded
user_id=43&course_id=7
Response example
{
"user_id": "43",
"course_id": "7",
"message": "Operation completed successfully"
}
Get user's course status
- Method: GET
- URL:
https://[domain].talentlms.com/api/v1/getuserstatusincourse - Watch out for: Returns null fields if user has not yet accessed the course after enrollment.
Request example
GET /api/v1/getuserstatusincourse?user_id=43&course_id=7
Authorization: Basic base64(apikey:)
Response example
{
"user_id": "43",
"course_id": "7",
"completion_status": "completed",
"completion_percentage": 100
}
Get user by email (lookup)
- Method: GET
- URL:
https://[domain].talentlms.com/api/v1/users/email::email - Watch out for: The colon-prefixed email syntax is specific to TalentLMS. URL-encode the email address to avoid parsing issues.
Request example
GET /api/v1/users/email:jdoe@example.com
Authorization: Basic base64(apikey:)
Response example
{
"id": 43,
"login": "jdoe",
"email": "jdoe@example.com",
"status": "active"
}
Rate limits, pagination, and events
Rate limits: TalentLMS does not publicly document specific rate limit thresholds or per-plan tiers in its official API docs.
Rate-limit headers: No
Retry-After header: No
Rate-limit notes: No official rate limit figures, headers, or Retry-After behavior documented. Contact TalentLMS support for enterprise-level guidance.
Pagination method: offset
Default page size: 20
Max page size: 1000
Pagination pointer: page, per_page
Webhooks available: No
Webhook notes: TalentLMS does not offer native outbound webhooks in its official documentation. Event-driven integrations are typically handled via polling the REST API or using third-party automation platforms (e.g., Zapier, Make).
Alternative event strategy: Poll the REST API for user and course status changes, or use the TalentLMS Zapier integration for event-triggered workflows.
SCIM API status
SCIM available: Yes
SCIM version: 2.0
Plan required: All paid plans (Core and above); SSO must be configured as a prerequisite
Endpoint: Tenant-specific SCIM endpoint provided within the TalentLMS SSO/SCIM settings UI after enabling SCIM for the configured IdP
Supported operations: Create users (POST /Users), Update users (PUT /Users/:id), Deactivate users (PATCH /Users/:id with active=false), List users (GET /Users), Get user by ID (GET /Users/:id)
Limitations:
- SCIM endpoint URL is IdP-specific and generated within the TalentLMS admin UI; it is not a static public endpoint.
- SSO (SAML 2.0) must be configured before SCIM provisioning can be enabled.
- Supported IdPs documented: Okta, Microsoft Entra ID (Azure AD), OneLogin.
- Group/branch provisioning support may vary by IdP connector.
- Hard deletion via SCIM may not be supported; deactivation (active=false) is the documented deprovisioning action.
Common scenarios
Provision and enroll a new employee: POST /api/v1/users with form-encoded first_name, last_name, email, login, password, and role=learner;
capture the returned id;
then POST /api/v1/addusertocourse with user_id and course_id.
Check for duplicate login or email first via GET /api/v1/users/email:[address] - the create call returns an error on collision with no upsert behavior.
Deactivate a departing employee: GET /api/v1/users/email:[address] to resolve the numeric id, then PUT /api/v1/users/:id with status=inactive.
Prefer this over DELETE - deletion is irreversible and removes all course completion records.
Via SCIM, send PATCH /Users/:id with {"op":"replace","path":"active","value":false} through the IdP connector;
SCIM deprovisioning requires an active SSO configuration.
Bulk-sync from an HR system: paginate GET /api/v1/users?page=1&per_page=1000 to build a local email-to-id map, then create, update, or deactivate per record.
No batch endpoint exists - every operation is a discrete HTTP call.
With no documented rate limits, implement deliberate pacing;
silent throttling is possible.
Provision a new employee and enroll in onboarding course
- POST /api/v1/users with first_name, last_name, email, login, password, and role=learner to create the user account.
- Capture the returned user id from the response.
- POST /api/v1/addusertocourse with user_id and the target onboarding course_id to enroll the user.
- Optionally GET /api/v1/getuserstatusincourse to confirm enrollment status.
Watch out for: Request bodies must be form-encoded. If login or email already exists, the create call returns an error - check for duplicates first using GET /api/v1/users/email:[address].
Deactivate a departing employee
- GET /api/v1/users/email:[employee_email] to retrieve the user's numeric id.
- PUT /api/v1/users/:id with status=inactive to deactivate the account without deleting learning history.
- If using SCIM, send a PATCH /Users/:id with {"op":"replace","path":"active","value":false} via the IdP-managed SCIM connector.
Watch out for: Prefer deactivation over DELETE to preserve course completion records. SCIM deprovisioning requires SSO to be active.
Bulk-sync users from an external HR system
- Paginate GET /api/v1/users?page=1&per_page=1000 to retrieve all existing TalentLMS users and build a local email-to-id map.
- For each HR record, check if the email exists in the map.
- If not found, POST /api/v1/users to create the user.
- If found and attributes differ, PUT /api/v1/users/:id with changed fields.
- For users present in TalentLMS but absent from HR, PUT /api/v1/users/:id with status=inactive.
Watch out for: No bulk/batch endpoint exists; each create or update is a separate HTTP call. No documented rate limits, so implement conservative request pacing to avoid throttling.
Why building this yourself is a trap
The account-wide API key is the single credential for all API access; there is no scope restriction or rotation mechanism documented, which means a leaked key exposes full admin operations across the entire tenant.
The non-standard email lookup syntax (/users/email:[address] with a colon separator, not a query parameter) is a parsing edge case - URL-encode the address to avoid silent misroutes.
The PUT /api/v1/users/:id endpoint behaves as a partial update in practice (omitting a field does not clear it), but it is declared as PUT, not PATCH - callers building idempotent sync logic should verify field behavior against their target fields rather than assuming full-replacement semantics. Custom user profile fields are account-specific;
field keys must be retrieved from the admin UI before use in API calls, and there is no endpoint to enumerate them programmatically.
SCIM's dependency on a pre-configured SSO connection means that any identity graph integration path through SCIM carries an implicit prerequisite: SSO must be live and stable before provisioning automation can be trusted. Teams that configure SCIM before validating their SSO setup will encounter provisioning failures that surface at the IdP layer, not within TalentLMS itself.
Automate TalentLMS workflows without one-off scripts
Stitchflow builds and maintains end-to-end IT automation across your SaaS stack, including apps without APIs. Built for exactly how your company works, with human approvals where they matter.