> ## Documentation Index
> Fetch the complete documentation index at: https://docs.timeback.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Question loop

> Fetch questions and submit answers during a lesson session

Once you have a `LessonSession` from [`lessons.start()`](/beta/build-on-timeback/sdk/managed-lessons/lesson-discovery#start-a-lesson), the question loop is how your app drives the lesson forward. Call `session.next()` to get a question, render it, then call `session.submit()` with the student's answer.

## The basic loop

```typescript theme={null}
let question = await session.next()

while (question) {
    // Render the question, collect an answer from the student
    const answer = await renderQuestion(question)

    const result = await session.submit({
        question: question.id,
        response: answer,
    })

    // result.score, result.correct, result.complete are available

    question = await session.next()
}

// No more questions -- complete the lesson
const completion = await session.complete()
```

## Fetch a question

`session.next()` returns the next `LessonQuestion`, or `null` when there are no more questions:

```typescript theme={null}
const question = await session.next()

if (!question) {
    // Lesson is complete, call session.complete()
}
```

Each normalized question includes an `id`; `content` and `content.rawXml` are optional in the contract. Check for XML before rendering and handle unsupported or missing content in your UI. Your app supplies a QTI renderer.

<Info>
  See the [reference](/beta/build-on-timeback/sdk/managed-lessons/reference#lessonquestion) for the full type.
</Info>

<Warning>
  Select a renderer that supports the item interaction and response format. The managed-session `submit()` accepts a string and the server sends it as `responses.RESPONSE`; it does not expose every multi-response QTI contract. Use the returned grading result for feedback.
</Warning>

## Submit an answer

After the student answers, submit their response:

```typescript theme={null}
const result = await session.submit({
    question: question.id,
    response: selectedAnswer,
})
```

The result tells you whether the answer was `correct`, the updated `score`, and whether the lesson is now `complete`. After each submission, `score` updates and a complete result stops subsequent `next()` calls. The public `finalized` property updates only after `complete()`.

<Info>
  See the [reference](/beta/build-on-timeback/sdk/managed-lessons/reference#lessonsubmitresult) for full parameter and return type documentation.
</Info>

```typescript theme={null}
const result = await session.submit({ question: question.id, response: 'A' })
console.log(result.correct) // Whether the answer was correct
console.log(session.score) // Updated cumulative score
console.log(result.complete) // Whether the answer ended the question loop
```

## Adaptive vs linear delivery

The SDK handles two delivery modes transparently. Your code uses the same `next()` / `submit()` loop regardless of mode.

<Note>
  You do not need to detect which mode is active. The `LessonSession` handles it based on the
  `lessonType` set during
  [`lessons.start()`](/beta/build-on-timeback/sdk/managed-lessons/lesson-discovery#start-a-lesson).
</Note>

### Adaptive (`powerpath-100`)

Each `next()` call hits the server, which asks PowerPath for the next question based on the student's performance so far. Questions are served one at a time, and difficulty adapts.

### Linear (`quiz`, `test-out`, etc.)

On the first `next()` call, the SDK fetches **all** questions at once and buffers them locally. Subsequent `next()` calls return from the local buffer without a network round trip. Already-answered questions are skipped automatically.

## Track progress during the loop

The [session properties](/beta/build-on-timeback/sdk/managed-lessons/reference#lesson-session) update in real time as the student progresses. Use the returned `result.complete` and `session.score` to render progress. These are mutable object properties; copy returned values into your framework state when each request resolves. For linear lessons, submit returns `correct: false` and `score: 0` before finalization; do not show that placeholder as a scored wrong answer.

## Next steps

<CardGroup cols={2}>
  <Card title="Completion" icon="flag-checkered" href="/beta/build-on-timeback/sdk/managed-lessons/completion">
    Finalize scoring and interpret results
  </Card>

  <Card title="Reference" icon="code" href="/beta/build-on-timeback/sdk/managed-lessons/reference">
    Parameters, properties, methods, and return types
  </Card>
</CardGroup>
