Documentation · Document AI

Validation rules. Deterministic checks on a probabilistic pipeline.

Run cross-field math, regex matchers and business rules over the extraction output. Rules are declarative, versioned per tenant, and fail loudly with the values they evaluated.

← Back to documentation

Overview

A deterministic gate between extraction and the rest of your workflow.

  • Runs after extraction — takes an extracted payload (or a fresh document plus a template) and returns pass/fail per rule.
  • Declarative — rules are JSON; no scripting required for the common cases.
  • Versioned — every rule set has a semver tag; you can pin a workflow to a specific version and roll forward safely.
  • Explainable — every failure includes the values the rule saw, not a generic "validation failed" string.

Endpoint

POST /v1/validate Run a rule set against a payload
POST /v1/validate/rules Create or update a rule set
GET /v1/validate/rules/{slug} Inspect a versioned rule set

Rule types

  • presence — field must be non-null; supports required vs preferred severities.
  • regex — field matches a named pattern (e.g. tax ID, IBAN).
  • range — numeric or date bounds (open or closed).
  • math — algebraic equality with a configurable tolerance (totals = sum of line items).
  • cross_doc — the value must match a referenced document (PO ↔ invoice).
  • custom — a small sandboxed expression in our rule DSL when the above don't fit.

Rule syntax

invoice-strict@2.4.0
{
  "slug":    "invoice-strict",
  "version": "2.4.0",
  "rules":   [
    { "id": "vendor_present",
      "type": "presence",
      "field": "vendor_name",
      "severity": "required" },

    { "id": "tax_id_format",
      "type": "regex",
      "field": "tax_id",
      "pattern": "^[0-9]{2}\\.[0-9]{3}\\.[0-9]{3}/[0-9]{4}-[0-9]{2}$" },

    { "id": "totals_reconcile",
      "type": "math",
      "expr": "total_amount == sum(line_items[].unit_price * line_items[].qty) + tax_amount",
      "tolerance": 0.01 },

    { "id": "po_match",
      "type": "cross_doc",
      "left":  "po_number",
      "right": "linked.purchase_order.number" }
  ]
}

Request

POST /v1/validate
curl -X POST https://api.cogneris.ai/v1/validate \
  -H "Authorization: Bearer $COGNERIS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "rule_set": "invoice-strict@2.4.0",
    "payload":  {
      "vendor_name":  "Acme Industries Ltd.",
      "po_number":    "PO-9912",
      "tax_id":       "12.345.678/0001-90",
      "line_items":   [ /* … */ ],
      "tax_amount":   240.10,
      "total_amount": 12480.50
    }
  }'

Response

200 OK
{
  "data": {
    "verdict": "fail",
    "summary": { "passed": 3, "failed": 1, "skipped": 0 },
    "results": [
      { "id": "vendor_present",   "status": "pass" },
      { "id": "tax_id_format",    "status": "pass" },
      {
        "id":      "totals_reconcile",
        "status":  "fail",
        "detail":  "Expected 12480.50; line-item sum + tax computed to 12240.40.",
        "observed": { "total_amount": 12480.50, "computed": 12240.40 }
      },
      { "id": "po_match",         "status": "pass" }
    ]
  },
  "meta": {
    "rule_set":   "invoice-strict@2.4.0",
    "audit_url":  "https://app.cogneris.ai/audit/val_01J9PS2K"
  },
  "has_errors": false
}

Managing rule sets

  • Versioning — every POST /v1/validate/rules bumps the version; old versions remain callable until you delete them.
  • Aliases — point invoice-strict@stable at 2.4.0 today, 2.5.0 tomorrow.
  • Dry-run — pass ?dry=true on a publish to lint rules and report ambiguities without taking effect.
  • DiffGET /v1/validate/rules/{slug}/diff?from=2.3.0&to=2.4.0 returns a structured changelog.

Errors

CodeMeaning
400Malformed rule (unknown type, bad expr) or missing rule_set.
404Rule set or version not found.
422Payload missing a referenced field; the rule that needed it reports status: "skipped" with a reason.

Next: Custom agents

Compose your own ReAct pipeline with the Agents SDK.

Read Custom agents