---
title: "Rotate an API key with an overlap window"
method: POST
path: "/api-keys/{api_key_id}/rotate"
tags: ["API Keys"]
---

# Rotate an API key with an overlap window

`POST /api-keys/{api_key_id}/rotate`

## Request

- Base URL: `https://developers.ozav.io/v2`
- URL: `https://developers.ozav.io/v2/api-keys/{api_key_id}/rotate`
- Auth: one of:
  - API key in header `X-API-Key`
  - HTTP bearer

Mints a successor key with identical scopes. The previous secret
remains valid for the overlap window (default 24 hours, maximum 7
days), then is revoked automatically. Live.

## Path parameters

- `api_key_id` string, required

## Request body

- object
  - `overlap_hours` integer: How long the previous secret stays valid after rotation, in hours (0-168; default 24). It is revoked automatically when the window elapses.

## Response `201`

Successor key; secret returned once.

- ApiKeyWithSecret: An API key's metadata - never its secret, which is shown only at creation and rotation.
  - `id` string, required: Opaque API-key identifier, prefixed `ozav_key_`.
  - `object` 'api_key', required: Resource type discriminator; always the literal `api_key`.
  - `name` string: Human-readable label you gave the key.
  - `key_prefix` string, required: Non-secret display prefix of the key (e.g. `ozav_sk_live_a1b2`) - enough to identify it without revealing the secret.
  - `environment` 'test' | 'live', required: Which environment the key operates against: - `test` - the sandbox; moves no real money. - `live` - production; can move real money.
  - `scopes` string[], required: The scopes granted to this key (intersected with the organization's entitlements at request time).
  - `role` 'admin' | 'operator' | 'viewer': The role this key was minted with, when it was minted with one. It is a label and a mint-time template - **not** part of the permission decision, which stays `entitlements ∩ scopes`. A rotated key keeps it. **Absent** on a key whose scopes were listed one by one, which is every key created before roles existed. The field is omitted rather than sent as `null`, because `null` here would read as "this key has no powers" instead of "this key was not minted from a template".
  - `last_used_at` string, date-time: When the key was last used to authenticate a request (RFC 3339 / ISO 8601, UTC).
  - `expires_at` string, date-time: When the key expires, if it has an expiry (e.g. an old secret's cutover time after a rotation).
  - `created_at` string, date-time: When the key was created (RFC 3339 / ISO 8601, UTC).
  - `secret` string: The full secret key; returned only on creation and rotation.

## Other responses

- `401`: Missing or invalid API key.
- `404`: The resource does not exist, is not visible to the caller, or the id was malformed for this position (see "Resource ids" under Errors). These share one status; `code` and `message` tell them apart.

---

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