Download OpenAPI specification:
API specification for Pulse LMS..
This API definition is intended to to be a good starting point for describing your API in OpenAPI/Swagger format.
Login with email and password.
| email required | string <email> |
| password required | string <password> |
{- "email": "user@example.com",
- "password": "pa$$word"
}{- "user": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "email": "user@example.com",
- "name": "string",
- "role": "user",
- "levelPreference": "A1",
- "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z"
}, - "tokens": {
- "accessToken": "string",
- "refreshToken": "string",
- "expiresIn": 0
}
}Exchange a refresh token for new access and refresh tokens.
| refreshToken required | string |
{- "refreshToken": "string"
}{- "accessToken": "string",
- "refreshToken": "string",
- "expiresIn": 0
}Send a password reset email with a reset link/token.
| email required | string <email> |
{- "email": "user@example.com"
}{- "title": "string",
- "status": 400,
- "detail": "string",
- "instance": "string"
}Confirm password reset using a token from email.
| token required | string |
| newPassword required | string <password> >= 8 characters |
{- "token": "string",
- "newPassword": "pa$$word"
}{- "title": "string",
- "status": 400,
- "detail": "string",
- "instance": "string"
}Start a passwordless login via magic link or email OTP.
| email required | string <email> |
| type required | string Enum: "magic_link" "otp" |
| redirectUrl | string <uri> Where the magic link should redirect (handled by frontend). |
{- "email": "user@example.com",
- "type": "magic_link",
}{- "title": "string",
- "status": 400,
- "detail": "string",
- "instance": "string"
}Verify email OTP and return tokens. Magic links are handled by redirect to frontend which exchanges token.
| email required | string <email> |
| otp required | string [ 4 .. 12 ] characters |
{- "email": "user@example.com",
- "otp": "string"
}{- "user": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "email": "user@example.com",
- "name": "string",
- "role": "user",
- "levelPreference": "A1",
- "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z"
}, - "tokens": {
- "accessToken": "string",
- "refreshToken": "string",
- "expiresIn": 0
}
}List vocabulary categories filtered by level/access.
| level | string (Level) Enum: "A1" "A2" "B1" "B2" "C1" "C2" Example: level=A1 CEFR proficiency level. |
| groupId | string <uuid> |
| access | string (AccessType) Enum: "free" "paid" Example: access=free Access classification for content. |
| isHighFrequency | boolean |
[- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "slug": "daily-conversation",
- "name": "Daily Conversation",
- "description": "string",
- "groupId": "eb54e96e-21b8-4f54-9cd4-80fccbd06f55",
- "level": "A1",
- "access": "free",
- "isHighFrequency": false,
- "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z"
}
]List words filtered by category, level, frequency, and search.
| categoryId | string <uuid> |
| level | string (Level) Enum: "A1" "A2" "B1" "B2" "C1" "C2" Example: level=A1 CEFR proficiency level. |
| q | string Full-text search query. |
| frequencyMin | integer >= 1 |
| frequencyMax | integer >= 1 |
| page | integer >= 1 Default: 1 |
| pageSize | integer [ 1 .. 100 ] Default: 20 |
{- "items": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "term": "hei",
- "translation": "hello",
- "phonetics": "/hæɪ/",
- "level": "A1",
- "categoryIds": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "frequencyRank": 120,
- "exampleSentences": [
- "string"
], - "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z"
}
], - "page": 0,
- "pageSize": 0,
- "total": 0
}Get a single word by id.
| wordId required | string <uuid> |
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "term": "hei",
- "translation": "hello",
- "phonetics": "/hæɪ/",
- "level": "A1",
- "categoryIds": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "frequencyRank": 120,
- "exampleSentences": [
- "string"
], - "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z"
}List sentences filtered by category, level, and search.
| categoryId | string <uuid> |
| level | string (Level) Enum: "A1" "A2" "B1" "B2" "C1" "C2" Example: level=A1 CEFR proficiency level. |
| q | string Full-text search query. |
| page | integer >= 1 Default: 1 |
| pageSize | integer [ 1 .. 100 ] Default: 20 |
{- "items": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "text": "string",
- "translation": "string",
- "level": "A1",
- "categoryIds": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "relatedWordIds": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z"
}
], - "page": 0,
- "pageSize": 0,
- "total": 0
}Get a single sentence by id.
| sentenceId required | string <uuid> |
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "text": "string",
- "translation": "string",
- "level": "A1",
- "categoryIds": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "relatedWordIds": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z"
}| level | string (Level) Enum: "A1" "A2" "B1" "B2" "C1" "C2" Example: level=A1 CEFR proficiency level. |
| categoryId | string <uuid> |
| type | string Enum: "words" "sentences" "mixed" |
[- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "title": "string",
- "description": "string",
- "type": "words",
- "level": "A1",
- "categoryIds": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "access": "free"
}
]{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "title": "string",
- "description": "string",
- "type": "words",
- "level": "A1",
- "categoryIds": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "access": "free"
}Start a quiz attempt and receive generated questions.
| quizId required | string <uuid> |
{- "attemptId": "ff88f33b-bb8d-4c28-947a-07ff3d628b10",
- "quizId": "5d9f833a-900c-4aa4-8bcb-33e2406f23e1",
- "questions": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "type": "multiple_choice",
- "prompt": "string",
- "options": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "text": "string",
- "explanation": "string"
}
], - "multipleCorrect": false,
- "sourceLanguage": "en",
- "targetLanguage": "no",
- "relatedWordId": "f508f075-c32c-4337-96fa-e83740939e23",
- "relatedSentenceId": "6955a985-4095-47e0-aa2b-a19c61be78ba"
}
]
}Submit answers for the ongoing quiz attempt.
| quizId required | string <uuid> |
| attemptId required | string <uuid> |
required | Array of objects or objects |
{- "attemptId": "ff88f33b-bb8d-4c28-947a-07ff3d628b10",
- "answers": [
- {
- "questionId": "ffa0420e-f70b-4e5b-99a0-434bff860467",
- "choiceIds": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "answerText": "string"
}
]
}{- "attemptId": "ff88f33b-bb8d-4c28-947a-07ff3d628b10",
- "quizId": "5d9f833a-900c-4aa4-8bcb-33e2406f23e1",
- "score": 100,
- "correctCount": 0,
- "wrongCount": 0,
- "breakdown": [
- {
- "questionId": "ffa0420e-f70b-4e5b-99a0-434bff860467",
- "correct": true
}
]
}{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "email": "user@example.com",
- "name": "string",
- "role": "user",
- "levelPreference": "A1",
- "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z"
}| name | string |
| levelPreference | string (Level) Enum: "A1" "A2" "B1" "B2" "C1" "C2" CEFR proficiency level. |
{- "name": "string",
- "levelPreference": "A1"
}{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "email": "user@example.com",
- "name": "string",
- "role": "user",
- "levelPreference": "A1",
- "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z"
}{- "level": "A1",
- "wordProgress": [
- {
- "wordId": "57f23edb-21e0-4045-93bd-dcd64d814bb0",
- "correctCount": 0,
- "wrongCount": 0,
- "mastery": 100,
- "lastReviewedAt": "2019-08-24T14:15:22Z"
}
], - "categoryProgress": [
- {
- "categoryId": "337f5e5d-288b-40d5-be14-901cc3acacc0",
- "completed": true,
- "progressPercent": 100
}
]
}Update progress for a specific word or category.
| wordId required | string <uuid> |
| result required | string Enum: "correct" "wrong" |
| categoryId | string <uuid> |
| progressPercent | number [ 0 .. 100 ] |
{- "wordId": "57f23edb-21e0-4045-93bd-dcd64d814bb0",
- "result": "correct",
- "categoryId": "337f5e5d-288b-40d5-be14-901cc3acacc0",
- "progressPercent": 100
}{- "title": "string",
- "status": 400,
- "detail": "string",
- "instance": "string"
}Subscribe or change plan.
| planId required | string <uuid> |
| cancelAtPeriodEnd | boolean |
{- "planId": "b3f60ba2-c1fd-4b3a-a23d-8e876e0ef75d",
- "cancelAtPeriodEnd": true
}{- "planId": "b3f60ba2-c1fd-4b3a-a23d-8e876e0ef75d",
- "status": "active",
- "currentPeriodEnd": "2019-08-24T14:15:22Z",
- "cancelAtPeriodEnd": true
}Admin-only. List users with filters.
| q | string |
| role | string Enum: "user" "admin" |
| status | string Enum: "active" "banned" "inactive" |
[- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "email": "user@example.com",
- "name": "string",
- "role": "user",
- "levelPreference": "A1",
- "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z"
}
]Admin-only. Create a user with password or send an invite magic link.
| email required | string <email> |
| name | string |
| role | string Default: "user" Enum: "user" "admin" |
| sendInvite | boolean Default: true If true, sends a magic-link invite instead of setting a password. |
| password | string <password> Optional if sendInvite=true. |
{- "email": "user@example.com",
- "name": "string",
- "role": "user",
- "sendInvite": true,
- "password": "pa$$word"
}{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "email": "user@example.com",
- "name": "string",
- "role": "user",
- "levelPreference": "A1",
- "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z"
}{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "email": "user@example.com",
- "name": "string",
- "role": "user",
- "levelPreference": "A1",
- "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z"
}| userId required | string <uuid> |
| role | string Enum: "user" "admin" |
| status | string Enum: "active" "banned" "inactive" |
{- "role": "user",
- "status": "active"
}{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "email": "user@example.com",
- "name": "string",
- "role": "user",
- "levelPreference": "A1",
- "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z"
}{- "title": "string",
- "status": 400,
- "detail": "string",
- "instance": "string"
}| slug required | string |
| name required | string |
| description | string |
| groupId | string <uuid> |
| level required | string (Level) Enum: "A1" "A2" "B1" "B2" "C1" "C2" CEFR proficiency level. |
| access required | string (AccessType) Enum: "free" "paid" Access classification for content. |
| isHighFrequency | boolean |
{- "slug": "string",
- "name": "string",
- "description": "string",
- "groupId": "eb54e96e-21b8-4f54-9cd4-80fccbd06f55",
- "level": "A1",
- "access": "free",
- "isHighFrequency": true
}{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "slug": "daily-conversation",
- "name": "Daily Conversation",
- "description": "string",
- "groupId": "eb54e96e-21b8-4f54-9cd4-80fccbd06f55",
- "level": "A1",
- "access": "free",
- "isHighFrequency": false,
- "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z"
}| categoryId required | string <uuid> |
| slug | string |
| name | string |
| description | string |
| groupId | string <uuid> |
| level | string (Level) Enum: "A1" "A2" "B1" "B2" "C1" "C2" CEFR proficiency level. |
| access | string (AccessType) Enum: "free" "paid" Access classification for content. |
| isHighFrequency | boolean |
{- "slug": "string",
- "name": "string",
- "description": "string",
- "groupId": "eb54e96e-21b8-4f54-9cd4-80fccbd06f55",
- "level": "A1",
- "access": "free",
- "isHighFrequency": true
}{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "slug": "daily-conversation",
- "name": "Daily Conversation",
- "description": "string",
- "groupId": "eb54e96e-21b8-4f54-9cd4-80fccbd06f55",
- "level": "A1",
- "access": "free",
- "isHighFrequency": false,
- "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z"
}{- "title": "string",
- "status": 400,
- "detail": "string",
- "instance": "string"
}| term required | string |
| translation | string |
| phonetics | string |
| level required | string (Level) Enum: "A1" "A2" "B1" "B2" "C1" "C2" CEFR proficiency level. |
| categoryIds | Array of strings <uuid> [ items <uuid > ] |
| frequencyRank | integer |
{- "term": "string",
- "translation": "string",
- "phonetics": "string",
- "level": "A1",
- "categoryIds": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "frequencyRank": 0
}{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "term": "hei",
- "translation": "hello",
- "phonetics": "/hæɪ/",
- "level": "A1",
- "categoryIds": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "frequencyRank": 120,
- "exampleSentences": [
- "string"
], - "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z"
}| wordId required | string <uuid> |
| term | string |
| translation | string |
| phonetics | string |
| level | string (Level) Enum: "A1" "A2" "B1" "B2" "C1" "C2" CEFR proficiency level. |
| categoryIds | Array of strings <uuid> [ items <uuid > ] |
| frequencyRank | integer |
{- "term": "string",
- "translation": "string",
- "phonetics": "string",
- "level": "A1",
- "categoryIds": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "frequencyRank": 0
}{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "term": "hei",
- "translation": "hello",
- "phonetics": "/hæɪ/",
- "level": "A1",
- "categoryIds": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "frequencyRank": 120,
- "exampleSentences": [
- "string"
], - "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z"
}{- "title": "string",
- "status": 400,
- "detail": "string",
- "instance": "string"
}| text required | string |
| translation | string |
| level required | string (Level) Enum: "A1" "A2" "B1" "B2" "C1" "C2" CEFR proficiency level. |
| categoryIds | Array of strings <uuid> [ items <uuid > ] |
{- "text": "string",
- "translation": "string",
- "level": "A1",
- "categoryIds": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
]
}{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "text": "string",
- "translation": "string",
- "level": "A1",
- "categoryIds": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "relatedWordIds": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z"
}| sentenceId required | string <uuid> |
| text | string |
| translation | string |
| level | string (Level) Enum: "A1" "A2" "B1" "B2" "C1" "C2" CEFR proficiency level. |
| categoryIds | Array of strings <uuid> [ items <uuid > ] |
{- "text": "string",
- "translation": "string",
- "level": "A1",
- "categoryIds": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
]
}{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "text": "string",
- "translation": "string",
- "level": "A1",
- "categoryIds": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "relatedWordIds": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z"
}{- "title": "string",
- "status": 400,
- "detail": "string",
- "instance": "string"
}| id required | string <uuid> |
| title required | string |
| description | string |
| type required | string Enum: "words" "sentences" "mixed" |
| level required | string (Level) Enum: "A1" "A2" "B1" "B2" "C1" "C2" CEFR proficiency level. |
| categoryIds | Array of strings <uuid> [ items <uuid > ] |
| access | string (AccessType) Enum: "free" "paid" Access classification for content. |
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "title": "string",
- "description": "string",
- "type": "words",
- "level": "A1",
- "categoryIds": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "access": "free"
}{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "title": "string",
- "description": "string",
- "type": "words",
- "level": "A1",
- "categoryIds": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "access": "free"
}| quizId required | string <uuid> |
| id required | string <uuid> |
| title required | string |
| description | string |
| type required | string Enum: "words" "sentences" "mixed" |
| level required | string (Level) Enum: "A1" "A2" "B1" "B2" "C1" "C2" CEFR proficiency level. |
| categoryIds | Array of strings <uuid> [ items <uuid > ] |
| access | string (AccessType) Enum: "free" "paid" Access classification for content. |
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "title": "string",
- "description": "string",
- "type": "words",
- "level": "A1",
- "categoryIds": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "access": "free"
}{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "title": "string",
- "description": "string",
- "type": "words",
- "level": "A1",
- "categoryIds": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "access": "free"
}{- "title": "string",
- "status": 400,
- "detail": "string",
- "instance": "string"
}[- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "type": "multiple_choice",
- "prompt": "string",
- "options": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "text": "string",
- "explanation": "string"
}
], - "multipleCorrect": false,
- "sourceLanguage": "en",
- "targetLanguage": "no",
- "relatedWordId": "f508f075-c32c-4337-96fa-e83740939e23",
- "relatedSentenceId": "6955a985-4095-47e0-aa2b-a19c61be78ba"
}
]| quizId required | string <uuid> |
required | Array of objects >= 2 items Provide options; mark one or more as correct with isCorrect. |
| multipleCorrect | boolean |
{- "options": [
- {
- "text": "string",
- "isCorrect": true
}, - {
- "text": "string",
- "isCorrect": true
}
], - "multipleCorrect": true
}{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "type": "multiple_choice",
- "prompt": "string",
- "options": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "text": "string",
- "explanation": "string"
}
], - "multipleCorrect": false,
- "sourceLanguage": "en",
- "targetLanguage": "no",
- "relatedWordId": "f508f075-c32c-4337-96fa-e83740939e23",
- "relatedSentenceId": "6955a985-4095-47e0-aa2b-a19c61be78ba"
}| quizId required | string <uuid> |
| questionId required | string <uuid> |
required | Array of objects >= 2 items Provide options; mark one or more as correct with isCorrect. |
| multipleCorrect | boolean |
{- "options": [
- {
- "text": "string",
- "isCorrect": true
}, - {
- "text": "string",
- "isCorrect": true
}
], - "multipleCorrect": true
}{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "type": "multiple_choice",
- "prompt": "string",
- "options": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "text": "string",
- "explanation": "string"
}
], - "multipleCorrect": false,
- "sourceLanguage": "en",
- "targetLanguage": "no",
- "relatedWordId": "f508f075-c32c-4337-96fa-e83740939e23",
- "relatedSentenceId": "6955a985-4095-47e0-aa2b-a19c61be78ba"
}| slug required | string |
| name required | string |
| description | string |
| sortOrder | integer |
{- "slug": "string",
- "name": "string",
- "description": "string",
- "sortOrder": 0
}{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "slug": "string",
- "name": "string",
- "description": "string",
- "sortOrder": 0
}| groupId required | string <uuid> |
| slug | string |
| name | string |
| description | string |
| sortOrder | integer |
{- "slug": "string",
- "name": "string",
- "description": "string",
- "sortOrder": 0
}{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "slug": "string",
- "name": "string",
- "description": "string",
- "sortOrder": 0
}