---
title: "Create a draft policy version"
method: POST
path: "/api/v1/actions/{action_id}/policy-versions"
tags: ["canonical"]
---

# Create a draft policy version

`POST /api/v1/actions/{action_id}/policy-versions`

## Request

- Base URL: `https://app.graypass.org` (the document declares no server; this is the origin it was published from)
- URL: `https://app.graypass.org/api/v1/actions/{action_id}/policy-versions`
- Auth: HTTP bearer

Prepare a new immutable policy snapshot without activating it.

## Path parameters

- `action_id` string, required

## Request body

- PolicyVersionCreate: Create a draft policy. Omitted optional security settings inherit from the active version; activation is a separate operation.
  - `allowed_audiences` string[], nullable: Relying-party audience identifiers allowed to receive proofs for this action.
  - `allowed_callers` string[], nullable: Credential identifiers allowed to authorize this action. An empty list permits any eligible server credential in the same environment.
  - `context_schema` object, nullable: JSON Schema object applied to authorization context. Include every business value that must be bound to approval.
  - `proof_ttl_seconds` integer, nullable: Proof lifetime in seconds, measured from issuance; the accepted range is 30-900 seconds.
  - `requirements` PolicyRequirements, required: Requirements and refusal precedence applied by one immutable policy version.
    - `challenge_compensates` string[]: Evidence shortfalls a completed challenge may compensate: operator_continuity, human_presence, coverage and freshness by default. Positive attack indicators remain subject to hold/deny rules.
    - `challenge_methods` string[]: Permitted compensating methods; default passkey. sandbox_confirm is sandbox-only simulation.
    - `claims` object: Minimum status by claim name. The default requests operator_continuity at uncertain. Choose a requirement supported by the named claim.
    - `coverage_min` 'none' | 'sparse' | 'partial' | 'sufficient': Minimum accepted evidence coverage category; default partial.
    - `deny_on` string[]: Reason codes that force deny under this policy. Default empty list.
    - `explicit_approval_required` boolean: Whether action-bound explicit approval is required even if other evidence satisfies policy.
    - `freshness_max_ms` integer: Maximum acceptable evidence age in milliseconds; default 60000 (one minute).
    - `hold_on` string[]: Reason codes that force hold under this policy. Default empty list.
    - `insufficient_evidence` 'challenge' | 'hold' | 'deny': Decision used for insufficient evidence: challenge, hold or deny. Default challenge.
    - `max_challenges` integer: Maximum challenges in one request chain before escalation to hold; default 2.

## Response `201`

New immutable draft policy and its assigned version number.

- PolicyVersion: Immutable decision contract and its draft, active or retired lifecycle state.
  - `action` string, required: Identifier of the protected-action record owning this version.
  - `activated_at` string, nullable: Policy activation time as an ISO 8601 timestamp, or null for a draft.
  - `allowed_audiences` string[], required: Relying-party audience identifiers allowed to receive proofs for this action.
  - `allowed_callers` string[], required: Credential identifiers allowed to authorize this action. An empty list permits any eligible server credential in the same environment.
  - `content_hash` string, required: Digest of the immutable policy content; retain it when comparing policy configurations.
  - `context_schema` object, required: JSON Schema object applied to authorization context. Include every business value that must be bound to approval.
  - `created_at` string, required: Creation time as an ISO 8601 timestamp.
  - `id` string, required: Identifier of this record. Treat it as opaque and retain it for subsequent operations.
  - `proof_ttl_seconds` integer, required: Proof lifetime in seconds, measured from issuance; the accepted range is 30-900 seconds.
  - `requirements` PolicyRequirements, required: Requirements and refusal precedence applied by one immutable policy version.
    - `challenge_compensates` string[]: Evidence shortfalls a completed challenge may compensate: operator_continuity, human_presence, coverage and freshness by default. Positive attack indicators remain subject to hold/deny rules.
    - `challenge_methods` string[]: Permitted compensating methods; default passkey. sandbox_confirm is sandbox-only simulation.
    - `claims` object: Minimum status by claim name. The default requests operator_continuity at uncertain. Choose a requirement supported by the named claim.
    - `coverage_min` 'none' | 'sparse' | 'partial' | 'sufficient': Minimum accepted evidence coverage category; default partial.
    - `deny_on` string[]: Reason codes that force deny under this policy. Default empty list.
    - `explicit_approval_required` boolean: Whether action-bound explicit approval is required even if other evidence satisfies policy.
    - `freshness_max_ms` integer: Maximum acceptable evidence age in milliseconds; default 60000 (one minute).
    - `hold_on` string[]: Reason codes that force hold under this policy. Default empty list.
    - `insufficient_evidence` 'challenge' | 'hold' | 'deny': Decision used for insufficient evidence: challenge, hold or deny. Default challenge.
    - `max_challenges` integer: Maximum challenges in one request chain before escalation to hold; default 2.
  - `retired_at` string, nullable: Policy retirement time as an ISO 8601 timestamp, or null when not retired.
  - `status` 'draft' | 'active' | 'retired', required: Lifecycle state of this record; use the operation-specific values listed in the schema.
  - `version` integer, required: Monotonically assigned policy version number for the action.

## Other responses

- `422`: The canonical handler returns a Problem for invalid input; correct the request before retrying.

---

[API](https://skmtc.dev/graypass/apis/graypass-api.md) - [All operations](https://skmtc.dev/graypass/apis/graypass-api/llms.txt) - [OpenAPI document](https://skmtc.dev/graypass/apis/graypass-api/revisions/5f9ab64fdfdb?raw)
