Skip to main content

User Templates

User templates are the primary way to define your output structure. Schemas are created and edited in the Spec composer (/specs) via the Extraction stage's schema editor. Templates give you complete control over which fields appear in your output, how they are extracted, and what validation rules apply. Unlike generated schemas, templates are executable: once published, they can be used to run Jobs, and they are also the schema a Spec is composed over. A template plus a composed rail (Data Policies, validation checkpoints, assembly) is a Spec, which runs as a production Pipeline on the engine.

  1. Create template — Give it a name and description.
  2. Add fields — Specify display name, data type, and optionally extraction instructions.
  3. Map to registry — Automatic matching — exact matches auto-apply, semantic matches need confirmation.
  4. Add reference tables — For code fields (e.g., country name → ISO code), upload key-value pairs.
  5. Publish — Create an immutable version snapshot ready for job execution.

Most teams start by importing an existing spreadsheet or CSV as a template baseline, then refine field types and add extraction instructions. Once you publish a version, it becomes immutable and available for job execution — any further changes happen in a new Workshop draft, keeping your production schema stable while you iterate.

When adding fields, take advantage of the automatic registry matching system. Fields with names that match existing registry entries are linked instantly, inheriting the AI-synthesized extraction instruction. For fields that do not match, write a clear manual instruction describing exactly what the AI should extract from the document. Well-written instructions are the single biggest lever for extraction accuracy.

For best results, keep templates focused on a single document type or closely related group of types. A template with 10-20 well-defined fields will produce higher accuracy than one with 50+ fields spanning unrelated domains. If you need different field sets for different document types, create separate templates and run targeted jobs for each.

Create a schema via API
curl -X POST https://api.talonic.com/v1/schemas \
  -H "Authorization: Bearer $TALONIC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Invoice Schema",
    "description": "Standard invoice fields for AP processing.",
    "definition": {
      "properties": {
        "invoice_number": {
          "type": "string",
          "title": "Invoice Number",
          "description": "Unique identifier on the invoice."
        },
        "vendor_name": { "type": "string", "title": "Vendor Name" },
        "total_amount": { "type": "number", "title": "Total Amount" }
      }
    }
  }'
Response
{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "short_id": "SCH-A1B2C3D4",
  "spec_id": null,
  "spec_version": null,
  "spec_materialized_version": null,
  "name": "Invoice Schema",
  "description": "Standard invoice fields for AP processing.",
  "definition": {
    "type": "object",
    "properties": {
      "invoice_number": {
        "type": "string",
        "description": "Unique identifier on the invoice.",
        "title": "Invoice Number"
      },
      "vendor_name": { "type": "string", "title": "Vendor Name" },
      "total_amount": { "type": "number", "title": "Total Amount" }
    }
  },
  "field_count": 3,
  "version": 1,
  "created_at": "2026-04-25T14:30:00.000Z",
  "updated_at": "2026-04-25T14:30:00.000Z",
  "links": {
    "self": "/v1/schemas/a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "extractions": "/v1/extractions?schema_id=a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "dashboard": "https://app.talonic.com/schemas/user/a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}

POST /v1/schemas accepts the field set in three shapes. The first is JSON Schema, as above: a definition with a properties object, where each property's title becomes the display name, type the data type, and an optional top-level required array marks required fields. The second is a flat key-type map such as { "vendor_name": "string", "total_amount": "number" }, accepted when every value is one of string, number, boolean, date, enum, array, or object. The third is a fields array of objects with field_name, display_name, data_type, description, and is_required. If you send a definition or fields array that produces no fields, the request fails with a 400 and nothing is saved.

Create the same schema from a flat key-type map
curl -X POST https://api.talonic.com/v1/schemas \
  -H "Authorization: Bearer $TALONIC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Invoice Schema (flat)",
    "definition": {
      "invoice_number": "string",
      "vendor_name": "string",
      "invoice_date": "date",
      "total_amount": "number"
    }
  }'

# Each key becomes a field whose title is the key itself.
# Rename display names later in the schema editor.

After creating a schema via the API, you can update it with PUT /v1/schemas/{id}, which replaces the name, description, and field definition. Note that when definition.properties is provided, all existing fields are replaced, so send the complete field set on every update. Registry matching and publishing remain app workflows in the Spec composer: trigger a Rematch from the schema editor, then publish an immutable version when ready. The API path is useful for teams that synchronize template definitions across environments.

Every schema route accepts either the full UUID or the short ID shown in the app, such as SCH-A1B2C3D4, which is the first eight characters of the UUID. GET /v1/schemas is cursor-paginated and takes a search parameter that matches the schema name. Schema names are capped at 100 characters. The response also carries spec_id, spec_version, and spec_materialized_version: when a schema was authored in the Spec composer, these point to the owning Spec and its published head, because the Spec's own ID differs from the schema ID. The version field is a separate legacy counter and stays at 1 for schemas created through the API.

A schema that is managed by a Spec document is read-only through the public API. PUT, PATCH, and DELETE on such a schema answer 409 Conflict, because the next Spec publish would overwrite any change made outside the composer. Edit those schemas in the Spec composer and publish there. Schemas created through POST /v1/schemas are not owned by a Spec and can be updated or deleted freely; a successful delete returns { "deleted": true, "id": "..." }.

Replacing fields through the API resets app-side field settings. A PUT or PATCH that includes definition.properties or a non-empty fields array deletes the existing fields and recreates them from the name, title, type, description, and required flag only. Manual instructions, reference tables, and registry mappings set in the schema editor are not carried over, and every field starts unmatched again. Send only name or description when you want to rename a schema without touching its fields.
You can import templates from Excel, CSV, or JSON files using the Import from file option. Column headers become field names, and data types are inferred automatically. This is the fastest way to bootstrap a template from an existing spreadsheet.

Frequently asked questions

How do I create a user template?+
Schemas are created and edited in the Spec composer (/specs) via the Extraction stage's schema editor: give the template a name and description, add fields with data types and instructions, map to the registry, add reference tables, and publish. You can also import from Excel, CSV, or JSON to bootstrap a template from an existing spreadsheet — column headers become field names and data types are inferred automatically.
What is the difference between generated schemas and user templates?+
Generated schemas are AI-created per document type with all Core and Proven fields — they are read-only and cannot run jobs. User templates are custom-defined output structures where you choose exactly which fields to include, how to map them to the registry, and what validation rules apply. Only published user templates can be used for Jobs.
Can I update a published template?+
Published versions are immutable. To make changes, open the Workshop draft, edit your fields, and publish a new version. The previous version remains available in Version History for reference and diffing. This append-only versioning ensures that historical job results always reference the exact schema that produced them.
How do I add fields to a template programmatically?+
Use PUT /v1/schemas/{id} with a definition.properties object describing the full field set; each property carries a type, title, and optional description. When definition.properties is provided, all existing fields are replaced, so include every field you want to keep. Registry matching then runs in the app: open the schema editor and trigger a Rematch, where exact name matches link instantly and semantic matches appear as suggestions for confirmation.
Why does updating my schema through the API return 409 Conflict?+
The schema is managed by a Spec document, so the public API treats it as read-only. A change made there would be overwritten by the next Spec publish. Make the change in the Spec composer and publish, or use spec_id from the schema response to find the owning Spec.
Can I refer to a schema by its short ID?+
Yes. Every /v1/schemas/{id} route accepts either the full UUID or the SCH- short ID shown in the app, for example SCH-A1B2C3D4. The short ID is the first eight characters of the UUID, uppercased, and is returned as short_id on every schema response.