Constaia
Endpoints

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 pathWhat it does
POST /v1/templatesCreates a template.
GET /v1/templatesLists 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

template
{
  "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.

FieldTypeDescription
expectstring | string[] | nullAccepted type or types (up to 20), from the catalogue.
checksobjectValidation rules, like options.checks.
extractboolean | objecttrue (the type's fields), false or your own JSON Schema.
storagenone | review | temporary | persistent | nullWhat happens to the original file. See Storage & privacy.
ttl_hoursinteger 1–720 | nullHours the file is kept with storage: "temporary".
keep_resultsbooleanfalse: results are returned once and not stored. Default true.
exportstring[]Exports generated when the analysis finishes (json, csv, xlsx, xml, vcard, pdf, redacted_image).
processingsovereign | standard | nullProcessing profile.
languagees | en | pt | fr | nullLanguage of the verdict messages.
redactbooleanGenerates a pixelated copy of the image. See Advanced privacy.
mask_fieldsstring[]Fields stored masked. See Advanced privacy.
verdict_without_expectbooleanv1.2. Without expect, verdict against the detected type (verdict.basis: "detected"). false: verdict: null without expect. Default true. See Verdicts.
face_verification{ enabled, required? } | nullFace 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

FieldTypeDescription
retention_daysinteger 1–3650 | nullDays 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_decisioninteger 0–720 | nullWith 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_daysinteger 1–90 | nullWith 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)

FieldTypeDefaultDescription
review.auto_approve_validbooleantruefalse: valid analyses also wait for human review.
review.require_human_forarray 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

FieldDescription
idId with the tpl_ prefix.
nameDisplay name (1–120 characters).
descriptionDescription (up to 1000 characters) or null.
exampletrue for the example templates created with the account.
created_at, updated_atISO 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).

WhereHow to pass it
POST /v1/analyze and POST /v1/classifytemplate inside options (multipart) or at the root of the JSON.
POST /v1/batchesIn the common options or in each item's.
POST /v1/verification-linkstemplate field. If you don't send documents, one is requested with the template's expect.
POST /v1/sessionstemplate field. The browser cannot change its options.
POST /v1/dossierstemplate 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/json

Only 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
ParameterTypeDescription
limitinteger 1–100Items per page. Default 20.
starting_afterstringId (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"
  • PATCH is partial: it only changes the fields you send. An analysis field set to null is removed from the template (the request or the account decide again). checks is replaced as a whole, not merged.
  • review is replaced as a whole: whatever you leave out of review goes back to its default.
  • Changes only affect analyses created afterwards.
  • DELETE returns { "id": "tpl_…", "object": "template", "deleted": true }. Analyses, links and dossiers already created with it don't change; new requests that use it get 422 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

templates.ts
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

HTTPcodeWhen
422invalid_parameterA field is not valid (param says which), for example an unknown type in expect.
422template_not_foundYou use a template id that doesn't exist in the account.
404resource_missingGET, PATCH or DELETE of a template that doesn't exist.

Next steps

On this page