---
title: "Update policy"
method: POST
path: "/v2/gateway.updatePolicy"
tags: ["gateway"]
---

# Update policy

`POST /v2/gateway.updatePolicy`

Update a single policy in place without resending the environment's full
policy list. The policy keeps its id and its position in the evaluation
order, and all other policies are untouched.

Omitted fields keep their stored values; at least one updatable field
must be provided. Setting `match` to null removes all match expressions
so the policy applies to every request. Providing one of `keyauth`,
`ratelimit`, `firewall` or `openapi` replaces the policy's rule
entirely, including switching its type; at most one may be set.

Policy ids are regenerated whenever `gateway.setPolicies` replaces the
list, so fetch current ids via `gateway.listPolicies` first.

**Required Permissions**

Your root key must have one of the following permissions:
- `environment.*.update_policy` (for any environment)
- `environment.<environment_id>.update_policy` (for a specific environment)

## Request body

- V2GatewayUpdatePolicyRequestBody — Partial update of a single policy. Omitted fields keep their stored values; at least one updatable field must be provided. Providing one of `keyauth`, `ratelimit`, `firewall` or `openapi` replaces the policy's rule entirely, including switching its type; at most one may be set.
  - `project` string, required — Identifies a resource by either its unique ID or its slug. Accepts a prefixed ID (such as 'proj_' or 'app_') or a slug.
  - `app` string, required — Identifies a resource by either its unique ID or its slug. Accepts a prefixed ID (such as 'proj_' or 'app_') or a slug.
  - `environment` string, required — Identifies a resource by either its unique ID or its slug. Accepts a prefixed ID (such as 'proj_' or 'app_') or a slug.
  - `policyId` string, required — Id of the policy to update, as returned by `gateway.listPolicies`. Ids are regenerated whenever `gateway.setPolicies` replaces the list, so list the policies first if you are unsure the id is current.
  - `name` string — New human-readable name. Omit to keep the current name.
  - `enabled` boolean — Enable or disable the policy. Disabled policies are stored but skipped during evaluation. Omit to keep the current setting.
  - `match` MatchExpr[], nullable — Replaces all match expressions. Set null to remove them so the policy applies to every request. Omit to keep the current expressions.
    - `path` PathMatch — Matches on the request path.
      - `path` StringMatch, required — String matcher. Exactly one of `exact`, `prefix` or `regex` must be set.
        - `exact` string — Matches when the input equals this value.
        - `prefix` string — Matches when the input starts with this value.
        - `regex` string — Matches when the input satisfies this RE2 regular expression. Invalid patterns are rejected when the policy is created.
        - `ignoreCase` boolean — Compare case-insensitively. May accompany any match mode.
    - `method` MethodMatch — Matches when the request method is one of the listed methods.
      - `methods` string[], required
    - `header` FieldMatch — Matches a named request field (header or query parameter). Exactly one of `present` or `value` must be set.
      - `name` string, required
      - `present` true — Matches when the field is present, regardless of value.
      - `value` StringMatch — String matcher. Exactly one of `exact`, `prefix` or `regex` must be set.
        - `exact` string — Matches when the input equals this value.
        - `prefix` string — Matches when the input starts with this value.
        - `regex` string — Matches when the input satisfies this RE2 regular expression. Invalid patterns are rejected when the policy is created.
        - `ignoreCase` boolean — Compare case-insensitively. May accompany any match mode.
    - `queryParam` FieldMatch — Matches a named request field (header or query parameter). Exactly one of `present` or `value` must be set.
      - `name` string, required
      - `present` true — Matches when the field is present, regardless of value.
      - `value` StringMatch — String matcher. Exactly one of `exact`, `prefix` or `regex` must be set.
        - `exact` string — Matches when the input equals this value.
        - `prefix` string — Matches when the input starts with this value.
        - `regex` string — Matches when the input satisfies this RE2 regular expression. Invalid patterns are rejected when the policy is created.
        - `ignoreCase` boolean — Compare case-insensitively. May accompany any match mode.
  - `keyauth` KeyauthPolicy — Verifies Unkey API keys on matching requests.
    - `keyspaces` string[], required — Keyspaces to verify keys against, referenced by id. All keyspaces must belong to your workspace.
    - `locations` KeyLocation[] — Where to look for the key on incoming requests, tried in order. Defaults to the `Authorization Bearer` header when omitted.
      - `bearer` BearerTokenLocation — Extract the key from the `Authorization Bearer` header.
      - `header` HeaderKeyLocation — Extract the key from a custom header.
        - `name` string, required
        - `stripPrefix` string — Optional prefix removed from the header value before verification.
      - `queryParam` QueryParamKeyLocation — Extract the key from a query parameter.
        - `name` string, required
    - `permissionQuery` string — Optional permission query the verified key must satisfy, e.g. `documents.read AND documents.write`.
    - `ratelimits` KeyRatelimit[] — Rate limits applied during key verification.
      - `name` string, required — Name of a rate limit configured on the key or its identity, or the name of the inline override defined by `limit` and `duration`.
      - `limit` integer — Inline override: maximum number of operations per window. Must be set together with `duration`.
      - `duration` integer — Inline override: window duration in milliseconds. Must be set together with `limit`.
      - `cost` integer — Cost charged against the limit per request. Defaults to 1.
  - `ratelimit` RatelimitPolicy — Rate limits matching requests.
    - `limit` integer, required — Maximum number of requests per window.
    - `windowMs` integer, required — Window duration in milliseconds.
    - `identifier` RatelimitIdentifier, required — How requests are grouped for rate limiting. Exactly one of `remoteIp`, `header`, `authenticatedSubject`, `path` or `principalField` must be set.
      - `remoteIp` RemoteIpKey — Rate limit by the client's IP address.
      - `header` HeaderKey — Rate limit by the value of a request header.
        - `name` string, required
      - `authenticatedSubject` AuthenticatedSubjectKey — Rate limit by the authenticated subject (e.g. the verified key).
      - `path` PathKey — Rate limit by the request path.
      - `principalField` PrincipalFieldKey — Rate limit by a field extracted from the authenticated principal.
        - `path` string, required
  - `firewall` FirewallPolicy — Blocks matching requests.
    - `action` 'ACTION_DENY', required — What to do with matching requests.
  - `openapi` OpenapiPolicy — Validates matching requests against the app's uploaded OpenAPI spec. Has no configuration of its own. If no spec has been uploaded for the deployment, the policy is a no-op and requests pass through unvalidated.

## Response `200`

Successfully updated the policy.

- V2GatewayUpdatePolicyResponseBody
  - `meta` Meta, required — Metadata object included in every API response. This provides context about the request and is essential for debugging, audit trails, and support inquiries. The `requestId` is particularly important when troubleshooting issues with the Unkey support team.
    - `requestId` string, required — A unique id for this request. Always include this ID when contacting support about a specific API request. This identifier allows Unkey's support team to trace the exact request through logs and diagnostic systems to provide faster assistance.
  - `data` EmptyResponse, required — Empty response object by design. A successful response indicates this operation was successfully executed.

## Other responses

- `400` — Bad request
- `401` — Unauthorized
- `403` — Forbidden - Insufficient permissions (requires `environment.*.update_policy`)
- `404` — Not Found - The environment, policy, or a referenced keyspace does not exist in your workspace
- `429` — Too Many Requests
- `500` — Internal server error

---

[API](https://skmtc.net/unkeyed/apis/unkey-api.md) · [All operations](https://skmtc.net/unkeyed/apis/unkey-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/unkeyed/unkey-api/revisions/4bd11a7252bc/schema)
