Docs / API reference - Stable

POST /v1/check

Deterministic verdict endpoint - strict context, no required_context loop.

/v1/check produces a deterministic verdict from a fully-shaped context. Use it when the caller knows the exact input shape upfront (OMS, claims platform, custom PEP behind a fixed contract).

For agent-shaped callers that assemble context on the fly, use /v1/resolve.

Request

POST /tnt-acme/v1/check
X-API-Key: ak-live-...
X-Verdict-TTL: 60        (optional, seconds ; default: tenant config)
Content-Type: application/json

Body :

{
  "action": "refund.execute",
  "resource": "TX-456",
  "scope": {
    "product_type": "customer_refund",
    "channel": "in_app"
  },
  "parameters": {
    "amount_eur": 40,
    "reason": "duplicate_charge"
  },
  "on_behalf_of": "hum-marie"
}
  • action (required) - the operation being decided.
  • resource (required) - the resource acted on.
  • scope (required) - a dict validated against the tenant's scope_schema. Every field must be recognised.
  • parameters (optional) - the operation's parameters ; every field will be part of the signed bindings.
  • on_behalf_of (optional) - the human principal on whose behalf the agent is calling.

Response - allowed / blocked / approval_required

{
  "operation_status": "complete",
  "verdict": "allowed",
  "cited_rule_ids": ["rul-refund-under-100"],
  "cited_rule_version_ids": ["rv-abc"],
  "dominating_rule_id": "rul-refund-under-100",
  "precedence_trace": [
    { "rule_id": "rul-refund-under-100", "rule_version_id": "rv-abc",
      "severity": "allow", "scope_match": "exact", "reason": "fires" }
  ],
  "resolved_target_ids": ["tgt-agents-refund-team"],
  "consultation_id": "cns-abc123",
  "signed_verdict": "eyJhbGciOiJFUzI1NiIsInR5cCI6ImdvdmVybmVkK2p3cyIsImtpZCI6...",
  "context_hash": "sha256:9f2c..."
}

The signed_verdict is a compact JWS. See Signed verdicts and PEP for the envelope layout.

Response - blocked

{
  "operation_status": "complete",
  "verdict": "blocked",
  "cited_rule_ids": ["rul-refund-over-1000"],
  "dominating_rule_id": "rul-refund-over-1000",
  "signed_verdict": "eyJ...",
  "consultation_id": "cns-..."
}

The signed envelope carries the deny decision. PEPs SHOULD still verify the signature ; a signed blocked verdict is proof to logs and auditors that Knowledge refused, not that the caller silently dropped the operation.

Response - approval_required

{
  "operation_status": "complete",
  "verdict": "approval_required",
  "cited_rule_ids": ["rul-refund-over-100"],
  "signed_verdict": "eyJ...",
  "consultation_id": "cns-...",
  "approval": {
    "endpoint": "/tnt-acme/v1/approvals",
    "example_body": {
      "consultation_id": "cns-...",
      "requester_notes": "duplicate charge, customer complained"
    }
  }
}

The caller creates an Approval via the approvals endpoint. The PEP typically returns 202-Accepted to the user with a status URL to poll.

Errors

StatusCodeMeaning
400invalid_scope_fieldA field in scope is not in the tenant's scope_schema
400invalid_scope_valueA field value is not in allowed_values
401missing_credentialsSee Authentication
403principal_deactivatedCaller's principal was deactivated
422insufficient_contextA rule needs a field that is not present ; use /resolve instead if this is a common case
500signing_key_unavailableThe verdict signing key could not be resolved ; check docs/engineering/keys-guide.md

Headers

  • Request :
    • X-API-Key: ak-... - required auth (or session cookie).
    • X-Verdict-TTL: N - override the tenant's default TTL for this call (seconds ; max 3600).
  • Response :
    • X-Verdict-TTL: N - the applied TTL, in seconds.
    • X-Consultation-Id: cns-... - the consultation ID, also in the body.

Related