Templates and versions
A template is a reusable document definition: a hearing notice, a summons, a fee receipt. Its content lives in versions (immutable snapshots of fields, merge tags, and options), so a document you generated last month is reproducible today, and editing can never silently change production output.
The lifecycle
draft ──finalize──► ready ──publish──► published ──(newer publish)──► superseded
| Version status | Meaning |
|---|---|
draft | Awaiting its base PDF upload |
ready | Finalized and usable |
published | The version generation resolves by default |
superseded | Previously published; republish it to roll back |
Two rules make the model safe:
- Versions are immutable. Once created, a version's fields and options never change. To change content, append a new version.
- Generation follows the published pointer.
POST …/generaterenders the template'spublished_versionunless the request pins a specificversion. Publishing is the only action that changes what production renders.
Creating a template
A template starts as a metadata shell, with name, description, and
optional defaults merged into every version:
curl -s "https://api.pdfs.ecourtdate.com/v1/templates" \
-H "x-api-key: $API_KEY" \
-H "X-On-Behalf-Of: clerk@example.gov" \
-H "Content-Type: application/json" \
-d '{ "name": "Hearing Notice", "description": "Standard notice of hearing, English" }'
All write operations require the templates:write scope and an
X-On-Behalf-Of header (Authentication).
Adding a version
POST /v1/templates/{templateId}/versions appends an immutable version with
fields (Fields), merge_tags (Merge tags),
defaults, and options (Document options).
The base PDF
A version can render on top of a base PDF (your existing court form) or on server-synthesized blank pages:
- Inline: include
base_pdf_base64(standard base64, max 20 MB decoded) and the version is immediatelyready. - Upload: omit the base PDF and the response includes one-time
uploadinstructions: HTTPPOSTthe file toupload.urlas multipart form data with every entry ofupload.fieldsincluded exactly as given, within the 15-minute window, then callPOST …/versions/{version}/finalize. Finalize validates the file and marks the versionready, or explains why not (409 UPLOAD_NOT_FOUNDif nothing was uploaded;422 INVALID_PDF,BASE_PDF_TOO_LARGE, orTOO_MANY_PAGESif the file can't be used). Finalize is idempotent once the version is ready. - Neither: a version with no base PDF and no upload renders on blank pages.
What finalize unlocks for editors
Once finalized, GET …/versions/{version} exposes geometry an editor UI needs:
pages: width, height, and rotation of every page, in points, so fields can be placed visually.acro_fields: the base PDF's interactive form-field inventory (name, kind, options, max length). These are the valid targets forfillfields, so users pick real field names instead of typing them blind.- Out-of-bounds fields are reported in the create/finalize response as
FIELD_OUT_OF_BOUNDSwarnings.
Previewing
POST …/versions/{version}/preview renders the version with whatever sample
data you supply (missing merge values are tolerated) and returns the PDF,
watermarked PREVIEW by default. Pass "watermark": false for WYSIWYG
editors.
Preview requires only templates:read, so browse and editor UIs can show
documents without generation rights. Previews are recorded as previews in the
audit trail, never as document issuance.
Publishing and rolling back
curl -s -X POST "https://api.pdfs.ecourtdate.com/v1/templates/$TEMPLATE_ID/versions/2/publish" \
-H "x-api-key: $API_KEY" \
-H "X-On-Behalf-Of: clerk@example.gov"
Publishing points the template's published_version at this version; the
previously published version becomes superseded. Republishing a superseded
version is rollback: same call, older version number.
Generating from a template with no published version returns 409
NO_PUBLISHED_VERSION (pin a version explicitly to render an unpublished
one).
Copying
POST /v1/templates/{templateId}/copy clones the published (or, if none, the
latest finalized) version into a new template: the fastest way to create a
Spanish variant of an English notice, or a per-division fork. A source with no
usable version returns 409 NOTHING_TO_COPY.
Listing, search, and archive
GET /v1/templateslists newest first (pagination), withstatus=active|archived|all.?q=searches template names case-insensitively over the newest 500 templates (search results are not cursor-paginated).DELETE /v1/templates/{templateId}archives: the template disappears from default listings and can no longer generate documents (409 TEMPLATE_ARCHIVED). Versions and history remain: archiving is not data deletion.