PlaycademyPlaycademy

QTI API

Question and test interoperability

Overview

QTI (Question & Test Interoperability) lets you create, deliver, and score digital assessments.

It's the standard format for questions and tests that work across different learning platforms.

Use QTI to build quizzes, tests, and interactive assessments that integrate with Timeback's progress tracking.

External Documentation

ResourceLink
Official API DocsQTI API Docs
Specification1EdTech QTI v3.0

Key Concepts

ConceptDescription
ItemA single question (multiple choice, fill-in-blank, etc.)
StimulusSupporting material for questions (articles, videos, images)
Assessment TestA collection of items that form a quiz or test
Assessment BankMultiple test variations for the same lesson (prevents memorization)

Common Use Cases

  • Create questions: Build multiple choice, true/false, and open-ended questions
  • Build assessments: Combine questions into quizzes and tests
  • Add supporting material: Include articles, videos, or images as context for questions
  • Embed in your app: Render QTI content using iframes

Essential Endpoints

EndpointPurpose
POST /itemsCreate a question
POST /stimuliCreate supporting material (article, video, image)
POST /assessment-testsCreate a test from multiple questions
GET /items/{id}Retrieve a question
GET /assessment-tests/{id}Retrieve a test

Examples

Create a Question

Request
curl -X POST $TIMEBACK_QTI_URL/assessment-items \  -H "Authorization: Bearer $ACCESS_TOKEN" \  -H "Content-Type: application/json" \  -d '{    "format": "xml",    "xml": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><qti-assessment-item xmlns=\"http://www.imsglobal.org/xsd/imsqtiasi_v3p0\" identifier=\"question-123\" title=\"Fraction Addition\" adaptive=\"false\" time-dependent=\"false\"><qti-response-declaration identifier=\"RESPONSE\" cardinality=\"single\" base-type=\"identifier\"><qti-correct-response><qti-value>B</qti-value></qti-correct-response></qti-response-declaration><qti-item-body><qti-choice-interaction response-identifier=\"RESPONSE\" shuffle=\"false\" max-choices=\"1\"><qti-prompt>What is 1/2 + 1/4?</qti-prompt><qti-simple-choice identifier=\"A\">1/6</qti-simple-choice><qti-simple-choice identifier=\"B\">3/4</qti-simple-choice><qti-simple-choice identifier=\"C\">2/6</qti-simple-choice></qti-choice-interaction></qti-item-body></qti-assessment-item>"  }'
const response = await fetch(`${TIMEBACK_QTI_URL}/assessment-items`, {    method: 'POST',    headers: {        Authorization: `Bearer ${accessToken}`,        'Content-Type': 'application/json',    },    body: JSON.stringify({        format: 'xml',        xml: '<?xml version="1.0" encoding="UTF-8"?><qti-assessment-item xmlns="http://www.imsglobal.org/xsd/imsqtiasi_v3p0" identifier="question-123" title="Fraction Addition" adaptive="false" time-dependent="false"><qti-response-declaration identifier="RESPONSE" cardinality="single" base-type="identifier"><qti-correct-response><qti-value>B</qti-value></qti-correct-response></qti-response-declaration><qti-item-body><qti-choice-interaction response-identifier="RESPONSE" shuffle="false" max-choices="1"><qti-prompt>What is 1/2 + 1/4?</qti-prompt><qti-simple-choice identifier="A">1/6</qti-simple-choice><qti-simple-choice identifier="B">3/4</qti-simple-choice><qti-simple-choice identifier="C">2/6</qti-simple-choice></qti-choice-interaction></qti-item-body></qti-assessment-item>',    }),})

Get Question Content

Request
curl $TIMEBACK_QTI_URL/assessment-items/question-123 \  -H "Authorization: Bearer $ACCESS_TOKEN"
const question = await fetch(`${TIMEBACK_QTI_URL}/assessment-items/question-123`, {    headers: {        Authorization: `Bearer ${accessToken}`,    },})const { identifier, title, qtiXml } = await question.json()

On this page