Skip to main content

Endpoints

Tent templates are reusable, AI-editable page layouts that seed new tents. Once a template is approved, 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.
Assets (images and files an iteration can reference) are managed with the shared asset endpoints — see Managing Assets.

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

Turn an existing tent’s latest completed render into a reusable template — its HTML and assets are copied over. Send {"name": "..."} with the new template’s display name. Returns 201 Created with the template object (source_type: "tent").

Iterate With AI

Queue an AI edit against the template’s current HTML. Send a required prompt (1-10000 characters) with the instruction, plus optional asset_ids naming template assets to make available to the generation. 202 Accepted
Starting a second generation while one is running returns 409 Conflict with error_code: "generation_in_progress".

Poll a Generation

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

Returns the HTML of the latest completed version (or of one specific generation) with a text/html content type — not JSON.

Save Code Directly

Send {"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

Approving marks the template’s newest completed version usable for seeding new tents via 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

Duplicate the template — its chat, generation history, and assets — as a fresh draft. Optionally send {"name": "..."}; the name defaults to "Copy of {name}". Returns 201 Created with the new template object.

List Templates

Cursor-paginated, with the same query parameters as listing email 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

Returns 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.