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

# Hosted LMS visual preview

> Render the real worker course player, execute safe preview-only steps, and share short-lived employer review links without creating learner progress.

Hosted LMS visual preview lets an authorized employer or agent inspect the real
worker course player without a local browser, a development server, or a worker
account. It uses the same isolated Preview session as the existing LMS preview
workflow.

<Warning>
  Hosted preview evidence is a simulated worker preview. It does not prove that
  a particular worker received an assignment, and it never writes learner
  progress, Native Forms attempts, Project To-dos, notifications, or completion
  records.
</Warning>

```text theme={null}
Base path: /api/public/v1/lms/preview
```

## Workflow

1. Create or restore a Preview session pinned to an exact draft revision or
   published course version.
2. Select the module, lesson, or supported item with the normal session
   `manage` operation.
3. Call `render` with the current `expectedStateRevision`.
4. Inspect the returned PNG, ARIA snapshot, diagnostics, and provenance
   manifest artifacts.
5. Use `step` only when you need to test one supported interaction.
6. Optionally mint an observe-only link for a signed-in employer organization
   member, then revoke it when review is complete.

## Endpoints

| Method | Path                                          | Purpose                                                                    |
| ------ | --------------------------------------------- | -------------------------------------------------------------------------- |
| `POST` | `/sessions/{sessionId}/render`                | Capture the session's current focus in desktop, mobile, or both viewports. |
| `POST` | `/sessions/{sessionId}/step`                  | Execute one closed preview-only action and return before/after evidence.   |
| `POST` | `/sessions/{sessionId}/links`                 | Mint a short-lived, observe-only employer review link.                     |
| `GET`  | `/sessions/{sessionId}/links`                 | List link records without recovering their secret URLs.                    |
| `GET`  | `/sessions/{sessionId}/links/{linkId}`        | Read one link's lifecycle status.                                          |
| `POST` | `/sessions/{sessionId}/links/{linkId}/revoke` | Revoke one review link.                                                    |
| `GET`  | `/sessions/{sessionId}/artifacts`             | List bounded Preview evidence records.                                     |
| `GET`  | `/artifacts/{artifactId}`                     | Read one ready artifact with a short-lived signed URL.                     |

The OpenAPI document also describes the existing session create, restore,
selection, answer, simulated-run, reset, and expiration operations.

## Render the current view

`POST /sessions/{sessionId}/render` requires `lms:write`, an
`Idempotency-Key`, and the current state revision:

```json theme={null}
{
  "expectedStateRevision": 7,
  "viewports": ["desktop", "mobile"],
  "moduleKey": "reconciliation",
  "lessonKey": "cutoff-testing"
}
```

The optional target fields are assertions. They do not navigate. Select the
target first, then render it. A mismatch fails closed instead of producing a
mislabeled screenshot.

The response contains:

* `evidenceClass: "SIMULATED_WORKER_PREVIEW"`;
* the exact state and render revisions;
* private PNG artifact records;
* an ARIA snapshot for semantic inspection;
* renderer diagnostics; and
* a provenance manifest binding every artifact to the session, target,
  viewport, revision, checksum, and byte size.

## Execute a safe step

`POST /sessions/{sessionId}/step` accepts a closed action vocabulary. It never
accepts CSS selectors, JavaScript, arbitrary URLs, coordinates, or free-form
browser instructions.

```json theme={null}
{
  "op": "complete_content",
  "lessonKey": "cutoff-testing",
  "expectedStateRevision": 7,
  "capture": "before_after",
  "viewport": "desktop"
}
```

Supported actions in this release are `open_lesson` and `complete_content`.
The receipt reports the canonical before and after state revisions and an
outcome of `APPLIED` or `ALREADY_SATISFIED`.

## Share an employer review link

`POST /sessions/{sessionId}/links` returns the URL exactly once. Treat it as a
short-lived secret. Its fragment token is exchanged once for an HttpOnly
cookie, and every read checks that the viewer is currently signed in as a
member of the Preview session's employer organization.

Links are observe-only. Opening one never changes the Preview session. Module
and lesson deep links are supported. Exact-question links currently fail with
`ITEM_LINK_UNAVAILABLE` rather than silently opening a broader view.

Later link reads return only metadata and lifecycle status:
`ACTIVE`, `CONSUMED`, `REVOKED`, or `EXPIRED`. They cannot recover the URL.

## Authorization and retry behavior

* Render, step, link creation, and link revocation require `lms:write` and a
  stable `Idempotency-Key`.
* Artifact and link reads require `lms:read`.
* Every operation enforces organization ownership of the Preview session.
* State-changing Preview operations use an expected revision and fail with
  `409` when the session changed.
* Renderer unavailability or capacity returns a retryable `503`. Reuse the
  same idempotency key after an uncertain response.
* Signed artifact URLs expire. Retrieve the artifact again when an authorized
  reviewer needs a fresh URL.

## SDK methods

`@opentrain-ai/sdk` 0.15.0 or later exposes the same contract through:

* `renderLmsPreviewHosted`;
* `stepLmsPreviewHosted`;
* `createLmsPreviewLink`;
* `getLmsPreviewLink`;
* `listLmsPreviewLinks`; and
* `revokeLmsPreviewLink`.

Use the machine-readable [OpenAPI document](https://app.opentrain.ai/api/public/v1/openapi.json)
for the complete request, response, and error schemas.
