Endpoints
POST /v1/tents with template_id starts a new generation from its HTML instead of from a blank page. Templates start as a draft and accumulate versions as you iterate — either by editing the HTML directly or by prompting the AI.
AI iteration is asynchronous. Posting a message returns
202 Accepted with a generation_id, and you poll the generation endpoint to track progress. Only one generation can run per template at a time.Idempotency
POST /v1/tent-templates, POST /v1/tent-templates/from-tent/{tentId}, POST /v1/tent-templates/{templateId}/messages, POST /v1/tent-templates/{templateId}/save-code, and POST /v1/tent-templates/{templateId}/clone accept an optional Idempotency-Key header. Retrying with the same key replays the stored result instead of creating a duplicate. If a request with the same key is still being processed, the API returns 409 Conflict with error_code: "idempotency_in_progress".
Create a Template
Request Body
Creating with
code seeds a completed v1 that the editor loads directly and returns 201 Created with the template object. To create from an existing tent instead, use POST /v1/tent-templates/from-tent/{tentId}; to change the HTML with AI afterward, iterate with a message.
Request Example
Response Example
201 Created
status is draft or approved. source_type is upload for API- or hand-authored templates, or tent for templates created from an existing tent (then source_tent_id points to it). On a subsequent GET, the object also includes latest_generation_status (generating, completed, or failed).
Create From a Tent
{"name": "..."} with the new template’s display name. Returns 201 Created with the template object (source_type: "tent").
Iterate With AI
prompt (1-10000 characters) with the instruction, plus optional asset_ids naming template assets to make available to the generation.
202 Accepted
409 Conflict with error_code: "generation_in_progress".
Poll a Generation
status moves through generating to completed or failed. Completed generations include the version they produced plus a content_path under /v1/tent-templates/...; failed ones return error_code: "generation_failed" and an error_message.
Read Content
text/html content type — not JSON.
Save Code Directly
{"code": "..."} with the full replacement HTML (1 byte-2 MB) to create a new version synchronously — 200 OK with the new generation_id and version. Blocked while an AI generation is running.
Approve and Unapprove
POST /v1/tents with template_id. The template must have at least one completed generation. Optionally send {"version": <n>} as an optimistic-concurrency precondition — a mismatch with the newest completed version (normally equal to current_version) returns 409 Conflict with error_code: "approval_version_stale". Approval works while a generation is running — it pins the latest already-completed version; the running generation, once finished, produces a newer draft version until you approve again.
Unapproving returns the template to draft and is never blocked: tents already seeded from the template are unaffected, but the template can no longer seed new tents until it is approved again. Both endpoints return the updated template object.
Clone a Template
draft. Optionally send {"name": "..."}; the name defaults to "Copy of {name}". Returns 201 Created with the new template object.
List Templates
status (any, draft, approved), sort_by (updated_at, created_at, name), sort_order, limit (1-100), and cursor. Responses contain templates and next_cursor. List items carry metadata only (no latest_generation_status or content_path) — fetch HTML per template via GET /v1/tent-templates/{templateId}/content.
Delete a Template
200 OK with {"template_id": "...", "deleted": true}. Deletion is never blocked — tents already seeded from the template keep their own copy of the content.
Common Errors
Next: Create Tents
Seed a new tent from your approved template with
POST /v1/tents.