A simulation is an interactive model with controls. Learners change the controls and watch the result, so there is no score, no winning, and no losing. If you want something with a score, build a game instead. Every route is under /v1/content/classrooms/{classroomId}/simulations and takes a tf_content_ key.
Planning, building, revising, restoring, and sharing work the same way for games and simulations, and are described once in Generation: Brief, Build, Revise. This page covers what is specific to simulations. The full route list is in the API Reference.
The simulation object
Create, read, update, and restore return the same shape. content appears only on GET /simulations/{simulationId}.
| Field | Notes |
|---|---|
id | Use as {simulationId} on later calls. |
classroomId | The classroom the simulation belongs to. |
title, description | Display text. description may be null. |
visibility | PRIVATE or PUBLIC. A public simulation opens at its play link without an account. |
subject | Set by the brief, not by you: computer-science, ai-ml, finance, business, math, science, or other. other until a brief exists. |
representation | Set by the brief: 2d-canvas for a plain canvas, or 3d-three when the third dimension is part of the lesson. It decides the build price; see Pricing. |
slug | A short label TutorFlow assigns. It is not part of any link. |
metadata | An object you own. The keys in Metadata that shapes the plan feed the brief; other keys are stored untouched. |
brief | The plan the build reads. null until a brief is generated or written. See The brief. |
contentKey | Storage reference of the version being served. An opaque identifier, not a URL. null until the first build. |
contentVersion | The version being served. 0 until the first build, then incremented by every build, revision, tuning, and restore. |
buildHistory | One entry per version: version, contentKey (opaque), createdAt, source (build, revision, restore, or tuning), note with the revision feedback when there was one, and restoredFromVersion on a restore. |
thumbnail | Storage reference of a capture of the opening frame, or null. An opaque identifier, not a URL. |
content | The built simulation as one complete HTML document, or null before the first build. Only on GET /simulations/{simulationId}. |
createdAt, updatedAt | Timestamps. Sort the list by updatedAt to find recent changes. |
A tuning entry records an educator changing a control's range, step, or starting value in the TutorFlow editor. The page was edited in place rather than regenerated, so it cost no credits. No Content API call creates one.
The brief
The brief is the quickest way to see what a simulation computes without reading its HTML, and the place to catch a wrong model before paying for a build. A generated brief has these fields. Write your own with PATCH /simulations/{simulationId} and a brief object to skip the priced brief call.
| Field | Notes |
|---|---|
title, pitch, eyebrow | The title, one sentence for the learner, and a two-to-four-word label shown above the title. |
facts | Two to four label and value pairs about the model: its parts, its rule, its scale. |
status | A short footer line naming what kind of model is running. |
subject | One of the subject values above. |
model | What the simulation computes: the state it tracks and the rules that advance it. |
controls | One to five entries of label, kind (slider, toggle, choice, or number), range, effect, and section. |
observations | One to four things the learner watches to read the result. |
inquiry | Two to four questions the learner answers by moving the controls. |
Check model and controls before building. A simulation that computes the wrong thing is the failure this content type is most prone to, and the build checks do not verify the arithmetic.
Metadata that shapes the plan
All keys are optional. PATCH merges metadata: keys you send replace their old values, and keys you leave out stay.
| Key | Values | Notes |
|---|---|---|
topic | Free text | The principle the learner should work out. Falls back to title. |
audience | Free text | Who the simulation is for. |
objectiveFocus | Free text | What the learner should end up understanding. |
theme | auto, studio, or exhibit | studio is light, exhibit is a dark stage, auto lets the plan choose. A learner can switch it in the player without a rebuild. |
language | Language name or code | Language of on-screen text. Set it; it is not inferred. |
referenceMarkdown | Markdown | Your own material to ground the plan. POST /brief can override it per call. |
Create a simulation
title and visibility are required. Keep new simulations PRIVATE until a person has opened the build.
curl -X POST "$TUTORFLOW_API_BASE_URL/v1/content/classrooms/$CLASSROOM_ID/simulations" \
-H "Authorization: Bearer $TUTORFLOW_CONTENT_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: simulation:compound-interest:v1" \
-d '{
"title": "Compound interest",
"description": "See how rate and time change a balance.",
"visibility": "PRIVATE",
"metadata": {
"topic": "Compound interest on a savings balance",
"audience": "First-year finance",
"objectiveFocus": "Why doubling the time matters more than doubling the rate",
"theme": "auto",
"language": "en",
"externalId": "simulation:compound-interest"
}
}'The response is 201 with the simulation object, contentVersion: 0, brief: null, subject: "other".
List simulations
GET /v1/content/classrooms/{classroomId}/simulations?page=1&limit=20&field=updatedAt&order=DESC&subject=finance
Authorization: Bearer tf_content_...| Parameter | Default | Notes |
|---|---|---|
page | 1 | 1-based. |
limit | 20 | Values above 100 are clamped to 100. take is a deprecated alias. |
field | createdAt | title, createdAt, updatedAt, or subject. Anything else returns 422 with error.allowedValues. |
order | DESC | ASC or DESC. Ties break on id. |
search | Case-insensitive substring of title. | |
updatedSince | ISO 8601 date-time. Only simulations updated at or after it. | |
subject | Only simulations with this subject. |
The response is the list envelope with simulation objects without content. The same parameters work on every resource list; see List pages.
Update a simulation
PATCH /simulations/{simulationId} is partial. It accepts title, description, visibility, brief, and metadata, and returns 200 with the updated simulation. subject, representation, contentKey, and contentVersion belong to the planner and the build pipeline and cannot be set.