Skip to main content
DocsAPI ReferenceLTI 1.3 API
Back to docs

LTI 1.3 API

Launch, JWKS, deep linking, AGS grades, NRPS roster

api
lti

LTI 1.3 API Reference

LTI 1.3 Advantage integration for Creatiq. Enables single-click content launch from any LMS, deep linking for content selection, Assignment and Grade Services (AGS) for gradebook sync, and Names and Role Provisioning Services (NRPS) for roster retrieval.

Base path: /lti


Endpoints

POST /lti/launch

Handle an LMS launch request (OIDC callback with id_token).

PropertyValue
AuthNone (public -- token is self-authenticating)
Feature gateNone (checked via ltiEnabled config flag)

Description

Receives the id_token JWT from the LMS after the OIDC login flow. Validates the token against registered platforms, checks nonce freshness, then redirects the user to the appropriate Creatiq workspace URL.

Redirect logic:

  1. If the token contains target_link_uri claim -- redirect there.
  2. If the token contains resource_link.id -- redirect to /workspace?lti=true&resource={id}.
  3. Otherwise -- redirect to /workspace?lti=true.

Request

Content-Type: application/x-www-form-urlencoded

FieldTypeRequiredDescription
id_tokenstringYesJWT issued by the LMS platform

Response

302 Redirect to workspace URL on success.

Errors

StatusErrorCondition
400Missing id_token parameterid_token not present in request body
401Unregistered platformToken issuer/clientId not found in registered platforms
401Invalid or expired nonceNonce already consumed or expired (600s TTL)
401Invalid token formatJWT cannot be decoded
503LTI integration is not configuredltiEnabled is false (missing env vars)

GET /lti/jwks

Public JWKS endpoint for LTI platforms to verify Creatiq's signatures.

PropertyValue
AuthNone (public)
Feature gateNone

Description

Returns the JSON Web Key Set containing Creatiq's RSA-256 public key. Platforms use this to verify deep-link response JWTs. Keys are auto-generated on first use (2048-bit RSA) and persisted in the lti_keys table.

Response

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

Errors

StatusErrorCondition
500Failed to get JWKSDatabase or key generation failure

GET /lti/config

Get LTI platform configuration URLs.

PropertyValue
AuthJWT Bearer token (authMiddleware)
Feature gatelti-integration

Description

Returns the URLs that an LMS administrator needs when registering Creatiq as an LTI tool.

Response

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

Errors

StatusErrorCondition
401UnauthorizedMissing or invalid JWT
403Feature not availablelti-integration feature not enabled for subscription tier

POST /lti/platforms

Register a new LTI platform.

PropertyValue
AuthJWT Bearer token (authMiddleware)
Feature gatelti-integration

Description

Registers an LMS platform for LTI 1.3 integration. Uses upsert logic -- if a platform with the same issuer + clientId already exists, it updates the record.

Request

{
  "issuer": "https://lms.example.com",
  "clientId": "creatiq-tool-12345",
  "name": "Example LMS",
  "authLoginUrl": "https://lms.example.com/auth/login",
  "authTokenUrl": "https://lms.example.com/auth/token",
  "keysetUrl": "https://lms.example.com/.well-known/jwks.json",
  "deploymentId": "deploy-001",
  "agsEndpoint": "https://lms.example.com/api/ags",
  "nrpsEndpoint": "https://lms.example.com/api/nrps"
}
FieldTypeRequiredConstraintsDescription
issuerstringYesURL, max 500Platform issuer URL
clientIdstringYes1--255 charsOAuth 2.0 client ID
namestringYes1--255 charsDisplay name
authLoginUrlstringYesURL, max 500OIDC login initiation URL
authTokenUrlstringYesURL, max 500OAuth 2.0 token endpoint
keysetUrlstringYesURL, max 500Platform's JWKS URL
deploymentIdstringNoMax 255LTI deployment ID
agsEndpointstringNoURL, max 500AGS service base URL
nrpsEndpointstringNoURL, max 500NRPS service base URL

Response (201 Created)

{
  "success": true,
  "data": {
    "id": "uuid",
    "issuer": "https://lms.example.com",
    "clientId": "creatiq-tool-12345",
    "name": "Example LMS",
    "authLoginUrl": "https://lms.example.com/auth/login",
    "authTokenUrl": "https://lms.example.com/auth/token",
    "keysetUrl": "https://lms.example.com/.well-known/jwks.json",
    "deploymentId": "deploy-001",
    "agsEndpoint": "https://lms.example.com/api/ags",
    "nrpsEndpoint": "https://lms.example.com/api/nrps",
    "createdAt": "2025-01-15T10:00:00.000Z",
    "updatedAt": "2025-01-15T10:00:00.000Z"
  }
}

Errors

StatusErrorCondition
400Validation error: ...Zod schema validation failure
401UnauthorizedMissing or invalid JWT
403Feature not availablelti-integration feature not enabled

POST /lti/deep-link

Create a deep linking response JWT for content selection.

PropertyValue
AuthJWT Bearer token (authMiddleware)
Feature gatelti-integration

Description

Generates a signed JWT that the LMS can use to register selected H5P content as LTI resource links. Each content item becomes an ltiResourceLink with a URL pointing to {appUrl}/h5p/play/{contentId}. The JWT is signed with RS256 using Creatiq's private key and expires in 5 minutes.

Request

{
  "platformId": "uuid-of-registered-platform",
  "contents": [
    {
      "type": "h5p",
      "title": "Interactive Quiz: Biology Chapter 3",
      "url": "https://app.creatiq.com/h5p/play/abc123",
      "contentId": "abc123"
    }
  ]
}
FieldTypeRequiredConstraintsDescription
platformIdstringYesUUIDRegistered platform ID
contentsarrayYes1--50 itemsContent items to link
contents[].typestringYesNon-emptyContent type identifier
contents[].titlestringYes1--500 charsDisplay title in LMS
contents[].urlstringYesURLContent URL
contents[].contentIdstringYesNon-emptyH5P content ID

Response

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

The JWT payload contains:

  • iss -- Creatiq app URL
  • aud -- Platform issuer
  • https://purl.imsglobal.org/spec/lti-dl/claim/content_items -- Array of ltiResourceLink items
  • https://purl.imsglobal.org/spec/lti-dl/claim/msg -- "Content selected successfully"

Errors

StatusErrorCondition
400Validation error: ...Schema validation failure
500Platform not foundplatformId does not match a registered platform

Assignment and Grade Services (AGS)

GET /lti/ags/lineitems

List line items (gradebook columns) for a platform context.

PropertyValue
AuthJWT Bearer token (authMiddleware)
Feature gatelti-ags

Description

Retrieves all line items from the LMS gradebook for a given context (course). Internally acquires an OAuth 2.0 access token from the platform using the lineitem scope.

Query Parameters

ParamTypeRequiredDescription
platformIdstringYes (UUID)Registered platform ID
contextIdstringYes (1--500)LMS course/context ID

Response

{
  "success": true,
  "data": [
    {
      "id": "https://lms.example.com/api/ags/lineitems/42",
      "label": "H5P Quiz Score",
      "scoreMaximum": 100,
      "resourceId": "abc123",
      "tag": "quiz",
      "startDateTime": "2025-01-01T00:00:00Z",
      "endDateTime": "2025-06-30T23:59:59Z"
    }
  ]
}

Errors

StatusErrorCondition
400Validation error: ...Invalid query params
500AGS endpoint not configured for platform: {id}Platform has no agsEndpoint
500Failed to list line items: {status}LMS returned an error

POST /lti/ags/lineitems

Create a line item in the LMS gradebook.

PropertyValue
AuthJWT Bearer token (authMiddleware)
Feature gatelti-ags

Request

{
  "platformId": "uuid",
  "contextId": "course-101",
  "label": "H5P Interactive Video Score",
  "scoreMaximum": 100,
  "resourceId": "content-abc123",
  "tag": "h5p-assessment"
}
FieldTypeRequiredConstraintsDescription
platformIdstringYesUUIDRegistered platform ID
contextIdstringYes1--500 charsLMS course/context ID
labelstringYes1--500 charsGradebook column name
scoreMaximumnumberYesPositiveMaximum possible score
resourceIdstringNoMax 500Associated resource ID
tagstringNoMax 255Category tag

Response (201 Created)

{
  "success": true,
  "data": {
    "id": "https://lms.example.com/api/ags/lineitems/43",
    "label": "H5P Interactive Video Score",
    "scoreMaximum": 100,
    "resourceId": "content-abc123",
    "tag": "h5p-assessment"
  }
}

Errors

StatusErrorCondition
400Validation error: ...Schema validation failure
500AGS endpoint not configured for platform: {id}No AGS endpoint
500Failed to create line item: {status}LMS returned an error

POST /lti/ags/scores

Publish a score to a specific line item.

PropertyValue
AuthJWT Bearer token (authMiddleware)
Feature gatelti-ags

Description

Publishes a learner's score to an LMS gradebook column. The score is submitted with activityProgress: "Completed" and gradingProgress: "FullyGraded". Internally acquires an OAuth 2.0 token with the score scope.

Request

{
  "platformId": "uuid",
  "lineItemUrl": "https://lms.example.com/api/ags/lineitems/42",
  "userId": "student-12345",
  "scoreGiven": 85,
  "scoreMaximum": 100,
  "comment": "Great work on the interactive quiz!"
}
FieldTypeRequiredConstraintsDescription
platformIdstringYesUUIDRegistered platform ID
lineItemUrlstringYesURL, max 1000Full URL of the line item
userIdstringYes1--500 charsLMS user identifier
scoreGivennumberYes>= 0Score achieved
scoreMaximumnumberYesPositiveMaximum possible score
commentstringNoMax 1000Instructor comment

Response

{
  "success": true,
  "message": "Score published"
}

Errors

StatusErrorCondition
400Validation error: ...Schema validation failure
500Failed to publish score: {status}LMS returned an error
500Token request failed with status {status}OAuth token acquisition failed

Names and Role Provisioning Services (NRPS)

GET /lti/nrps/members

Fetch the membership list (roster) from an LMS platform.

PropertyValue
AuthJWT Bearer token (authMiddleware)
Feature gatelti-nrps

Description

Retrieves all members of an LMS course context. Supports paginated responses -- follows Link header rel="next" up to 50 pages. LTI roles are mapped to simplified roles:

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

Query Parameters

ParamTypeRequiredDescription
platformIdstringYes (UUID)Registered platform ID
contextIdstringYes (1--500)LMS course/context ID

Response

{
  "success": true,
  "data": {
    "id": "https://lms.example.com/api/nrps/memberships",
    "context": {
      "id": "course-101"
    },
    "members": [
      {
        "userId": "user-001",
        "roles": ["instructor"],
        "name": "Jane Doe",
        "email": "jane@example.com",
        "status": "Active"
      },
      {
        "userId": "user-002",
        "roles": ["learner"],
        "name": "John Smith",
        "email": "john@example.com",
        "status": "Active"
      }
    ]
  }
}

Errors

StatusErrorCondition
400Validation error: ...Invalid query params
500NRPS endpoint not configured for platform: {id}Platform has no nrpsEndpoint
500Failed to fetch members: {status}LMS returned an error

OAuth 2.0 Token Flow

All AGS and NRPS requests require an OAuth 2.0 access token from the LMS. The token service handles this transparently:

  1. Check in-memory cache for a valid token (with 60-second buffer before expiry).
  2. If no cached token, create a client_credentials grant request:
    • client_assertion_type: urn:ietf:params:oauth:client-assertion-type:jwt-bearer
    • client_assertion: JWT signed with RS256 (iss/sub = clientId, aud = authTokenUrl, exp = 5 min)
    • scope: Required LTI scopes for the operation
  3. Cache the returned token for its expires_in duration.

LTI Scopes Used

ScopeUsed By
https://purl.imsglobal.org/spec/lti-ags/scope/lineitemList/create line items
https://purl.imsglobal.org/spec/lti-ags/scope/scorePublish scores
https://purl.imsglobal.org/spec/lti-ags/scope/result.readonlyRead results
https://purl.imsglobal.org/spec/lti-nrps/scope/contextmembership.readonlyFetch members

Database Tables

lti_platforms

ColumnTypeDescription
idUUID (PK)Auto-generated
issuerVARCHAR(500)Platform issuer URL
client_idVARCHAR(255)OAuth client ID
nameVARCHAR(255)Display name
auth_login_urlVARCHAR(500)OIDC login URL
auth_token_urlVARCHAR(500)Token endpoint
keyset_urlVARCHAR(500)JWKS URL
deployment_idVARCHAR(255)LTI deployment ID
ags_endpointVARCHAR(500)AGS service URL
nrps_endpointVARCHAR(500)NRPS service URL
created_atTIMESTAMPCreation time
updated_atTIMESTAMPLast update time

Unique constraint: (issuer, client_id).

lti_keys

ColumnTypeDescription
kidVARCHAR(64) (PK)Key ID
public_keyTEXTPEM-encoded RSA public key
private_keyTEXTPEM-encoded RSA private key
created_atTIMESTAMPCreation time

lti_nonces

ColumnTypeDescription
valueVARCHAR(255) (PK)Nonce string
platform_idUUID (FK)References lti_platforms.id
consumed_atTIMESTAMPWhen the nonce was used (null = unconsumed)
expires_atTIMESTAMPExpiry time (600 seconds after creation)

xAPI Integration

The AGS service listens for xAPI statements with score-trigger verbs (completed, passed, failed). When detected, these can trigger automatic grade passback to the LMS. This listener is initialized on service startup.

Back to docsdocs/product/api/lti.md