List templates

GET /v1/templates

Lists your non-archived templates, most recently updated first. Use the returned id as template_id in POST /v1/generate. Requires a valid API key.

Example

curl https://doclinth.com/v1/templates \
  -H "Authorization: Bearer dl_live_YOUR_KEY"

Python

import os, requests

res = requests.get(
    "https://doclinth.com/v1/templates",
    headers={"Authorization": f"Bearer {os.environ['DOCLINTH_API_KEY']}"},
)
res.raise_for_status()
templates = res.json()["data"]
invoice = next(t for t in templates if t["name"] == "Clean Invoice")
print(invoice["id"])  # pass this to POST /v1/generate

Response

{
  "data": [
    {
      "id": "40f7e3c6-b662-4b37-b671-3356ddc2ec12",
      "name": "Clean Invoice",
      "description": "Minimal invoice for SaaS billing.",
      "page_format": "A4",
      "published": true,
      "updated_at": "2026-07-02T15:14:33.000Z",
      "created_at": "2026-06-30T21:33:00.000Z"
    }
  ]
}

Source HTML and sample data are never returned by this endpoint.

Retrieve one template

GET /v1/templates/{id}

Returns a single template plus its sample_data, its rendered html (the published version, falling back to the draft), and a derived variables list of every path the template references — the canonical answer to what shape should my data be. Pair it with strict mode to catch missing fields before they render blank.

curl https://doclinth.com/v1/templates/TEMPLATE_ID \
  -H "Authorization: Bearer dl_live_YOUR_KEY"

{
  "id": "40f7e3c6-b662-4b37-b671-3356ddc2ec12",
  "name": "Clean Invoice",
  "description": "Minimal invoice for SaaS billing.",
  "page_format": "A4",
  "sample_data": { "customer": { "name": "Acme" }, "items": [], "total": 3078 },
  "html": "<!doctype html>…{{customer.name}}…",
  "variables": ["customer.name", "items", "total"],
  "published": true,
  "created_at": "2026-06-30T21:33:00.000Z",
  "updated_at": "2026-07-02T15:14:33.000Z"
}

Paths inside {{#each}}/{{#with}} blocks are listed relative to their block context, so pair variables with sample_data for the exact nested shape.

Create a template from a prompt

POST /v1/templates

AI-authors a new template from a natural-language prompt and saves it as a draft. This is the API-key equivalent of the in-app AI editor — built for agents and automations (it backs the create_template MCP tool and the n8n node). It consumes your monthly AI-authoring allowance, not your PDF quota.

Drafts are never rendered by /v1/generate until you review and publish them in the dashboard. This keeps a generated template from silently changing live output — you always ship on purpose.

curl -X POST https://doclinth.com/v1/templates \
  -H "Authorization: Bearer dl_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"prompt": "A consulting invoice with hourly line items, a notes section, and 8% tax", "quality": "fast"}'

{
  "id": "9b1e7c40-2f3a-4d8e-9c1b-6a2f0e5d7c33",
  "name": "A consulting invoice with hourly line items, a notes se…",
  "description": "A consulting invoice with hourly line items, a notes section, and 8% tax",
  "sample_data": { "invoice_number": "INV-1042", "items": [], "total": 0 }
}

quality is "fast" (default) or "pro"; "pro" uses a stronger model and requires a paid plan (otherwise 403 upgrade_required). The returned id is a draft — fetch its full data contract with GET /v1/templates/{id}, publish it, then generate.

Notes

  • You can also copy any template's id from the Templates dashboard (each row has a Copy button).
  • Archived templates are excluded; unarchive one in the editor to list it again.
  • Burst-limited per API key, same as /v1/generate. Exceeding it returns 429 rate_limited.

Full status/code list: Errors. Machine-readable API definition: OpenAPI spec.