---
title: "Replace a policy."
method: PUT
path: "/api/policies/{policyName}"
tags: ["Policies"]
---

# Replace a policy.

`PUT /api/policies/{policyName}`

## Request

- Base URL: `/` (relative, and the document was published on a file host, not at the API’s origin)
- URL: `/api/policies/{policyName}`
- Auth: HTTP bearer

Replaces an existing policy with the request body, as a new revision. The policy is validated before it is stored. Its description and notes are kept unless the body gives them. To set the description and notes in the same write, pass details=true and send {"policy": <the policy>, "description": "...", "notes": "..."}; description and notes are optional, a field left out or null is left as it is, and an empty value clears it. Without details=true the body is the policy itself. Send the ETag from your read in If-Match to make the write conditional: if the policy, its description, or its notes changed since, nothing is written and the response is 409 with reason policy_changed. Without If-Match the write is not checked against an earlier read. Admins may replace another user's policy by passing that user's username as owner. Requires the `policies:write` scope.

## Path parameters

- `policyName` string, required

## Query parameters

- `owner` string
- `details` boolean

## Headers

- `Authorization` string, required
- `If-Match` string

## Request body

- object: Native Phileas policy. identifiers is required; custom dictionaries use dictionaries.

## Response `200`

The policy was replaced and is now active. The ETag header identifies it as written. A policy_activated audit event is recorded.

## Other responses

- `400`: The policy is invalid, the request has a description or notes parameter, If-Match is not an entity tag this API returned, or, with details=true, the body is not a policy with details or the description or notes are too long.
- `401`: The Authorization header is absent or the API key is not recognized.
- `403`: Insufficient scope, disabled API, or access denied.
- `404`: There is no such policy, with a message. Also returned, saying only not found, when the owner does not exist or the caller may not reach it, so an owner value cannot be used to discover accounts.
- `406`: No representation matches Accept.
- `409`: The policy was not replaced, and reason says why: policy_managed (a managed policy, which cannot be replaced) or policy_changed (it changed since the read If-Match names, or concurrently; read it again and retry). Nothing was written.
- `413`: Content Too Large
- `415`: Unsupported Media Type
- `500`: Internal Server Error
- `503`: Service Unavailable

## Changes

- **2026-10-11** `adb70fdccccb`: 2 info
  - added the new optional `header` request parameter `If-Match`
  - added the new optional `query` request parameter `details`
- **2026-10-10** `c4f85daa9208`: 14 info
  - added the optional property `field` to the response with the `400` status
  - added the optional property `field` to the response with the `401` status
  - added the optional property `field` to the response with the `404` status
  - added the optional property `field` to the response with the `413` status
  - …10 more
- **2026-10-06** `1d78dd354641`: 2 warning
  - deleted the `query` request parameter `description`
  - deleted the `query` request parameter `notes`
- **2026-10-06** `a35e2c11efff`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/philterd/apis/philter-api/changes/api/policies/:policyName/put.md)

---

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