Skip to main content

List Checks

List in-pipeline validation checks with GET /v1/structuring/checks: six check types, per-schema scoping, and how check outcomes feed review gate decisions.

A validation check is an in-pipeline data quality rule that runs automatically against every structuring result the moment it is produced. This is in-pipeline validation, distinct from Benchmarks (the /v1/validation namespace), which measure extraction accuracy against Ground Truth after the fact. GET /v1/structuring/checks lists every active check configured for your organization; together with review gates, check outcomes decide whether a record auto-approves or waits for human review.

Each check is scoped to exactly one schema via user_schema_id, so different document types can carry different validation logic. A check runs only against results produced under its schema: when a structuring result lands, the platform loads all active checks for the result's schema in sort_order ascending and evaluates each one against the extracted field values, recording one outcome row per check. There is no cross-schema or organization-wide check — to enforce the same rule on several schemas, create the check once per schema.

Six check types exist, each with its own config shape:

  • field_format — a field value must match a format: regex (with a pattern), email, url, date / iso_date, or uuid. Config: { field, format, pattern? }.
  • field_range — a numeric field must fall within min/max bounds; allow_null: true passes null values instead of failing them. Config: { field, min?, max?, allow_null? }.
  • field_presence — one or more fields must be non-null; mode: "all" (default) requires every listed field, mode: "any" requires at least one. Config: { fields, mode? }.
  • cross_field — relates two fields with a rule: date_before, date_after, not_equal, or sum_equals (with a tolerance, default 0.01; field_a supports array sums like line_items[].amount). Config: { rule, field_a, field_b, tolerance? }.
  • lookup — a field value must appear in a static values allowlist. Config: { field, values }.
  • custom_expression — reserved for a future expression engine; today it always records a skip outcome.
Check outcomes have four statuses, not two: pass, fail, skip, and error. A check records skip (not fail) when its target field is null or its type/format is unrecognized, and error when the evaluation itself crashed (for example an invalid regex pattern). Only fail and error outcomes appear in the pending review queue.
GET/v1/structuring/checks

Query parameters

schema_iduuidFilter checks to one schema scope. Omit to list checks across all schemas.

curl

curl -s "https://api.talonic.com/v1/structuring/checks?schema_id=36ef3a00-a4dc-4e49-af6a-66ae20f9b58a" \
  -H "Authorization: Bearer tlnc_your_api_key"

Response

Response fields

dataarrayArray of validation check objects, ordered by sort_order ascending, then created_at ascending.
data[].idstringCheck UUID.
data[].user_schema_idstringThe schema this check is scoped to.
data[].namestringCheck name.
data[].descriptionstring | nullOptional description.
data[].typestringCheck type: field_format, field_range, field_presence, cross_field, lookup, or custom_expression.
data[].severitystringSeverity label recorded on every outcome this check produces: warning (default), error, or critical. critical outcomes are what a validation_pass gate rule with scope critical_only counts.
data[].configobject | nullType-specific configuration object (see the type list above).
data[].is_activebooleanWhether the check runs against new results. The list returns only active checks.
data[].sort_orderintegerEvaluation and display order among checks for the same schema.
data[].created_atstringISO 8601 creation timestamp.
data[].updated_atstringISO 8601 last update timestamp.
data[].linksobjectRelated resource URLs (self).

Response

{
  "data": [
    {
      "id": "5fee4bba-8380-44b8-9780-5e4548424b3c",
      "user_schema_id": "36ef3a00-a4dc-4e49-af6a-66ae20f9b58a",
      "name": "Total amount range",
      "description": "Totals must be plausible",
      "type": "field_range",
      "severity": "error",
      "config": { "field": "total_amount", "min": 0, "max": 1000000 },
      "is_active": true,
      "sort_order": 0,
      "created_at": "2026-08-29T11:35:01.940Z",
      "updated_at": "2026-08-29T11:35:01.940Z",
      "links": {
        "self": "/v1/structuring/checks/5fee4bba-8380-44b8-9780-5e4548424b3c"
      }
    },
    {
      "id": "342e816c-0687-474e-9393-44ed76dca9d8",
      "user_schema_id": "36ef3a00-a4dc-4e49-af6a-66ae20f9b58a",
      "name": "Due date is a date",
      "description": null,
      "type": "field_format",
      "severity": "warning",
      "config": { "field": "due_date", "format": "date" },
      "is_active": true,
      "sort_order": 1,
      "created_at": "2026-08-29T11:35:01.956Z",
      "updated_at": "2026-08-29T11:35:01.956Z",
      "links": {
        "self": "/v1/structuring/checks/342e816c-0687-474e-9393-44ed76dca9d8"
      }
    }
  ]
}

Errors

Error responses

401unauthorizedMissing or invalid API key.
429rate_limitedToo many requests. Retry after the period indicated in the Retry-After header.

Checks flag individual quality issues; gate rules decide what happens next. A gate's validation_pass rule counts how many outcomes with status fail a result accumulated (optionally scoped to critical-severity checks or a specific check_ids list) and flags the result for review when the count exceeds max_failures. Failing check outcomes also surface directly in [GET /v1/structuring/approvals/pending](pending-approvals), so you can triage data quality issues even without a gate configured.

Field references in config.field use dot and array-index paths over the extracted values: vendor_name reads the field's value, vendor.name reads a key inside an object value, and line_items[0].amount indexes into an array value. The cross_field type's sum_equals rule additionally accepts the line_items[].amount form in field_a to sum a column across every array entry — the standard invoice pattern "line items must sum to the total".

Frequently asked questions

What does severity actually control?+
Severity is a label stamped on every outcome the check produces — it does not by itself block delivery or force review. It matters in two places: a validation_pass gate rule with scope critical_only counts only failures from critical-severity checks, and review UIs use it to rank issues. Whether a result needs review is decided by gate rules, not by severity alone.
Can I create checks that apply to all schemas?+
No. Every check created through the API is scoped to one schema: user_schema_id is a required UUID on create. To enforce the same rule across several schemas, create one check per schema.
How are checks ordered during evaluation?+
Checks are evaluated in sort_order ascending, then by created_at. Order does not short-circuit — every active check for the schema runs and records an outcome — so sort_order is primarily a display and reporting order.
Are soft-deleted checks included in the list?+
No. The list returns only active checks (is_active: true). A soft-deleted check disappears from the list but its historical outcomes on past results are preserved, and you can reactivate it by id with PUT.
What happens when a check references a field the document did not fill?+
Most types record a skip outcome when the target field is null or missing, so absent data is not punished as a failure. The exceptions are field_presence, whose whole purpose is to fail on missing fields, and field_range, which fails on null unless allow_null: true is set in its config.