---
title: "Test Cedar policy evaluation against real entities"
method: POST
path: "/zones/{zone_id}/policy-evaluations"
tags: ["PolicyEvaluations"]
---

# Test Cedar policy evaluation against real entities

`POST /zones/{zone_id}/policy-evaluations`

## Request

- Base URL: `https://docs.keycard.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://docs.keycard.ai/zones/{zone_id}/policy-evaluations`
- Auth: one of:
  - HTTP bearer
  - OAuth 2
    - Client credentials
    - Token URL: `/service-account-token`

Stateless evaluation endpoint for testing Cedar policy evaluation against real entities before deployment. Supports evaluating a single policy, a full policy set, or raw Cedar text.

## Path parameters

- `zone_id` string, required

## Headers

- `X-API-Version` string
- `X-Client-Request-ID` string, uuid

## Request body

- PdpPolicyEvaluationRequest
  - `principal_type` 'user' | 'application', required
  - `principal_id` string, required: Public ID of the user or application.
  - `action` string, required: Cedar action to evaluate (e.g. `any`). The engine namespaces actions automatically as `Keycard::Action::"<name>"`.
  - `resource_id` string, required: Public ID of the resource.
  - `subject_type` 'user' | 'application'
  - `subject_id` string: Public ID of the subject (required when subject_type is set).
  - `authority_type` 'delegation' | 'impersonation', nullable: Discriminator for the subject authority model. Determines how the subject relationship is expressed in the Cedar context: - `"delegation"` — sets `context.on_behalf = true` on the actor check. The actor is acting on behalf of the subject. - `"impersonation"` — sets `context.impersonate = true` on the actor check. The actor is impersonating the subject. When null and a subject is present, defaults to `"delegation"` for backward compatibility.
  - `acting_principal_id` string: ID of the acting application from a verified RFC 8693 `actor_token`, as sent on `/policy/check`. Resolved with the same entity lookup as an application `principal_id` and exposed to Cedar as `context.acting_principal.application` on both checks. Lets a captured evaluation request be replayed faithfully.
  - `context` PdpEvaluationContext: Additional context for Cedar authorization evaluation. Fields here are mapped directly into the Cedar `context` record.
    - `scopes` string[]: OAuth scopes associated with the request. Mapped to `context.scopes` in the Cedar evaluation as a `Set<String>`.
    - `session_id` string: Session identifier for the current authorization context. Mapped to `context.session_id` in Cedar.
    - `claims` PdpEvaluationClaims: Token claims for the actor, subject, and/or acting principal. Mapped to `context.actor_claims`, `context.subject_claims`, and `context.acting_principal_claims` in Cedar.
      - `actor` PdpClaimsData: Represents token claims passed into the Cedar context. Mapped to the Cedar `Keycard::Claims` type. Known fields (`email`, `groups`, `issuer_claims`) are typed; additional claims are passed through as untyped key-value pairs via `additionalProperties`.
        - `email` string: Email claim from the authentication token.
        - `groups` string[]: Group membership claims from the authentication token.
        - `issuer_claims` PdpIssuerClaims: Issuer-specific claims forwarded opaquely from STS (e.g. GHA OIDC assertion claims). Mapped to `context.actor_claims.issuer_claims` in Cedar. All fields are optional and issuer-dependent. See issuer documentation for available claim fields.
      - `subject` PdpClaimsData: Represents token claims passed into the Cedar context. Mapped to the Cedar `Keycard::Claims` type. Known fields (`email`, `groups`, `issuer_claims`) are typed; additional claims are passed through as untyped key-value pairs via `additionalProperties`.
        - `email` string: Email claim from the authentication token.
        - `groups` string[]: Group membership claims from the authentication token.
        - `issuer_claims` PdpIssuerClaims: Issuer-specific claims forwarded opaquely from STS (e.g. GHA OIDC assertion claims). Mapped to `context.actor_claims.issuer_claims` in Cedar. All fields are optional and issuer-dependent. See issuer documentation for available claim fields.
      - `acting_principal` PdpClaimsData: Represents token claims passed into the Cedar context. Mapped to the Cedar `Keycard::Claims` type. Known fields (`email`, `groups`, `issuer_claims`) are typed; additional claims are passed through as untyped key-value pairs via `additionalProperties`.
        - `email` string: Email claim from the authentication token.
        - `groups` string[]: Group membership claims from the authentication token.
        - `issuer_claims` PdpIssuerClaims: Issuer-specific claims forwarded opaquely from STS (e.g. GHA OIDC assertion claims). Mapped to `context.actor_claims.issuer_claims` in Cedar. All fields are optional and issuer-dependent. See issuer documentation for available claim fields.
  - `policy_source` PdpPolicySource, required: Specifies which policies to evaluate. Exactly one of policy, policy_set, raw, or manifest must be provided.
    - `policy` PdpPolicyRef
      - `policy_id` string, required: Public ID of the policy.
      - `version_id` string: Public ID of a specific policy version. When omitted, the draft is used. If no draft exists, returns 400.
      - `schema_version` string: Cedar schema version override (date string, e.g. "2026-03-16"). When omitted, uses the schema_version recorded on the resolved policy version or draft.
    - `policy_set` PdpPolicySetRef
      - `policy_set_id` string, required: Public ID of the policy set.
      - `version_id` string: Public ID of a specific policy set version. When omitted, the draft is used. If no draft exists, returns 400.
    - `raw` PdpRawPolicyInput
      - `cedar` string, required: Raw Cedar policy text. Can contain one or more policy statements. Converted to JSON before evaluation.
      - `schema_version` string, required: Cedar schema version to evaluate against.
      - `validate` boolean: When true, validate the converted policy against the schema before evaluation. Validation errors are returned as 400 with details. Set to false to skip validation and attempt evaluation directly.
    - `manifest` PdpInlinePolicySetManifest: Inline policy-set manifest used by the `manifest` variant of PolicySource. Mirrors the shape of a stored policy set version's manifest so a policy set under construction (no stored id/version) can be tested without being saved first. The `sha` field on each entry is ignored on input and recomputed server-side.
      - `entries` PdpPolicySetManifestEntry[], required
        - `policy_id` string, required
        - `policy_version_id` string, required
        - `sha` string: SHA-256 of the policy version content, populated by the server
      - `schema_version` string, required: Cedar schema version the entries are validated against.

## Response `200`

The evaluation result

- PdpPolicyEvaluationResponse
  - `decision` 'allow' | 'deny', required
  - `evaluation_status` 'complete' | 'partial'
  - `determining_policies` string[]: Raw Cedar policy IDs that determined the decision, of the form "<policy_version_id>::<cedar_key>", unioned across sub-checks. See `checks` for the resolved, human-readable form with per-check attribution.
  - `checks` PdpEvaluationCheck[]: Per-sub-check results, each with the policies that determined it. A simple request has one actor check; an on-behalf-of / impersonation request has a subject check and an actor check. The overall decision is deny-wins across these. Determining-policy names and policy-set version populate only when evaluating a minted policy set/version; raw text and drafts are structural.
    - `role` 'actor' | 'subject': actor = the requesting principal's access (or its right to act for the subject in an on-behalf-of flow); subject = the impersonated / delegated principal's own access.
    - `decision` 'allow' | 'deny'
    - `determining_policies` PdpDeterminingPolicyDetail[]
      - `policy_id` string: Public ID of the policy.
      - `policy_name` string: Human-readable policy name.
      - `rule_id` string: Cedar per-rule `@id` annotation that determined the decision (e.g. `limit-linear-scopes`). Falls back to the generated `policyN` key when the Cedar statement carries no `@id`.
      - `policy_version_id` string: Public ID of the policy version that was evaluated.
      - `policy_set_id` string: Public ID of the policy set the policy belongs to.
      - `policy_set_name` string: Human-readable policy set name.
      - `policy_set_version` integer: Version number of the policy set.
      - `effect` 'permit' | 'forbid'
  - `reason` string: Human-readable explanation of the decision, suitable for presenting to end users.
  - `diagnostics` PdpDiagnosticEntry[]
    - `policy_id` string
    - `message` string
  - `evaluated_at` string, date-time, required
  - `entity_snapshot` PdpEntitySnapshot
    - `principal` union
      - PdpUserSnapshot: Subset of the IAM User entity relevant to Cedar evaluation. All fields match the IAM management API User schema.
        - `type` 'user', required
        - `id` string, required: User public ID (same as IAM management API).
        - `email` string, required
        - `email_verified` boolean
      - PdpApplicationSnapshot: Subset of the IAM Application entity relevant to Cedar evaluation. All fields match the IAM management API Application schema.
        - `type` 'application', required
        - `id` string, required: Application public ID (same as IAM management API).
        - `name` string, required
        - `registration_method` 'managed' | 'dcr', required
        - `credential_type` string: Present only when resolved via credential lookup.
        - `dependencies` PdpResourceSnapshot[]: Resources this application depends on.
          - `id` string, required: Resource public ID (same as IAM management API).
          - `identifier` string, required
          - `name` string, required
          - `scopes` string[]
    - `resource` PdpResourceSnapshot: Subset of the IAM Resource entity relevant to Cedar evaluation. All fields match the IAM management API Resource schema.
      - `id` string, required: Resource public ID (same as IAM management API).
      - `identifier` string, required
      - `name` string, required
      - `scopes` string[]
    - `subject` union: Present when subject_type/subject_id were provided.
      - PdpUserSnapshot: Subset of the IAM User entity relevant to Cedar evaluation. All fields match the IAM management API User schema.
        - `type` 'user', required
        - `id` string, required: User public ID (same as IAM management API).
        - `email` string, required
        - `email_verified` boolean
      - PdpApplicationSnapshot: Subset of the IAM Application entity relevant to Cedar evaluation. All fields match the IAM management API Application schema.
        - `type` 'application', required
        - `id` string, required: Application public ID (same as IAM management API).
        - `name` string, required
        - `registration_method` 'managed' | 'dcr', required
        - `credential_type` string: Present only when resolved via credential lookup.
        - `dependencies` PdpResourceSnapshot[]: Resources this application depends on.
          - `id` string, required: Resource public ID (same as IAM management API).
          - `identifier` string, required
          - `name` string, required
          - `scopes` string[]
    - `context` object: The assembled Cedar context record.

## Other responses

- `400`: Bad Request - invalid input or validation error. Common causes: - Schema validation error (action/principal/resource doesn't exist in schema) - Entity not found (invalid principal_id, subject_id, or resource_id) - Policy source error (policy/policy set/version not found, draft doesn't exist) - Unsupported schema version - Invalid Cedar policy syntax (when using 'raw' source with validate=true)
- `401`: unauthorized error response when caller session is not authenticated
- `403`: forbidden error response when caller does not have permissions to a resource
- `429`: rate limit exceeded error response when caller has exhausted api limits for the given time period
- `500`: internal server error response when server encountered error of its own creation
- `503`: service unavailable error when server you're attempting to reach is not available
- `default`: internal server error response when server encountered error of its own creation

## Changes

- **2026-10-16** `0cfaff865771`: 14 breaking, 7 warning, 72 info
  - the response property `details/items/field` became optional for the status `400`
  - the response property `details/items/field` became optional for the status `401`
  - the response property `details/items/field` became optional for the status `403`
  - the response property `details/items/field` became optional for the status `429`
  - …89 more
- **2026-08-26** `d65d51379d93`: 2 info
  - added the new optional request property `authority_type`
  - added the optional property `checks/items/determining_policies/items/rule_id` to the response with the `200` status
- **2026-07-01** `2f5033ed4491`: 2 info
  - added the optional property `checks` to the response with the `200` status
  - added the optional property `reason` to the response with the `200` status
- **2026-06-17** `1a0dd4d857ee`: 2 info
  - added the new optional request property `context/claims/actor/issuer_claims`
  - added the new optional request property `context/claims/subject/issuer_claims`
- **2026-04-24** `fcab5a5e6cd0`: 1 info
  - added the new optional request property `policy_source/manifest`

[Operation history](https://skmtc.dev/keycardai/apis/keycard-ai-keycard-api/changes/zones/:zone_id/policy-evaluations/post.md)

---

[API](https://skmtc.dev/keycardai/apis/keycard-ai-keycard-api.md) - [All operations](https://skmtc.dev/keycardai/apis/keycard-ai-keycard-api/llms.txt) - [OpenAPI document](https://skmtc.dev/keycardai/apis/keycard-ai-keycard-api/revisions/0dee67e0a73a?raw)
