Automette docs

Get a template's field schema

GET
/api/v1/templates/{id}/fields

Authorization

ApiKeyAuth
AuthorizationBearer <token>

API key from Settings → API Keys.

In: header

Path Parameters

id*string

Query Parameters

primary?boolean

true returns only content fields, dropping styling properties. Canvas layers left with nothing are omitted.

Response Body

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/api/v1/templates/string/fields"
{  "id": "cm4tpl8e20001js04xq2v9k3m",  "engine": "typst",  "field_count": {    "total": 1,    "primary": 1  },  "fields": [    {      "key": "customer",      "type": "text",      "example": "Acme Ltd",      "primary": true    }  ],  "sample_data": {    "customer": "Acme Ltd"  }}

Preview a template POST

Renders the template so you can look at it, and returns a signed URL valid for one hour. Fields you do not supply fall back to the template's sample values, so an empty body still produces a filled page rather than a skeleton. Send `document` to preview a candidate without saving it first. **Word templates carry no sample values** — their field schema has nowhere to author one — so each field falls back to its own name and an empty body previews as "Position", "Manager Name". Send `data` to see one meaningfully. Typst and canvas templates have real authored samples. **A preview is not a render.** It creates no render record, does not appear in `GET /api/v1/renders`, costs no credits, and the file expires. Authoring is iterative, and charging per look would make the loop this API exists for the most expensive way to use the product. When you want a retained, listed, deliverable document, call `POST /api/v1/renders`. A template that fails to render returns `422` with the engine's own message — for Typst that includes the line number, which is what you feed back into a fix.

Start a file upload POST

Returns a short-lived URL to post a file to, and an `upload_id` to commit it with. Use this rather than sending bytes to the API. The direct upload endpoints run as serverless functions, which reject request bodies over 4.5MB before this code sees them; here the file goes straight to storage, so the only ceiling is the 25MB we set — and it is enforced by the upload itself, so an oversized file is refused at the door rather than after it is stored. Nothing is stored until you commit. An upload that is never committed expires on its own and counts against nothing. `template_asset` and `template_docx` belong to one template and need `template_id`. `brand_kit_image` and `brand_kit_font` go to the team's Brand Kit, take no `template_id`, and are shared by every template the team has. A Brand Kit upload **adds; it never replaces** — a filename already in the kit is refused with a 409, because replacing a file changes it for every template already pointing at its key. Replacing or deleting one is a dashboard action. A `brand_kit_font` filename must end `.ttf` or `.otf`; a `.woff`/`.woff2` is refused here, before the file is sent, rather than after it arrives. Post the file as `multipart/form-data` to `upload_url`, sending every name/value in `fields` first and the file last, in a part named `file`. `upload_with` is the complete command, already filled in.