Skip to main content

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 statusMeaning
draftAwaiting its base PDF upload
readyFinalized and usable
publishedThe version generation resolves by default
supersededPreviously 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 …/generate renders the template's published_version unless the request pins a specific version. 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 immediately ready.
  • Upload: omit the base PDF and the response includes one-time upload instructions: HTTP POST the file to upload.url as multipart form data with every entry of upload.fields included exactly as given, within the 15-minute window, then call POST …/versions/{version}/finalize. Finalize validates the file and marks the version ready, or explains why not (409 UPLOAD_NOT_FOUND if nothing was uploaded; 422 INVALID_PDF, BASE_PDF_TOO_LARGE, or TOO_MANY_PAGES if 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 for fill fields, 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_BOUNDS warnings.

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/templates lists newest first (pagination), with status=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.