Automette docs
Getting Started

Core concepts

Automette has a small object model. Once you know the four nouns below, the rest of the product is variations on a theme.

The data model at a glance

Team
 └── Template          ← the design + the field list
      └── Job          ← one trigger event (API call, CSV upload, form submit, etc.)
           └── Render  ← one output file

A team owns everything. A template is the document blueprint. A job is the thing that fired off work. A render is the file you actually download.

Template

A template is the document blueprint: the layout, the static copy, and the fields that get filled in at render time. Automette ships two engines you can build templates in:

  • Typst — text-based markup, compiled to PDF. Best for invoices, certificates, multi-page reports.
  • Canvas — visual drag-and-drop editor. Best for social posts, banners, image-first designs.

Both engines support the same idea: declare a field, then pass a value when you render. The list of fields a template accepts is its available fields — visible in the dashboard and via GET /api/v1/templates/{id}.

A template lives inside a project and belongs to one team. Two templates with the same name are two different templates — IDs are what's stable.

Render

A render is one output file. PDF, PNG, or JPG, depending on the template engine and the request. Every render has:

  • A statuspending, running, completed, or failed.
  • A URL to the file (null until completed).
  • A visibilitypublic (CloudFront-cached, shareable) or secure (presigned URL only).
  • The input data that produced it, kept for reference.

Renders are immutable. If you need to "regenerate," you create a new render — the old one stays exactly as it was. See Retrieve renders for the API shape.

Job

A job is the trigger event. One job groups one or more renders that came from the same source. Single-template API calls and form submissions produce a job with one render. CSV bulk uploads and Template Set collections produce a job with many renders.

Every job has a source identifying what triggered it:

SourceWhat fired it
apiPOST /api/v1/renders
csvBulk generate from a CSV
uiGenerate page in the dashboard, or the editor Export button
formPublic form submission
ondemandOn-demand URL (pre-warm at sign time)
collectionPOST /api/v1/collections against a Template Set

Jobs show up in History in the dashboard regardless of source — one log for everything you've ever generated.

Brand Kit

A brand kit centralizes your visual identity — colors, fonts, logos — so multiple templates stay on-brand without per-template duplication. Reference the kit from a template and changes to the kit propagate to every template using it.

Template Set

A template set groups multiple templates (e.g. invoice + cover letter + delivery slip) and maps one canonical set of field names onto each template's internal field names. Triggering a render against a Set produces one job with N renders — useful when one event needs to produce a packet of related documents.

See the Collections API for the programmatic path.

Form

A form is a hosted, shareable URL (https://automette.com/forms/{slug}) that submits to a template or template set. Each submission becomes a job. Forms support quota limits, expiry dates, and optional password gating — useful for time-bound campaigns or per-customer micro-sites.

On-demand URL

An on-demand URL is a signed image URL like https://automette.com/ondemand/{base}/image.pdf?data=...&s=.... The first request renders and caches; every request after is a CDN hit. Used for embedding personalized documents in emails or live web pages — no API call per recipient.

How it all fits

If you take a single API render, you get one job (source: api) with one render. If you trigger a Collections call, you get one job (source: collection) with N renders, one per template in the Set. If you upload a 500-row CSV, you get one job (source: csv) with 500 renders.

The fact that everything funnels into the same Job + Render model is intentional: history, billing, and search all work the same way regardless of which trigger fired the work.

On this page