📘 Public beta · Endpoints are stable; OpenAPI specs and SDKs ship monthly. See changelog →
Products
Document Intelligence
Templates

Templates

A template is a user-defined schema for a custom document type. Use templates when:

  • You have a doc type not in the built-in registry.
  • A built-in type's schema doesn't match a vendor-specific variant you receive.
  • You want field-level confidence thresholds (e.g. "NIK must be ≥ 95% confidence to auto-trust").

Template object

{
  "id": "tpl_01HXY...",
  "name": "PT Bank XYZ — Loan Disbursement Form v3",
  "slug": "bank-xyz-disbursement-v3",
  "documentTypeHint": "other",
  "fields": [
    {
      "name": "application_id",
      "label": "Application ID",
      "type": "string",
      "required": true,
      "requireConfidenceAbove": 90
    },
    {
      "name": "amount_idr",
      "label": "Loan amount (IDR)",
      "type": "number",
      "required": true,
      "requireConfidenceAbove": 95
    },
    {
      "name": "tenor_months",
      "label": "Tenor (months)",
      "type": "enum",
      "values": [6, 12, 18, 24, 36, 48, 60],
      "required": true
    },
    {
      "name": "disbursement_date",
      "label": "Disbursement date",
      "type": "date",
      "required": true
    },
    {
      "name": "approvers",
      "label": "Approvers",
      "type": "array",
      "items": {
        "type": "object",
        "fields": [
          { "name": "name", "type": "string", "required": true },
          { "name": "title", "type": "string" },
          { "name": "signed_at", "type": "date" }
        ]
      }
    }
  ],
  "active": true,
  "createdAt": "...",
  "updatedAt": "...",
  "version": 3
}

Field types

TypeNotes
stringFree text. Use this for names, addresses, codes.
dateYYYY-MM-DD. Various input formats are normalized.
numberNumeric. Locale-aware parsing (IDR formats like "1.000.000").
enumFixed value list in values[]. Output is one of the values.
arrayList of objects matching the nested items.fields[].

Field options

OptionEffect
required: trueMissing field fails extraction.
requireConfidenceAbove: 90Field-level confidence floor. Below → flag for review.
values: [...]Constrain to enum.
regex: '^[A-Z]{3}-\\d{6}$'Post-extract validation pattern.
hint: 'NIK format'Free-text hint passed to the extractor — guides the AI when ambiguous.

Endpoints

GET/api/templates
Auth · API keyScope · documents:read

List all templates in your org. Filter by active=true to hide retired versions.

POST/api/templates
Auth · API keyScope · documents:write

Create. The slug must be unique per org.

GET/api/templates/{id}
Auth · API keyScope · documents:read
PATCH/api/templates/{id}
Auth · API keyScope · documents:write

Update. Bumps version and keeps old versions queryable for audit (you can't truly mutate history).

DELETE/api/templates/{id}
Auth · API keyScope · documents:write

Soft-delete — sets active: false. Historical extractions tied to the template stay queryable.

Applying a template

Templates apply in two ways:

1. On upload. Pass type=<template_slug> instead of a built-in type:

curl -X POST .../api/documents/upload \
  -F "file=@./disbursement-form.pdf" \
  -F "type=bank-xyz-disbursement-v3"

2. On re-extract. If you uploaded without specifying a template and want to apply one now:

curl -X POST .../api/documents/doc_01HXY.../reextract \
  -H "Content-Type: application/json" \
  -d '{ "templateId": "tpl_01HXY..." }'

When templates beat the built-in models

ScenarioTemplate advantage
Heavily repeated form (always same layout)Deterministic rule_template extraction → 99%+ confidence, zero variability
Vendor-specific invoice variantOverride the built-in invoice template with your own field set
Multi-page contracts with consistent section headingsTemplate can include find_section operators (advanced)
Field-level confidence thresholds matterBuilt-in types use document-level confidence; templates can go per-field

When templates are overkill

ScenarioWhy
Ad-hoc one-off documentsJust use generic_ocr, post-process in your code
Documents that come in many variant formatsBuilt-in models generalize better than rule templates
You're not willing to maintain templates over timeTemplates rot when forms change; you'll need version discipline

Template versioning matters

Bumping a template version doesn't auto-re-extract historical documents. If you update the schema, decide explicitly: do you backfill (loop over historical docs, call reextract with the new template) or accept that older extractions used the older schema. Both are valid — document the choice in your audit policy.