Versions
A model project keeps a git-style history: you edit a mutable draft, and commit it as an immutable version with a required "What changed?" message (and an optional "Why?"). Committed versions can be listed, diffed, restored into the draft, solved directly, and pinned by a marketplace listing when you publish.
Info: Each execution records the model version used, enabling audit trails. You can always trace a solve result back to the exact model definition that produced it.
Commit a version
POST /api/v2/projects/{project_id}/commit
| Field | Type | Required | Description |
|---|---|---|---|
summary | string | Yes | What changed (the commit message) |
body | string | No | Why — extended rationale |
Returns 201 with the new version (id prefixed mpv_), including its frozen model snapshot, structural stats, and problem class.
import httpx
response = httpx.post(
"https://jaot.io/api/v2/projects/mp_abc123/commit",
headers={"Authorization": "Bearer ok_live_..."},
json={"summary": "Tighten capacity to 80", "body": "Q3 capacity drop"},
)
version = response.json()
print(f"Committed {version['id']} (v{version['sequence']})")List versions
GET /api/v2/projects/{project_id}/versions
Newest first. Supports skip and limit (default 50). Summaries omit the full model snapshot — fetch one for the whole thing:
GET /api/v2/projects/{project_id}/versions/{version_id}
Diff two versions
GET /api/v2/projects/{project_id}/versions/{a}/diff/{b}
Returns a structural diff: variables/constraints added, removed, and changed, plus objective changes — the same diff the workspace's version history renders, and the grounded input for the AI "explain these changes" feature.
Restore a version
POST /api/v2/projects/{project_id}/versions/{version_id}/restore
Checks the committed version out into the draft (history is untouched — nothing is deleted). If the draft has uncommitted changes, the restore returns 409 unless you pass ?discard_draft=true.
Solve a specific version
POST /api/v2/projects/{project_id}/solve?version_id={version_id} solves the frozen snapshot instead of the draft — see the Models API.
Builder document versions (visual builder)
The standalone visual builder keeps its own lighter-weight history of canvas snapshots. These are not project commits: they come in two types:
- Unnamed checkpoints -- automatic snapshots created as you work. Subject to retention pruning.
- Named versions -- promoted checkpoints with a name and description. Never pruned.
When you pin a trigger to a version, that version is automatically promoted to named status to prevent it from being pruned.
List versions
GET /api/v2/builder/{document_id}/versions
Returns the version history for a builder document, newest first. Response omits the full canvas_json for performance -- use the single-version endpoint to retrieve it.
Authentication: API key (organization scope)
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
skip | int | 0 | Number of versions to skip |
limit | int | 50 | Maximum versions to return |
import requests
response = requests.get(
"https://jaot.io/api/v2/builder/doc_abc123/versions",
headers={"Authorization": "Bearer ok_live_..."},
params={"limit": 10}
)
versions = response.json()
for v in versions:
label = v.get("version_name") or f"Checkpoint #{v['sequence']}"
print(f"{label} -- {v['created_at']}")Response (200)
[
{
"id": "ver_def456",
"document_id": "doc_abc123",
"organization_id": "org_b7e4d1a0",
"sequence": 12,
"is_named": true,
"version_name": "Production v2.1",
"version_description": "Added capacity constraint for warehouse B",
"change_summary": "Modified 2 constraints, added 1 variable",
"created_at": "2026-02-18T14:30:00Z"
},
{
"id": "ver_ghi789",
"document_id": "doc_abc123",
"organization_id": "org_b7e4d1a0",
"sequence": 11,
"is_named": false,
"version_name": null,
"version_description": null,
"change_summary": "Added 1 constraint",
"created_at": "2026-02-18T14:25:00Z"
}
]Response fields
| Field | Type | Description |
|---|---|---|
id | string | Version ID (e.g., ver_def456) |
document_id | string | Parent builder document |
sequence | int | Auto-incrementing sequence number |
is_named | boolean | Whether this is a named (permanent) version |
version_name | string | Name (null for unnamed checkpoints) |
version_description | string | Optional description |
change_summary | string | Auto-generated summary of changes from previous version |
created_at | string | ISO 8601 timestamp |
Get a version
GET /api/v2/builder/{document_id}/versions/{version_id}
Returns a single version including the full canvas_json snapshot.
Authentication: API key (organization scope)
response = requests.get(
"https://jaot.io/api/v2/builder/doc_abc123/versions/ver_def456",
headers={"Authorization": "Bearer ok_live_..."},
)
version = response.json()
print(f"{version['version_name']}: {version['change_summary']}")Response (200)
{
"id": "ver_def456",
"document_id": "doc_abc123",
"organization_id": "org_b7e4d1a0",
"sequence": 12,
"is_named": true,
"version_name": "Production v2.1",
"version_description": "Added capacity constraint for warehouse B",
"canvas_json": { "nodes": [...], "edges": [...] },
"model_json": { "variables": [...], "constraints": [...], "objective": {...} },
"change_summary": "Modified 2 constraints, added 1 variable",
"created_at": "2026-02-18T14:30:00Z"
}Create a checkpoint
POST /api/v2/builder/{document_id}/versions
Snapshot the current canvas state as an unnamed checkpoint. If the canvas is unchanged since the last checkpoint, the existing version is returned without creating a duplicate.
Authentication: API key (organization scope)
Request body
| Field | Type | Required | Description |
|---|---|---|---|
canvas_json | object | Yes | Current canvas state to snapshot |
response = requests.post(
"https://jaot.io/api/v2/builder/doc_abc123/versions",
headers={"Authorization": "Bearer ok_live_..."},
json={
"canvas_json": {
"nodes": [
{"id": "n1", "type": "variable", "data": {"name": "widgets"}}
],
"edges": []
}
}
)
version = response.json()
print(f"Checkpoint created: {version['id']} (sequence #{version['sequence']})")Response (201 Created)
{
"id": "ver_new123",
"document_id": "doc_abc123",
"sequence": 13,
"is_named": false,
"version_name": null,
"canvas_json": { "nodes": [...], "edges": [...] },
"change_summary": "Added 1 node",
"created_at": "2026-02-19T09:00:00Z"
}Promote to named version
PATCH /api/v2/builder/{document_id}/versions/{version_id}
Assign a name and optional description to an existing checkpoint. Named versions are never pruned by the retention policy.
Authentication: API key (organization scope)
Request body
| Field | Type | Required | Description |
|---|---|---|---|
version_name | string | Yes | Name for the version |
version_description | string | No | Optional description |
response = requests.patch(
"https://jaot.io/api/v2/builder/doc_abc123/versions/ver_ghi789",
headers={"Authorization": "Bearer ok_live_..."},
json={
"version_name": "Before Q1 changes",
"version_description": "Stable version before adding seasonal constraints"
}
)
version = response.json()
print(f"Promoted: {version['version_name']} (is_named={version['is_named']})")Restore a version
POST /api/v2/builder/{document_id}/versions/{version_id}/restore
Restore the document canvas to a previous version. Before applying the restore, a safety checkpoint of the current canvas is automatically created so you can undo the restore if needed.
Authentication: API key (organization scope)
Request body
| Field | Type | Required | Description |
|---|---|---|---|
current_canvas_json | object | Yes | Current canvas state (used for safety checkpoint) |
response = requests.post(
"https://jaot.io/api/v2/builder/doc_abc123/versions/ver_def456/restore",
headers={"Authorization": "Bearer ok_live_..."},
json={
"current_canvas_json": current_canvas # your current canvas state
}
)
result = response.json()
print(f"Restored! Safety checkpoint: {result['checkpoint_id']}")
print(f"Document updated: {result['document']['id']}")Response (200)
{
"checkpoint_id": "ver_safety_abc",
"document": {
"id": "doc_abc123",
"organization_id": "org_b7e4d1a0",
"name": "Warehouse Optimizer",
"canvas_json": { "nodes": [...], "edges": [...] },
"model_json": { "variables": [...], "constraints": [...] },
"is_active": true,
"created_at": "2026-01-10T09:00:00Z",
"updated_at": "2026-02-19T09:15:00Z"
}
}Errors
| Status | Description |
|---|---|
| 404 | Document or version not found |