Ressources
Games over the Content API

Games over the Content API

Create, build, revise, and manage classroom games from an external system. Same endpoints as the admin UI uses, and the same credit cost.

Games are reachable from the Content API with the same operations the admin UI has, and at the same credit cost. The API routes through the very services the UI calls, so nothing about access, validation, or pricing differs between the two.

All routes live under /v1/content/classrooms/{classroomId}/games and take a tf_content_ key.

Resource operations

MethodPathSuccess response
POST/games201 with the created game
GET/games200 with a page of games
GET/games/{id}200 with the game, including its built HTML
PATCH/games/{id}200 with the updated game
DELETE/games/{id}200 with the deleted game
POST/games/{id}/versions/{version}/restore200 with the restored game

POST /games honours the Idempotency-Key header, like the other content resources. A retried create with the same key returns the game made the first time rather than a second one.

Restoring a version runs no model and charges nothing. It makes the chosen version the newest rather than overwriting history, so a restore is itself reversible.

Reading a game returns its HTML

GET /games/{id} includes a content field holding the built game as a complete HTML document. A game is a self-contained page, so this is the whole thing, and it can be large.

GET /games does not include it. List responses carry metadata only, so paging through a classroom stays cheap. Fetch the content for the one game you actually need.

The contentKey field on a game is TutorFlow's internal storage reference. Treat it as opaque and read the game through the API rather than trying to address that key yourself.

Generation

Building a game is three steps, and each is its own call. They are separate because the plan is cheap and the build is not: reading a plan and rejecting it should not cost what building it costs.

MethodPathCredits
POST/games/{id}/brief1
POST/games/{id}/build12
POST/games/{id}/revise10

These are the same prices the admin UI pays, drawn from the organization's AI Credit balance. Check the balance with GET /v1/content/credits before a batch.

POST /games/{id}/brief accepts an optional referenceMarkdown body field to ground the plan in your own material. POST /games/{id}/revise takes a feedback field describing the change in plain language, the same way the chat panel in the editor does.

These three stream

The generation routes respond with text/event-stream, not a JSON body. Read them as Server-Sent Events. The build completes when the stream ends.

Disconnecting aborts the work. If your client hangs up mid-build, the model call stops rather than running to completion unread. That also means a client timeout shorter than a build will cancel the build, so set timeouts with the build duration in mind rather than the default.

A typical run

  1. POST /games with a title, and keep the returned id.
  2. POST /games/{id}/brief with what learners should practise. Read the plan from the stream.
  3. Inspect the plan. If it is wrong, PATCH the game or ask for another brief. This is the cheap point to change your mind.
  4. POST /games/{id}/build. Wait for the stream to end.
  5. GET /games/{id} to read the built game and its version history.
  6. POST /games/{id}/revise with feedback if something needs changing.
  7. PATCH /games/{id} with visibility: "PUBLIC" when it is ready to share, and hand out its link.

What the build guarantees

Every generated version is checked twice before it is stored: an automated validation of the page, then a playthrough that opens the game and works the controls. A version that will not start, or that freezes partway, is rebuilt rather than returned.

Those checks confirm the game runs. They judge nothing about whether it suits a particular class, so an integration that publishes automatically is publishing something no person has played. See Games Overview for what the checks do and do not cover.