Templates
Reference for /v1/templates: save a verification setup (expect, checks, storage, human review, retention) and reuse it with template in analyze, classify, batches, links, sessions and dossiers.
A template (tpl_…) is a saved verification setup: which documents you accept (expect), what you check
(checks), what gets stored and for how long, and when a person has to look at the result. You create it once and use
it by id with template in any flow, instead of repeating the same options on every call. Step-by-step guide with
examples in four languages: Reuse settings with templates.
| Method and path | What it does |
|---|---|
POST /v1/templates | Creates a template. |
GET /v1/templates | Lists the account's templates. |
GET /v1/templates/{id} | Retrieves a template. |
PATCH /v1/templates/{id} | Changes a template (partial). |
DELETE /v1/templates/{id} | Deletes a template. |
Every route uses a secret key (ck_test_… or ck_live_…) from your backend. Templates belong to the account, not
to a mode: the same template works with test and live keys. You can also manage them in the
dashboard, under Templates.
The template object
{
"id": "tpl_01J9Z8Q3K4M5N6P7Q8R9S0T1V2",
"object": "template",
"name": "Valid Spanish ID, adult holder",
"description": "A Spanish ID card that has not expired, held by someone aged 18 or over.",
"expect": "es_dni",
"checks": { "not_expired": true, "min_age_years": 18 },
"extract": true,
"storage": "review",
"ttl_hours": null,
"keep_results": true,
"export": [],
"processing": null,
"language": null,
"redact": false,
"mask_fields": ["document_number"],
"verdict_without_expect": true,
"retention_days": 90,
"review_retention_hours_after_decision": 0,
"review_max_days": 7,
"review": { "auto_approve_valid": true, "require_human_for": ["review", "invalid"] },
"example": false,
"created_at": "2026-09-30T09:12:44Z",
"updated_at": "2026-09-30T09:12:44Z"
}Analysis options
They mean the same and are validated the same way as in POST /v1/analyze. A null
value in the response means the template doesn't set it: the request's value is used or, if the request doesn't send
it either, the account's.
| Field | Type | Description |
|---|---|---|
expect | string | string[] | null | Accepted type or types (up to 20), from the catalogue. |
checks | object | Validation rules, like options.checks. |
extract | boolean | object | true (the type's fields), false or your own JSON Schema. |
storage | none | review | temporary | persistent | null | What happens to the original file. See Storage & privacy. |
ttl_hours | integer 1–720 | null | Hours the file is kept with storage: "temporary". |
keep_results | boolean | false: results are returned once and not stored. Default true. |
export | string[] | Exports generated when the analysis finishes (json, csv, xlsx, xml, vcard, pdf, redacted_image). |
processing | sovereign | standard | null | Processing profile. |
language | es | en | pt | fr | null | Language of the verdict messages. |
redact | boolean | Generates a pixelated copy of the image. See Advanced privacy. |
mask_fields | string[] | Fields stored masked. See Advanced privacy. |
verdict_without_expect | boolean | v1.2. Without expect, verdict against the detected type (verdict.basis: "detected"). false: verdict: null without expect. Default true. See Verdicts. |
face_verification | { enabled, required? } | null | Face verification on links and dossiers created with the template (optional module; turning it on requires the module to be active on the account). See Face verification. |
When you create or change a template, precise_bboxes is accepted too (as in analyze), although it isn't returned in
the object.
Retention and review deadlines
| Field | Type | Description |
|---|---|---|
retention_days | integer 1–3650 | null | Days the results (extracted data, verdict, exports) of analyses made with the template are kept. null: the account's period. See Retention. |
review_retention_hours_after_decision | integer 0–720 | null | With storage: "review", hours the original is kept after the review is decided. 0: deleted on decision. null: the account's (24 by default). |
review_max_days | integer 1–90 | null | With storage: "review", maximum days the original is kept if nobody decides. null: the account's (30 by default). |
The deadlines are resolved when each analysis is created and stored with it: changing the template later doesn't alter analyses already made.
Human review policy (review)
| Field | Type | Default | Description |
|---|---|---|---|
review.auto_approve_valid | boolean | true | false: valid analyses also wait for human review. |
review.require_human_for | array of valid, invalid, review | ["review"] | Verdicts that go to the review queue. Add invalid if a person must confirm every rejection. |
An analysis made with the template is left pending (review.status: "pending", verdict.final_status: null) if its
verdict is in require_human_for, or if it is valid and auto_approve_valid is false. Without a template, only
review ones. The queue is handled in the dashboard or through the API: see Reviews.
Other fields
| Field | Description |
|---|---|
id | Id with the tpl_ prefix. |
name | Display name (1–120 characters). |
description | Description (up to 1000 characters) or null. |
example | true for the example templates created with the account. |
created_at, updated_at | ISO 8601 dates. |
Using a template
Pass the template id with template. The template is applied first and the request's options on top, and they
win; checks is merged key by key (you can add holder on each request and keep the template's other checks).
| Where | How to pass it |
|---|---|
POST /v1/analyze and POST /v1/classify | template inside options (multipart) or at the root of the JSON. |
POST /v1/batches | In the common options or in each item's. |
POST /v1/verification-links | template field. If you don't send documents, one is requested with the template's expect. |
POST /v1/sessions | template field. The browser cannot change its options. |
POST /v1/dossiers | template field. Applied to every document analysed in the dossier. |
curl https://api.constaia.com/v1/analyze \
-H "Authorization: Bearer $CONSTAIA_API_KEY" \
-F "file=@dni.jpg" \
-F 'options={"template":"tpl_01J9Z8Q3K4M5N6P7Q8R9S0T1V2","checks":{"holder":{"full_name":"María García López"}},"metadata":{"user_id":"123"}}'The analysis returns the template used in template_id (and in its alias template). If the template doesn't exist in
the account (or was deleted): 422 template_not_found, with param: "options.template" in analyze, classify,
batches and sessions, and param: "template" in links and dossiers.
Create a template
POST /v1/templates
Content-Type: application/jsonOnly name is required. The other fields are the object's (without id, object, example or dates). Fields are
strict: an unknown one returns 422 invalid_parameter with its param.
curl https://api.constaia.com/v1/templates \
-H "Authorization: Bearer $CONSTAIA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Valid ID, adult holder",
"expect": ["es_dni", "es_nie"],
"checks": { "not_expired": true, "min_age_years": 18 },
"storage": "review",
"review_max_days": 7,
"mask_fields": ["document_number"],
"review": { "require_human_for": ["review", "invalid"] }
}'Answers 201 with the template object. If expect or a check is not valid, 422 invalid_parameter with the exact
param (expect, checks.min_age_years, review.require_human_for…).
List templates
GET /v1/templates?limit=20| Parameter | Type | Description |
|---|---|---|
limit | integer 1–100 | Items per page. Default 20. |
starting_after | string | Id (tpl_…) of the last template on the previous page. |
Returns { "object": "list", "data": [...], "has_more": false, "url": "/v1/templates" }, newest first. See
Pagination.
Retrieve, change and delete
curl https://api.constaia.com/v1/templates/tpl_01J9Z8Q3K4M5N6P7Q8R9S0T1V2 \
-H "Authorization: Bearer $CONSTAIA_API_KEY"
curl -X PATCH https://api.constaia.com/v1/templates/tpl_01J9Z8Q3K4M5N6P7Q8R9S0T1V2 \
-H "Authorization: Bearer $CONSTAIA_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "checks": { "not_expired": true, "min_age_years": 16 }, "ttl_hours": null }'
curl -X DELETE https://api.constaia.com/v1/templates/tpl_01J9Z8Q3K4M5N6P7Q8R9S0T1V2 \
-H "Authorization: Bearer $CONSTAIA_API_KEY"PATCHis partial: it only changes the fields you send. An analysis field set tonullis removed from the template (the request or the account decide again).checksis replaced as a whole, not merged.reviewis replaced as a whole: whatever you leave out ofreviewgoes back to its default.- Changes only affect analyses created afterwards.
DELETEreturns{ "id": "tpl_…", "object": "template", "deleted": true }. Analyses, links and dossiers already created with it don't change; new requests that use it get422 template_not_found.
A template that doesn't exist in the account returns 404 resource_missing.
Example templates
Every account starts with five templates (example: true), named in the account's language: valid Spanish ID with an
adult holder, sports medical certificate under 6 months, sexual offences certificate with no records, bank transfer
receipt and invoice (with an XLSX export). They are created when the account signs up or, for older accounts, on the
first read of the list. You can use them as they are, change them or delete them.
SDKs
import { Constaia } from "@constaia/sdk";
const constaia = new Constaia();
const tpl = await constaia.templates.create({
name: "Valid ID, adult holder",
expect: ["es_dni", "es_nie"],
checks: { notExpired: true, minAgeYears: 18 },
review: { requireHumanFor: ["review", "invalid"] },
reviewMaxDays: 7,
});
for await (const t of constaia.templates.list()) console.log(t.id, t.name);
await constaia.templates.update(tpl.id, { maskFields: ["document_number"] });
await constaia.templates.delete(tpl.id);Errors
| HTTP | code | When |
|---|---|---|
422 | invalid_parameter | A field is not valid (param says which), for example an unknown type in expect. |
422 | template_not_found | You use a template id that doesn't exist in the account. |
404 | resource_missing | GET, PATCH or DELETE of a template that doesn't exist. |
Next steps
POST /v1/batches
Reference for POST /v1/batches: analyse up to 100 documents in one asynchronous call, with common or per-document options and a combined export.
Verification links
Reference for /v1/verification-links: create a hosted page where the person uploads their documents from their phone, receive the results by webhook, callback or email, and retrieve, list or cancel links.