Course Bundle
Subscriptions
Memberships
Gift Course
Third-Party Integrations
Tutor LMS Shortcodes
Course Bundle
Subscriptions
Memberships
Gift Course
Third-Party Integrations
Tutor LMS Shortcodes

Introduction to REST API

Tutor LMS is fully integrated with the WordPress REST API. This allows Tutor LMS data to be read and, with Tutor LMS Pro, created, updated, and deleted, using JSON requests. It supports standard HTTP verbs, API key permissions, and token-based user identity.

Important: Authentication changed in Tutor LMS 4.2.0. Basic Auth with an API key and secret no longer works. Your application now sends its key and secret once to log in, and receives an access token that identifies the end user. API keys no longer act as the key owner, and responses depend on the user the token belongs to. 

Requirements

To use the latest version of the REST API, you must be using:

  • Tutor LMS v4.2 or later

Tutor LMS Free provides a read-oriented API for courses, curriculum, quizzes, authors, and ratings, plus the authentication endpoints. Routes that create, update, or delete data, such as enrollments and assignment submissions, require Tutor LMS Pro.

You can access the API over both HTTP and HTTPS connections. But, HTTPS is strongly recommended. 

Request / Response Format

The default response format of the Tutor LMS REST API is JSON, so you use plain JSON to set or update resource attributes. Every successful request returns a 200 OK status. 

Most responses use this envelope:

{
  "code": "success",
  "message": "Human-readable message",
  "data": {}
}

General notes about responses:

  1. Dates are returned in the format YYYY-MM-DD HH:MM:SS.
  2. Resource IDs are returned as integers.
  3. Decimal monetary amounts (course prices or totals) are returned as strings with two decimal places.
  4. A request for an empty collection or a missing resource can return HTTP 200 with “code”: “not_found” and an empty data.
  5. Responses depend on the user the access token belongs to. See Access and responses below.

How authentication works

Two credentials work together:

  • API key and secret identify your application and set what it is allowed to do through its permission level (Read, Write, Delete, or All). You send them only to log in.
  • Access token identifies the end user. It is short-lived, and your application sends it with every other request. A refresh token renews it without logging in again and can be revoked.

The authentication flow:

  1. Create an API key in Tutor LMS and choose its permission level.
  2. Log in with the key and secret in Headers and the end user’s username and password in the Body. You will receive an access token and a refresh token.
  3. Save the access token and send the access token with each request.
  4. When the access token expires, use the refresh token to get a new pair of tokens.
  5. Log out to revoke the refresh token.

Here’s the detailed step-by-step process:

Step 1: Create an API key

Create REST API key

Go to Tools > REST API in your WordPress dashboard. Click Add New to create an API key and secret pair for a user. Each key has a permission level:

PermissionWhat it allows
Read[Read requests, for example GET]
Write[Create and update requests]
Delete[Delete requests]
AllAll of the above

Step 2: Log in to get tokens

URL: https://yourwebsiteaddress/wp-json/tutor/v1/auth/login
Type: POST

Send your API key and secret as headers:

KeyValue
Content-Typeapplication/json
Tutor-Api-KeyYOUR_API_KEY
Tutor-Api-SecretYOUR_API_SECRET
Set login header

Request body:

set Admin id and password for authentication
FieldTypeRequiredDescription
usernamestringYesThe user’s WordPress login or email
passwordstringYesThe user’s password
{
  "username": "END_USER_USERNAME", 
  "password": "END_USER_PASSWORD"
}

Successful response:

{
  "access_token": "ACCESS_TOKEN",
  "expires_in": 86400,
  "refresh_token": "REFRESH_TOKEN",
  "user_id": 12,
  "display_name": "Jane Doe"
}

expires_in is the access token lifetime in seconds. 86400 is the default of 1 day, and 0 means the token does not expire.

If the API key is missing or invalid, the request is refused with rest_forbidden. 

Step 3: Send authenticated requests

Save the access token as a Bearer token. In Postman, open the Authorization tab, choose Bearer Token, and enter the access token.

set bearer token

Your API key and secret are not needed for any requests other than login. The token is tied to the key it was created with, so the key’s permission level still applies. 

Step 4: Refresh an expired access token

Access token and refresh token

When the access token expires, request a new pair of tokens with the refresh token. No API key headers are needed.

URL: https://yourwebsiteaddress/wp-json/tutor/v1/auth/refresh
Type: POST
{
  "refresh_token": "YOUR_REFRESH_TOKEN"
}

The response has the same shape as the login response, with a new access token and a new refresh token. Refresh tokens are tied to the API key they were issued with. If that key has been deleted or revoked, the request returns 403.

Step 5: Log out

URL: https://yourwebsiteaddress/wp-json/tutor/v1/auth/logout 
Type: POST
FieldTypeRequiredDescription
refresh_tokenstringNo*Ends the session for this refresh token
allbooleanNoIf true, ends all refresh sessions for the user

* Send refresh_token, or send all: true with a valid access token in the Authorization: Bearer or Tutor-User-Token header.

Successful response:

{ "success": true }

Token lifetimes

Access and refresh token lifetimes are configurable. Both are set in days on the Tools > Rest API page, under Token Lifetime.

TokenDefault valueAllowed range
Access token lifetime1 day1 to 365 days
Refresh token lifetime30 days1 to 365 days
  • The refresh token lifetime must be greater than the access token lifetime.
  • Setting a lifetime to 0 means the token never expires. Tutor LMS strongly recommends against this, because a stolen token would remain valid indefinitely.

Security best practices

  • Store keys, secrets, and tokens securely on the server side. Never include them in client-side code or public repositories.
  • Use HTTPS for all requests.
  • Give each API key the lowest permission level it needs.
  • Treat the refresh token like a password. It can be used to obtain new access tokens.
  • Log out to revoke refresh tokens when a session ends.

Access and responses

Responses and access depend on the user the access token belongs to, and on the API key’s permission level.

Course content. Course details, curriculum, topics, lessons, announcements, quizzes, quiz answers, and quiz attempts are available only when the course is public, the user is enrolled, or the user is an instructor or admin with access to that course. Otherwise, the API returns 403. (Pro routes for enrollments, assignments, quiz attempts, and Q&A also check who is making the request and whether they can access the specific item.)

Private user details. Author and course responses include only the user’s ID, display name, and nicename by default. Login name, email, registration date, and URL are included only when the caller is the user themselves, has the list_users capability, or is an instructor of a course the user is enrolled in. Reviewer email addresses in course ratings follow the same rule.

Quiz answers. Correct-answer information is removed from quiz responses until the learner completes an attempt, unless the caller can manage the course. For choice questions, the options are returned without is_correct. For other question types, the answers are returned empty.

Quiz attempts. Callers receive only their own attempts, unless they can manage the course.

Requirements by route

RouteMethodWhat it needs
/auth/loginPOSTAPI key and secret (Read or higher)
/auth/refreshPOSTRefresh token
/auth/logoutPOSTRefresh token, or access token with all: true
/coursesGETAccess token, Read
/courses/{id}GETAccess token, Read, course content access
/course-contents/{id}GETAccess token, Read, course content access
/topicsGETAccess token, Read, course content access
/lessonsGETAccess token, Read, content access to the topic’s course
/course-announcement/{id}GETAccess token, Read, course content access
/quizzes, /quizzes/{id}GETAccess token, Read, content access to the quiz’s course
/quiz-question-answer/{id}GETAccess token, Read, content access to the quiz’s course
/quiz-attempt-details/{id}GETAccess token, Read, content access to the quiz’s course
/author-information/{id}GETAccess token, Read
/course-rating/{id}GETAccess token, Read

If a caller isn’t allowed to perform a request, the API returns 403 Forbidden.

Errors

Occasionally, you may encounter errors when accessing the REST API. Possible errors:

HTTP Status CodeError CodeDescription
400 Bad RequestINVALID_PARAMInvalid or missing parameters in the request.
401 UnauthorizedUNAUTHORIZEDThe access token is missing, invalid, or expired. [Confirm whether expired and invalid tokens use separate error codes.]
403 ForbiddenFORBIDDENThe API key permission or the user’s access does not allow this resource or action. Also returned when a refresh token’s API key is invalid or revoked.
500 Internal Server ErrorINTERNAL_SERVER_ERRORThe server encountered an unexpected condition.
404 Not FoundNOT_FOUNDThe requested resource could not be found.
405 Method Not AllowedMETHOD_NOT_ALLOWEDThe HTTP method used is not allowed for this resource.
408 Request TimeoutREQUEST_TIMEOUTThe server timed out while waiting to execute the request.
502 Bad GatewayBAD_GATEWAYInvalid response received from an upstream server.
504 Gateway TimeoutGATEWAY_TIMEOUTThe server, while acting as a gateway or proxy, did not receive a timely response from an upstream server.
505 HTTP Version Not SupportedHTTP_VERSION_NOT_SUPPORTEDThe server does not support the HTTP protocol version used in the request.
507 Insufficient StorageINSUFFICIENT_STORAGEThe server is unable to store the representation needed to complete the request.
508 Loop DetectedLOOP_DETECTEDThe server detected an infinite loop while processing a request.

WordPress errors use the standard REST error format, with code, message, and data status. 

For example, a request with a missing or invalid API key at login returns:

{
  "code": "rest_forbidden",
  "message": "Sorry, you are not allowed to do that.",
  "data": { "status": 401 }
}

Note: Only errors with status codes 400, 401, 403, and 500 originate from Tutor LMS. WordPress handles all other errors.

Join the world’s #1 Tutor LMS community

Build, manage, and scale your eLearning business with the most powerful WordPress LMS — all in one place.

Crafted by Humans

© 2026 All Rights Reserved