Skip to main content

Overview

The @timeback/qti package provides a client for the QTI (Question and Test Interoperability) API, enabling:
  • Assessment Items: Query and manage question items
  • Assessment Tests: Query tests with nested structure
  • Stimuli: Query shared content for questions
  • Lessons: Submit and retrieve lesson feedback
  • Validation: Validate QTI XML content

Installation

npm install @timeback/qti

Quick Start

import { QtiClient } from '@timeback/qti'

const client = new QtiClient({
	env: 'staging',
	auth: {
		clientId: process.env.QTI_CLIENT_ID!,
		clientSecret: process.env.QTI_CLIENT_SECRET!,
	},
})

const { items, total, page, pages } = await client.assessmentItems.list()
const item = await client.assessmentItems.get('item-123')

Assessment Items

List & Get Items

client.assessmentItems.list()
client.assessmentItems.list({ page: 2, limit: 50, sort: 'title', order: 'asc' })
client.assessmentItems.get(itemId)
client.assessmentItems.stream()
client.assessmentItems.stream({ max: 500 }).toArray()
MethodReturnsDescription
list(){ items, total, page, pages }List with pagination metadata
get()AssessmentItemGet item by ID
stream()AsyncIterable<Item>Memory-efficient streaming
.toArray()Item[]Collect streamed items

Create, Update, Upsert & Delete

client.assessmentItems.create({ identifier, title, ...content })
client.assessmentItems.update(itemId, { title, ...content })
client.assessmentItems.upsert(itemId, { title, ...content })
client.assessmentItems.delete(itemId)
client.assessmentItems.processResponse(itemId, { response })

Assessment Tests

client.assessmentTests.list()
client.assessmentTests.get(testId)
client.assessmentTests.stream()
client.assessmentTests.create({ identifier, title, ...content })
client.assessmentTests.update(testId, { title, ...content })
client.assessmentTests.upsert(testId, { title, ...content })
client.assessmentTests.delete(testId)
client.assessmentTests.updateMetadata(testId, metadata)
client.assessmentTests.getQuestions(testId)

Test Parts

Assessment tests contain test parts, which contain sections:
client.assessmentTests.testParts(testId).list()
client.assessmentTests.testParts(testId).get(testPartId)
client.assessmentTests.testParts(testId).create({ identifier, ...content })
client.assessmentTests.testParts(testId).update(testPartId, { ...content })
client.assessmentTests.testParts(testId).delete(testPartId)

Sections

Sections live within a test part:
client.assessmentTests.testParts(testId).sections(testPartId).list()
client.assessmentTests.testParts(testId).sections(testPartId).get(sectionId)
client.assessmentTests.testParts(testId).sections(testPartId).create({ identifier, ...content })
client.assessmentTests.testParts(testId).sections(testPartId).update(sectionId, { ...content })
client.assessmentTests.testParts(testId).sections(testPartId).delete(sectionId)

Section Items

Manage items within a section:
client.assessmentTests.testParts(testId).sections(testPartId).items(sectionId).add(itemRef)
client.assessmentTests.testParts(testId).sections(testPartId).items(sectionId).remove(itemIdentifier)
client.assessmentTests.testParts(testId).sections(testPartId).items(sectionId).reorder(orderInput)

Stimuli

Stimuli are shared content blocks referenced by multiple items:
client.stimuli.list()
client.stimuli.get(stimulusId)
client.stimuli.stream()
client.stimuli.create({ identifier, title, ...content })
client.stimuli.update(stimulusId, { title, ...content })
client.stimuli.upsert(stimulusId, { title, ...content })
client.stimuli.delete(stimulusId)
upsert() is available on all three writable QTI resources.
  • update(id, data): strict (throws if the resource doesn’t exist)
  • upsert(id, data): loose (creates the resource if it doesn’t exist)

Lessons

Submit and retrieve lesson feedback:
client.lesson.submitLesson({ lessonId, studentId, ...feedbackData })
client.lesson.getLesson(lessonId)
client.lesson.submitQuestion({ questionId, studentId, ...feedbackData })

Validation

Validate QTI XML content:
client.validate.validate({ schema: 'item', xml: '<qti-assessment-item>...</qti-assessment-item>' })
client.validate.validate({ schema: 'test', xml: '<qti-assessment-test>...</qti-assessment-test>' })
client.validate.validate({ schema: 'stimulus', xml: '<qti-stimulus>...</qti-stimulus>' })
client.validate.batch({
	xml: ['<qti-assessment-item>...</qti-assessment-item>', '...'],
	schema: 'item',
	entityIds: ['item-1', 'item-2'],
})
SchemaDescription
itemQTI 3.0 assessment item
testQTI 3.0 assessment test
stimulusQTI 3.0 stimulus
Returns { valid: boolean, errors?: string[] }

Item Types

QTI supports various interaction types:
TypeDescription
choiceInteractionMultiple choice (single or multiple select)
textEntryInteractionText input
extendedTextInteractionLong text/essay
inlineChoiceInteractionDropdown select
orderInteractionOrdering/ranking
matchInteractionMatching pairs
gapMatchInteractionFill in the blank
hotspotInteractionImage hotspots

Next Steps

PowerPath

Adaptive assessments

OneRoster

Link assessments to gradebook

Types

QTI type definitions