---
title: "Test policy against input"
method: POST
path: "/api/v1/policies/{id}/test"
tags: ["Dynamic Policies"]
deprecated: true
---

# Test policy against input

`POST /api/v1/policies/{id}/test`

## Request

- Base URL: `https://orchestrator.getaxonflow.com`
- URL: `https://orchestrator.getaxonflow.com/api/v1/policies/{id}/test`
- Auth: none declared. Required headers: `X-Tenant-ID`
- TypeScript: <https://skmtc.dev/getaxonflow/apis/axonflow-orchestrator-api/docs/api/v1/policies/:id/test/post.ts> (a function with typed inputs; its response is checked against the schema)

> **Deprecated.**

Test how a specific policy evaluates against sample input

## Path parameters

- `id` string, uuid, required

## Headers

- `X-Tenant-ID` string, required

## Request body

- object
  - `query` string, required: Input to evaluate
  - `context` object: Additional context

## Response `200`

Test result

- PolicyEvaluationResult: The policy verdict carried on every orchestrator response. Its property SET is held equal to the Go type's JSON members by `TestThePublishedSchemasMatchTheTypesThePlatformMarshals`, which compares the two by reflection, so a field added to one and not the other fails CI rather than reaching a spec-generated client (#3724). The properties are also written in the Go type's declaration order as a courtesy to a reader diffing the two; nothing enforces that, and order is not part of the contract.
  - `allowed` boolean
  - `applied_policies` string[]
  - `risk_score` number
  - `severity` 'critical' | 'high' | 'medium' | 'low': Highest severity among the matched policies.
  - `severity_policy_id` string: The policy that contributed `severity`.
  - `required_actions` string[]
  - `processing_time_ms` integer
  - `database_accessed` boolean
  - `evaluation_error` boolean: Distinguishes **could not govern** from **a policy said block**, and is the only signal that does. True when the engine could NOT complete evaluation because governance-segment resolution failed (a resolver or storage error -- never "the caller belongs to zero segments"). `allowed` is always false when this is set, because the engine fails CLOSED on that error, so a consumer reading only `allowed` still behaves safely; a consumer that audits or alerts MUST read this field to tell an availability failure apart from a genuine policy match. Before it existed the only signal was the magic string `applied_policies: ["segment_resolution_failed"]`.
  - `segments_resolved` boolean: True only when a resolved, non-empty governance-segment set was actually factored into this verdict. False covers every legitimate organisation-only case -- no identity supplied, no resolver wired (community, or no SCIM), or the caller belongs to zero segments -- as well as the `evaluation_error` case. None of those are failures: the flag exists so a reader of a policy-simulation preview does not mistake a legitimate org-only allow for a segment-aware one.
  - `applied_policies_detail` AppliedPolicyDetail[]: Structured mirror of `applied_policies` carrying each matched policy's risk level and allow_override metadata, without a second query. No session override is applied to a result in v11 (#4252).
    - `policy_id` string
    - `policy_name` string
    - `description` string
    - `action` string
    - `risk_level` 'low' | 'medium' | 'high' | 'critical'
    - `allow_override` boolean: False if and only if the policy forbids a session override.
    - `matched_rule` string
    - `segment_id` string: The governance segment this policy is scoped to, or absent when it is not segment-scoped. ATTRIBUTION AND AUDIT ONLY -- it is not an override-eligibility signal anywhere: a segment-scoped policy uses the same `allow_override` contract as a tenant policy.
  - `preferred_provider` string: LLM provider a matched routing policy prefers. When more than one applying route row names one, the LAST applying row in evaluation order wins it and the routing reason: rows are walked by priority, highest first, then newest first, so the winner is the lowest-priority applying row (#4249).
  - `allowed_providers` string[]: Strict provider allow-list for compliance routing. Failover stays within this list. It is the intersection of every applying route row's list, whatever their order; an empty intersection refuses the request (`no_compliant_provider`).
  - `routing_reason` string: Why routing was changed.

## Other responses

- `401`: Unauthorized - missing or invalid organization scope (coded envelope)
- `404`: Policy not found

---

[API](https://skmtc.dev/getaxonflow/apis/axonflow-orchestrator-api.md) - [All operations](https://skmtc.dev/getaxonflow/apis/axonflow-orchestrator-api/llms.txt) - [OpenAPI document](https://skmtc.dev/getaxonflow/apis/axonflow-orchestrator-api/revisions/f408ef3ec9dd?raw)
