Skip to main content
DocsIntegration GuidesLTI 1.3 Integration
Back to docs

LTI 1.3 Integration

LMS setup, launch flow, grade passback, roster sync

integration
lti-integration

LTI 1.3 Integration Guide

This guide walks external system administrators through integrating their Learning Management System (LMS) with Creatiq using the LTI 1.3 Advantage standard.


1. Overview

Creatiq implements the IMS Global LTI 1.3 Advantage specification, enabling seamless integration with any LTI 1.3-compliant LMS. The integration supports:

  • Resource Link Launch -- Single sign-on from the LMS directly into Creatiq H5P content.
  • Deep Linking (LTI-DL) -- Instructors can browse and select Creatiq content from within the LMS course builder.
  • Assignment and Grade Services (AGS) -- Scores from H5P interactions flow back to the LMS gradebook automatically.
  • Names and Role Provisioning Services (NRPS) -- Course rosters sync from the LMS into Creatiq for enrollment management.

LTI integration is available on the Premium plan and requires the lti-integration feature flag to be enabled for your tenant.


2. Prerequisites

Before starting, confirm the following:

RequirementDetail
LMS versionMust support LTI 1.3 Advantage (e.g., Moodle 3.10+, Canvas, Blackboard Ultra, Brightspace)
Creatiq planPremium or Enterprise (feature flag: lti-integration)
Network accessThe LMS must be able to reach the Creatiq server over HTTPS
Admin privilegesYou need LMS administrator access to register an external tool
Environment variableLTI_ENCRYPTION_KEY must be set on the Creatiq server

Creatiq Environment Variables

The following environment variables must be configured on the Creatiq server:

VariableRequiredDescription
LTI_ENCRYPTION_KEYYesEncryption key for LTI security operations. Must be set for LTI to be enabled.
LTI_PLATFORM_URLNoDefault LMS platform URL (for single-platform setups)
LTI_PLATFORM_NAMENoHuman-readable name for the default platform
LTI_CLIENT_IDNoOAuth 2.0 client ID assigned by the default platform
LTI_AUTH_ENDPOINTNoPlatform's OIDC authentication endpoint
LTI_TOKEN_ENDPOINTNoPlatform's OAuth 2.0 token endpoint
LTI_AUTH_SERVERNoAuthorization server URL (if different from token endpoint)
NEXT_PUBLIC_APP_URLYesPublic URL of the Creatiq application (e.g., https://creatiq.example.com)

If LTI_ENCRYPTION_KEY is not set, all LTI features are automatically disabled and the /lti/launch endpoint returns 503 Service Unavailable.


3. Platform Registration

Step 1: Retrieve Creatiq Tool Configuration

Call the configuration endpoint to get the URLs your LMS needs:

GET /lti/config
Authorization: Bearer <admin-token>

Response:

{
  "success": true,
  "data": {
    "enabled": true,
    "launchUrl": "https://creatiq.example.com/lti/launch",
    "jwksUrl": "https://creatiq.example.com/lti/jwks",
    "deepLinkUrl": "https://creatiq.example.com/lti/deep-link",
    "loginUrl": "https://creatiq.example.com/lti/login"
  }
}

Step 2: Register Creatiq as an External Tool in the LMS

In your LMS admin panel, create a new LTI 1.3 tool with the following values:

LMS FieldValue
Tool URL / Launch URLhttps://creatiq.example.com/lti/launch
Login Initiation URLhttps://creatiq.example.com/lti/login
Public Keyset URL (JWKS)https://creatiq.example.com/lti/jwks
Redirect URIhttps://creatiq.example.com/lti/launch
Deep Linking URLhttps://creatiq.example.com/lti/deep-link

After saving, the LMS will provide you with:

  • Issuer URL (e.g., https://lms.example.com)
  • Client ID
  • OIDC Authentication URL
  • OAuth 2.0 Token URL
  • Platform JWKS URL
  • Deployment ID (optional)

Step 3: Register the LMS Platform in Creatiq

Send these values to the Creatiq platform registration endpoint:

POST /lti/platforms
Authorization: Bearer <admin-token>
Content-Type: application/json

{
  "issuer": "https://lms.example.com",
  "clientId": "abc-123-client-id",
  "name": "My LMS",
  "authLoginUrl": "https://lms.example.com/mod/lti/auth.php",
  "authTokenUrl": "https://lms.example.com/mod/lti/token.php",
  "keysetUrl": "https://lms.example.com/mod/lti/certs.php",
  "deploymentId": "1",
  "agsEndpoint": "https://lms.example.com/mod/lti/service.php",
  "nrpsEndpoint": "https://lms.example.com/mod/lti/service.php"
}

All fields are validated with the following constraints:

FieldTypeConstraints
issuerstringValid URL, max 500 characters
clientIdstring1-255 characters
namestring1-255 characters
authLoginUrlstringValid URL, max 500 characters
authTokenUrlstringValid URL, max 500 characters
keysetUrlstringValid URL, max 500 characters
deploymentIdstringOptional, max 255 characters
agsEndpointstringOptional, valid URL, max 500 characters
nrpsEndpointstringOptional, valid URL, max 500 characters

A successful response returns the registered platform with its generated UUID:

{
  "success": true,
  "data": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "issuer": "https://lms.example.com",
    "clientId": "abc-123-client-id",
    "name": "My LMS",
    "authLoginUrl": "https://lms.example.com/mod/lti/auth.php",
    "authTokenUrl": "https://lms.example.com/mod/lti/token.php",
    "keysetUrl": "https://lms.example.com/mod/lti/certs.php",
    "deploymentId": "1",
    "agsEndpoint": "https://lms.example.com/mod/lti/service.php",
    "nrpsEndpoint": "https://lms.example.com/mod/lti/service.php",
    "createdAt": "2026-03-25T10:00:00.000Z",
    "updatedAt": "2026-03-25T10:00:00.000Z"
  }
}

If a platform with the same issuer + clientId already exists, the registration is updated (upsert behavior).


4. Launch Flow

The LTI 1.3 launch follows the IMS Security Framework (OIDC third-party login):

LMS                          Creatiq                       Browser
 |                              |                             |
 |  1. User clicks link         |                             |
 |----------------------------->|                             |
 |  2. OIDC login initiation    |                             |
 |     POST /lti/login          |                             |
 |----------------------------->|                             |
 |  3. Redirect to LMS auth     |                             |
 |<-----------------------------|                             |
 |  4. LMS authenticates user   |                             |
 |  5. POST /lti/launch         |                             |
 |     (with id_token JWT)      |                             |
 |----------------------------->|                             |
 |                              | 6. Validate id_token        |
 |                              |    - Decode JWT             |
 |                              |    - Match issuer+clientId  |
 |                              |    - Validate nonce         |
 |                              | 7. Redirect user            |
 |                              |------- 302 redirect ------->|
 |                              |                             |

Validation Steps (Step 6)

  1. The id_token JWT is decoded (not yet signature-verified against the platform JWKS -- see note below).
  2. The iss (issuer) and aud (client ID) claims are matched against registered platforms.
  3. If a nonce claim is present, it is validated and consumed (single-use, 10-minute expiry).
  4. If the platform is not registered, the launch is rejected with 401 Unregistered platform.

Redirect Logic (Step 7)

After successful validation, the user is redirected based on claims in the token:

PriorityClaimRedirect Target
1target_link_uriDirectly to the specified URL
2resource_link.id/workspace?lti=true&resource=<resourceId>
3(none)/workspace?lti=true

Launch Token Claims

The LMS sends a JWT id_token containing standard LTI 1.3 claims:

ClaimDescription
issIssuer (LMS platform URL)
subSubject (user ID in the LMS)
audAudience (Creatiq client ID)
nonceOne-time nonce for replay protection
https://purl.imsglobal.org/spec/lti/claim/message_typeLtiResourceLinkRequest
https://purl.imsglobal.org/spec/lti/claim/version1.3.0
https://purl.imsglobal.org/spec/lti/claim/rolesUser roles array
https://purl.imsglobal.org/spec/lti/claim/target_link_uriTarget content URL
https://purl.imsglobal.org/spec/lti/claim/resource_linkResource link object (id, title)
https://purl.imsglobal.org/spec/lti/claim/contextCourse context (id, label, title)

5. Deep Linking

Deep Linking allows instructors to select Creatiq H5P content from within the LMS course editor and embed it as a link.

Flow

  1. The LMS sends a LtiDeepLinkingRequest launch to Creatiq.
  2. Creatiq presents a content picker to the instructor.
  3. The instructor selects one or more H5P content items.
  4. Creatiq creates a signed Deep Linking Response JWT and returns it to the LMS.
POST /lti/deep-link
Authorization: Bearer <user-token>
Content-Type: application/json

{
  "platformId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "contents": [
    {
      "type": "ltiResourceLink",
      "title": "Cell Biology Quiz",
      "url": "https://creatiq.example.com/h5p/play/content-123",
      "contentId": "content-123"
    }
  ]
}

Validation constraints:

FieldConstraints
platformIdValid UUID
contentsArray of 1-50 items
contents[].typeNon-empty string
contents[].title1-500 characters
contents[].urlValid URL
contents[].contentIdNon-empty string

The response contains a signed JWT:

{
  "success": true,
  "data": {
    "jwt": "eyJhbGciOiJSUzI1NiIsInR5cCI6..."
  }
}

JWT Payload Structure

The Deep Linking Response JWT contains:

{
  "iss": "https://creatiq.example.com",
  "aud": "https://lms.example.com",
  "nonce": "<random-uuid>",
  "https://purl.imsglobal.org/spec/lti-dl/claim/content_items": [
    {
      "type": "ltiResourceLink",
      "title": "Cell Biology Quiz",
      "url": "https://creatiq.example.com/h5p/play/content-123",
      "custom": {
        "contentId": "content-123"
      }
    }
  ],
  "https://purl.imsglobal.org/spec/lti-dl/claim/msg": "Content selected successfully"
}

The JWT is signed with RS256 using Creatiq's RSA key pair (2048-bit). The LMS verifies it against the Creatiq JWKS endpoint (/lti/jwks). The token expires after 5 minutes.


6. Grade Passback (AGS)

Assignment and Grade Services allow Creatiq to push H5P content scores back to the LMS gradebook. This requires the lti-ags feature flag.

Prerequisites

  • The registered platform must have an agsEndpoint configured.
  • The LMS must grant the following OAuth 2.0 scopes:
    • https://purl.imsglobal.org/spec/lti-ags/scope/lineitem (read/write line items)
    • https://purl.imsglobal.org/spec/lti-ags/scope/score (write scores)
    • https://purl.imsglobal.org/spec/lti-ags/scope/result.readonly (read results)

Authentication

AGS requests use the OAuth 2.0 Client Credentials flow:

  1. Creatiq creates a JWT client assertion signed with its RSA private key.
  2. The assertion is sent to the platform's token endpoint.
  3. The platform returns an access token (cached with a 60-second expiry buffer).

Line Items

A line item represents a column in the LMS gradebook.

List line items:

GET /lti/ags/lineitems?platformId=<uuid>&contextId=<course-id>
Authorization: Bearer <admin-token>

Create a line item:

POST /lti/ags/lineitems
Authorization: Bearer <admin-token>
Content-Type: application/json

{
  "platformId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "contextId": "course-101",
  "label": "Cell Biology Quiz",
  "scoreMaximum": 100,
  "resourceId": "content-123",
  "tag": "quiz"
}

Publishing Scores

To send a score to the LMS gradebook:

POST /lti/ags/scores
Authorization: Bearer <admin-token>
Content-Type: application/json

{
  "platformId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "lineItemUrl": "https://lms.example.com/mod/lti/service.php/lineitems/42",
  "userId": "student-456",
  "scoreGiven": 85,
  "scoreMaximum": 100,
  "comment": "Good work on the quiz!"
}

Creatiq automatically sets activityProgress to Completed and gradingProgress to FullyGraded when publishing scores.

Automatic Score Triggers

Creatiq listens for xAPI statements with the following verbs and can trigger automatic AGS score publishing:

  • http://adlnet.gov/expapi/verbs/completed
  • http://adlnet.gov/expapi/verbs/passed
  • http://adlnet.gov/expapi/verbs/failed

Score Object Structure

FieldTypeDescription
userIdstringLearner identifier in the LMS
scoreGivennumberThe score earned (min: 0)
scoreMaximumnumberMaximum possible score (positive)
commentstringOptional comment (max 1000 chars)
activityProgressenumInitialized, Started, InProgress, Submitted, Completed
gradingProgressenumFullyGraded, Pending, PendingManual, Failed, NotReady
timestampISO 8601Time of the score submission

7. Roster Sync (NRPS)

Names and Role Provisioning Services allow Creatiq to retrieve the course membership list from the LMS. This requires the lti-nrps feature flag.

Prerequisites

  • The registered platform must have an nrpsEndpoint configured.
  • The LMS must grant the scope: https://purl.imsglobal.org/spec/lti-nrps/scope/contextmembership.readonly

Fetching Members

GET /lti/nrps/members?platformId=<uuid>&contextId=<course-id>
Authorization: Bearer <admin-token>

Response:

{
  "success": true,
  "data": {
    "id": "https://lms.example.com/mod/lti/service.php/memberships",
    "context": {
      "id": "course-101"
    },
    "members": [
      {
        "userId": "user-1",
        "roles": ["instructor"],
        "name": "Jane Smith",
        "email": "jane@example.com",
        "status": "Active"
      },
      {
        "userId": "user-2",
        "roles": ["learner"],
        "name": "John Doe",
        "email": "john@example.com",
        "status": "Active"
      }
    ]
  }
}

Role Mapping

LTI roles from the LMS are mapped to Creatiq roles as follows:

LTI Role (contains)Creatiq Role
Instructor, TeachingAssistantinstructor
Administratoradmin
Learner, Studentlearner
(other)other

Pagination

NRPS supports paginated responses. Creatiq automatically follows Link header rel="next" URLs to retrieve all members, up to a maximum of 50 pages per request.


8. Endpoint Reference

All LTI endpoints are mounted under the /lti prefix.

Public Endpoints (No Auth)

MethodPathDescription
POST/lti/launchOIDC launch callback (receives id_token)
GET/lti/jwksPublic JWKS endpoint for signature verification

Authenticated Endpoints (Premium Feature)

MethodPathFeature FlagDescription
GET/lti/configlti-integrationGet tool configuration URLs
POST/lti/platformslti-integrationRegister an LMS platform
POST/lti/deep-linklti-integrationCreate deep linking response JWT
GET/lti/ags/lineitemslti-agsList gradebook line items
POST/lti/ags/lineitemslti-agsCreate a gradebook line item
POST/lti/ags/scoreslti-agsPublish a score to the gradebook
GET/lti/nrps/memberslti-nrpsFetch course membership roster

JWKS Endpoint

The /lti/jwks endpoint returns the public key in JWK format, used by the LMS to verify JWTs signed by Creatiq:

{
  "keys": [
    {
      "kty": "RSA",
      "n": "...",
      "e": "AQAB",
      "kid": "uuid-key-id",
      "use": "sig",
      "alg": "RS256"
    }
  ]
}

Creatiq auto-generates a 2048-bit RSA key pair on first use and persists it in the lti_keys database table.


9. Troubleshooting

Common Issues

SymptomCauseSolution
/lti/launch returns 503LTI_ENCRYPTION_KEY not setSet the environment variable and restart the server
Launch returns "Unregistered platform"Issuer/Client ID mismatchVerify the issuer and clientId match the LMS exactly
"Invalid or expired nonce"Launch took longer than 10 minutes, or nonce was replayedRetry the launch from the LMS
AGS returns "AGS endpoint not configured"Platform was registered without agsEndpointRe-register the platform with the correct endpoint
NRPS returns "NRPS endpoint not configured"Platform was registered without nrpsEndpointRe-register the platform with the correct endpoint
Token request failed (AGS/NRPS)Platform rejected the client assertionVerify the LMS has granted the required OAuth scopes
Deep link response rejected by LMSKey mismatch or token expiredEnsure the LMS is fetching keys from /lti/jwks; deep link tokens expire after 5 minutes
Feature not available (403)Feature flag not enabledEnable lti-integration, lti-ags, or lti-nrps for your tenant

Verifying the Integration

  1. Check LTI status: GET /lti/config should return "enabled": true.
  2. Check JWKS: GET /lti/jwks should return a valid JWK with alg: RS256.
  3. Test launch: Initiate a launch from the LMS and confirm you are redirected to Creatiq.
  4. Test AGS: Create a line item and publish a test score; verify it appears in the LMS gradebook.
  5. Test NRPS: Fetch members and verify the roster matches the LMS course enrollment.

Database Tables

The LTI integration uses three database tables (auto-created on startup):

TablePurpose
lti_platformsRegistered LMS platforms (issuer, client ID, endpoints)
lti_keysRSA key pairs for JWT signing
lti_noncesOne-time nonces for launch replay protection

Expired nonces are cleaned up automatically via the cleanupExpiredNonces() service method.

Back to docsdocs/product/integration/lti-integration.md