---
title: "Rotate Issued API Key"
method: POST
path: "/v2alpha1/admin/issuedApiKeys/{key_id}:rotate"
tags: ["ApiKeys"]
---

# Rotate Issued API Key

`POST /v2alpha1/admin/issuedApiKeys/{key_id}:rotate`

Generates a new secret for an issued API key. Creates a new API key with a
new key_id and secret, and immediately revokes the old key. This is the
recommended way to update scopes, metadata, or rotate credentials.

For zero-downtime rotation, use this workflow instead:
  1. IssueApiKey with new credentials
  2. Deploy new secret to all services
  3. Verify new secret works everywhere
  4. AdminRevokeIssuedApiKey to remove the old key

```http
POST /v2alpha1/admin/issuedApiKeys/01HQZX9VYQKJB8XQZQXQZQXQXQ:rotate
{
  "scopes": ["read"]
}
```

## Path parameters

- `key_id` string, required

## Request body

- AdminRotateIssuedApiKeyBody — RotateIssuedApiKeyRequest is the request for AdminRotateIssuedApiKey. Rotation is a custom method (AIP-136) that swaps an active key for a new one with a fresh secret and key_id, then revokes the old key. It is not a partial update, so it does not carry an update_mask. Mutable fields use presence-based semantics: an absent field inherits from the old key, while a present field (including an explicitly empty value) overrides.
  - `ip_restriction` IPRestriction — IPRestriction defines IP-based access controls for an API key. When allowed_cidrs is non-empty, only requests from IPs matching at least one CIDR range are permitted. Empty allowed_cidrs means no IP restriction (all IPs allowed). Derived tokens (JWT/macaroon) inherit the parent key's CIDR allowlist: the restriction is sealed into the token at derivation and re-enforced on every verification.
    - `allowed_cidrs` string[] — allowed_cidrs is a list of CIDR ranges that are allowed to use this key. Supports both IPv4 (e.g., "10.0.0.0/8") and IPv6 (e.g., "2001:db8::/32"). If empty, all IPs are allowed (no restriction).
  - `metadata` object — metadata for the new API key. Absent (nil) inherits from the old key; present (including empty Struct) overrides.
  - `name` string — name for the new API key. Absent (HasName() == false) inherits from the old key; present (including empty string) overrides.
  - `rate_limit_policy` RateLimitPolicy — RateLimitPolicy describes the rate limit policy for an API key. In OSS mode, this policy is informational and meant to be consumed by upstream gateways (Envoy, Cloudflare, etc.) for enforcement. In commercial mode, Talos enforces rate limits using in-memory or Redis backends, both using the GCRA (Generic Cell Rate Algorithm). Compliant with draft-ietf-httpapi-ratelimit-headers-10.
    - `quota` string, int64 — quota is the number of requests allowed per window.
    - `unit` string
    - `window` string — window is the time window for the quota. Common values: 60s (1 minute), 3600s (1 hour), 86400s (1 day).
  - `scopes` string[] — scopes for the new API key. Absent (nil slice) inherits from the old key; present (including empty list) overrides.
  - `visibility` 'KEY_VISIBILITY_UNSPECIFIED' | 'KEY_VISIBILITY_SECRET' | 'KEY_VISIBILITY_PUBLIC' — KeyVisibility distinguishes public (client-safe) keys from secret (server-only) keys. Public keys use a different configurable prefix for visual distinction. Both types share the same scope/permission system — visibility is about exposure safety. - KEY_VISIBILITY_UNSPECIFIED: Treated as SECRET

## Response `200`

A successful response.

- RotateIssuedApiKeyResponse
  - `issued_api_key` IssuedApiKey — IssuedApiKey represents an API key issued (generated) by Talos. Root keys are opaque v1 format tokens stored in the database. Derived tokens (JWT/Macaroon) are created via DeriveToken and are stateless (not stored).
    - `actor_id` string
    - `create_time` string, date-time
    - `expire_time` string, date-time
    - `ip_restriction` IPRestriction — IPRestriction defines IP-based access controls for an API key. When allowed_cidrs is non-empty, only requests from IPs matching at least one CIDR range are permitted. Empty allowed_cidrs means no IP restriction (all IPs allowed). Derived tokens (JWT/macaroon) inherit the parent key's CIDR allowlist: the restriction is sealed into the token at derivation and re-enforced on every verification.
      - `allowed_cidrs` string[] — allowed_cidrs is a list of CIDR ranges that are allowed to use this key. Supports both IPv4 (e.g., "10.0.0.0/8") and IPv6 (e.g., "2001:db8::/32"). If empty, all IPs are allowed (no restriction).
    - `key_id` string
    - `last_used_time` string, date-time
    - `metadata` object — metadata is a free-form JSON object for caller-defined attributes (e.g., source, environment, tags). Values may be strings, numbers, booleans, arrays, objects, or null. Total serialized size is capped at 4KB. AIP-148 metadata field.
    - `name` string
    - `rate_limit_policy` RateLimitPolicy — RateLimitPolicy describes the rate limit policy for an API key. In OSS mode, this policy is informational and meant to be consumed by upstream gateways (Envoy, Cloudflare, etc.) for enforcement. In commercial mode, Talos enforces rate limits using in-memory or Redis backends, both using the GCRA (Generic Cell Rate Algorithm). Compliant with draft-ietf-httpapi-ratelimit-headers-10.
      - `quota` string, int64 — quota is the number of requests allowed per window.
      - `unit` string
      - `window` string — window is the time window for the quota. Common values: 60s (1 minute), 3600s (1 hour), 86400s (1 day).
    - `revocation_description` string — revocation_description provides free-form context for a revocation. Only set when revocation_reason is PRIVILEGE_WITHDRAWN. JSON API change: field was formerly revocation_reason_text. Field number 13 is unchanged so the change is wire-compatible for binary proto encoding.
    - `revocation_reason` 'REVOCATION_REASON_UNSPECIFIED' | 'REVOCATION_REASON_KEY_COMPROMISE' | 'REVOCATION_REASON_AFFILIATION_CHANGED' | 'REVOCATION_REASON_SUPERSEDED' | 'REVOCATION_REASON_PRIVILEGE_WITHDRAWN' — RevocationReason provides structured revocation reasons inspired by RFC 5280. Used in both admin and self-revocation flows. - REVOCATION_REASON_UNSPECIFIED: Default zero value. Use a specific reason; UNSPECIFIED is rejected by admin and self-revocation endpoints. - REVOCATION_REASON_KEY_COMPROMISE: The key was leaked or believed to be in the hands of an unauthorized party. - REVOCATION_REASON_AFFILIATION_CHANGED: The owning actor's relationship with the issuer changed (e.g., role change, departure). - REVOCATION_REASON_SUPERSEDED: A new key has replaced this one as part of a rotation. - REVOCATION_REASON_PRIVILEGE_WITHDRAWN: Admin-only. The actor's privilege to use this key was withdrawn by an operator. Self-revocation requests using this reason are rejected with InvalidArgument. Pair with `description` on the admin revoke requests to record the operator-supplied justification.
    - `scopes` string[]
    - `status` 'KEY_STATUS_UNSPECIFIED' | 'KEY_STATUS_ACTIVE' | 'KEY_STATUS_REVOKED' | 'KEY_STATUS_EXPIRED' — KeyStatus represents the lifecycle state of an API key. - KEY_STATUS_UNSPECIFIED: Default zero value. Never returned by the server. Treated as ACTIVE for backward compatibility but should not be relied on. - KEY_STATUS_ACTIVE: The key is valid and can be used to authenticate. - KEY_STATUS_REVOKED: The key was revoked. Verification fails with VERIFICATION_ERROR_REVOKED. See revocation_reason for the cause. - KEY_STATUS_EXPIRED: The key passed its expire_time. Verification fails with VERIFICATION_ERROR_EXPIRED. The transition is computed at read time and not persisted.
    - `update_time` string, date-time
    - `visibility` 'KEY_VISIBILITY_UNSPECIFIED' | 'KEY_VISIBILITY_SECRET' | 'KEY_VISIBILITY_PUBLIC' — KeyVisibility distinguishes public (client-safe) keys from secret (server-only) keys. Public keys use a different configurable prefix for visual distinction. Both types share the same scope/permission system — visibility is about exposure safety. - KEY_VISIBILITY_UNSPECIFIED: Treated as SECRET
  - `old_issued_api_key` IssuedApiKey — IssuedApiKey represents an API key issued (generated) by Talos. Root keys are opaque v1 format tokens stored in the database. Derived tokens (JWT/Macaroon) are created via DeriveToken and are stateless (not stored).
    - `actor_id` string
    - `create_time` string, date-time
    - `expire_time` string, date-time
    - `ip_restriction` IPRestriction — IPRestriction defines IP-based access controls for an API key. When allowed_cidrs is non-empty, only requests from IPs matching at least one CIDR range are permitted. Empty allowed_cidrs means no IP restriction (all IPs allowed). Derived tokens (JWT/macaroon) inherit the parent key's CIDR allowlist: the restriction is sealed into the token at derivation and re-enforced on every verification.
      - `allowed_cidrs` string[] — allowed_cidrs is a list of CIDR ranges that are allowed to use this key. Supports both IPv4 (e.g., "10.0.0.0/8") and IPv6 (e.g., "2001:db8::/32"). If empty, all IPs are allowed (no restriction).
    - `key_id` string
    - `last_used_time` string, date-time
    - `metadata` object — metadata is a free-form JSON object for caller-defined attributes (e.g., source, environment, tags). Values may be strings, numbers, booleans, arrays, objects, or null. Total serialized size is capped at 4KB. AIP-148 metadata field.
    - `name` string
    - `rate_limit_policy` RateLimitPolicy — RateLimitPolicy describes the rate limit policy for an API key. In OSS mode, this policy is informational and meant to be consumed by upstream gateways (Envoy, Cloudflare, etc.) for enforcement. In commercial mode, Talos enforces rate limits using in-memory or Redis backends, both using the GCRA (Generic Cell Rate Algorithm). Compliant with draft-ietf-httpapi-ratelimit-headers-10.
      - `quota` string, int64 — quota is the number of requests allowed per window.
      - `unit` string
      - `window` string — window is the time window for the quota. Common values: 60s (1 minute), 3600s (1 hour), 86400s (1 day).
    - `revocation_description` string — revocation_description provides free-form context for a revocation. Only set when revocation_reason is PRIVILEGE_WITHDRAWN. JSON API change: field was formerly revocation_reason_text. Field number 13 is unchanged so the change is wire-compatible for binary proto encoding.
    - `revocation_reason` 'REVOCATION_REASON_UNSPECIFIED' | 'REVOCATION_REASON_KEY_COMPROMISE' | 'REVOCATION_REASON_AFFILIATION_CHANGED' | 'REVOCATION_REASON_SUPERSEDED' | 'REVOCATION_REASON_PRIVILEGE_WITHDRAWN' — RevocationReason provides structured revocation reasons inspired by RFC 5280. Used in both admin and self-revocation flows. - REVOCATION_REASON_UNSPECIFIED: Default zero value. Use a specific reason; UNSPECIFIED is rejected by admin and self-revocation endpoints. - REVOCATION_REASON_KEY_COMPROMISE: The key was leaked or believed to be in the hands of an unauthorized party. - REVOCATION_REASON_AFFILIATION_CHANGED: The owning actor's relationship with the issuer changed (e.g., role change, departure). - REVOCATION_REASON_SUPERSEDED: A new key has replaced this one as part of a rotation. - REVOCATION_REASON_PRIVILEGE_WITHDRAWN: Admin-only. The actor's privilege to use this key was withdrawn by an operator. Self-revocation requests using this reason are rejected with InvalidArgument. Pair with `description` on the admin revoke requests to record the operator-supplied justification.
    - `scopes` string[]
    - `status` 'KEY_STATUS_UNSPECIFIED' | 'KEY_STATUS_ACTIVE' | 'KEY_STATUS_REVOKED' | 'KEY_STATUS_EXPIRED' — KeyStatus represents the lifecycle state of an API key. - KEY_STATUS_UNSPECIFIED: Default zero value. Never returned by the server. Treated as ACTIVE for backward compatibility but should not be relied on. - KEY_STATUS_ACTIVE: The key is valid and can be used to authenticate. - KEY_STATUS_REVOKED: The key was revoked. Verification fails with VERIFICATION_ERROR_REVOKED. See revocation_reason for the cause. - KEY_STATUS_EXPIRED: The key passed its expire_time. Verification fails with VERIFICATION_ERROR_EXPIRED. The transition is computed at read time and not persisted.
    - `update_time` string, date-time
    - `visibility` 'KEY_VISIBILITY_UNSPECIFIED' | 'KEY_VISIBILITY_SECRET' | 'KEY_VISIBILITY_PUBLIC' — KeyVisibility distinguishes public (client-safe) keys from secret (server-only) keys. Public keys use a different configurable prefix for visual distinction. Both types share the same scope/permission system — visibility is about exposure safety. - KEY_VISIBILITY_UNSPECIFIED: Treated as SECRET
  - `secret` string

## Other responses

- `201` — API key rotated successfully. New key issued, old key revoked.
- `default` — An unexpected error response.

---

[API](https://skmtc.net/ory/apis/ory-talos-api.md) · [All operations](https://skmtc.net/ory/apis/ory-talos-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/ory/ory-talos-api/versions/faeb5ce56780/schema)
