---
title: Rotation
path: reference/rotation
status: published
---

# Rotation Reference

Endpoint reference for rotation policies and schedules. For the guide, see [Rotation Policies](../api-guides/rotation). For the model, see [Rotation](../core-concepts/rotation).

**Base path:** `/v1/rotation/`

## GET /v1/rotation/policies

List rotation policies.

Query: `active_only`, `limit`, `cursor`.

Response:

```json
{
  "data": [
    {
      "id": "rot_quarterly",
      "name": "quarterly",
      "interval": "90d",
      "interval_seconds": 7776000,
      "grace_period": "48h",
      "auto_generate": false,
      "is_active": true,
      "secrets_count": 15
    }
  ],
  "cursor": null,
  "has_more": false
}
```

**Scope:** `admin`.

## POST /v1/rotation/policies

Create.

Body:

| Field | Required | Description |
|-------|----------|-------------|
| `name` | Yes | Tenant-unique |
| `interval` | Yes | Duration (`90d`, `7d`, `24h`) |
| `description` | No | |
| `grace_period` | No | Default `48h` |
| `warn_before` | No | Comma-separated durations before rotation |
| `auto_generate` | No | Default `false` |
| `secret_policy_id` | No | Value-generation policy |
| `webhook_ids` | No | Webhooks to notify |

**Scope:** `admin`.

## GET /v1/rotation/policies/{id}

**Scope:** `admin`.

## PATCH /v1/rotation/policies/{id}

Partial update.

**Scope:** `admin`.

## DELETE /v1/rotation/policies/{id}

Delete. Attached secrets are detached.

**Scope:** `admin`.

## POST /v1/rotation/policies/{id}/enable

Enable a paused policy.

**Scope:** `admin`.

## POST /v1/rotation/policies/{id}/disable

Pause without detaching secrets.

**Scope:** `admin`.

## POST /v1/rotation/policies/{id}/secrets

Assign a secret to the policy.

Body: `{"secret_path": "..."}`.

Response `201 Created`: `SecretAssignment` object.

**Scope:** `admin`.

## DELETE /v1/rotation/policies/{id}/secrets/{secret_path}

Detach a secret (path URL-encoded).

**Scope:** `admin`.

## POST /v1/rotation/policies/{id}/rotate

Trigger rotation for the policy.

Body (optional): `{"secret_paths": ["..."]}` to scope to specific paths.

Response: array of `RotationHistoryItem`.

**Scope:** `secrets:rotate`.

## GET /v1/rotation/policies/{id}/history

List rotation events.

Query: `status` (`success`|`failed`|`pending`), `limit`, `cursor`.

Response:

```json
{
  "data": [
    {
      "id": "rh_abc",
      "policy_id": "rot_quarterly",
      "secret_path": "...",
      "status": "success",
      "old_version": 3,
      "new_version": 4,
      "rotated_at": "2026-04-23T00:00:00Z",
      "rotated_by": "system:rotation-scheduler"
    }
  ],
  "has_more": false
}
```

**Scope:** `audit:read`.

## GET /v1/rotation/due

Secrets due for rotation.

Query: `within_hours` (default 24), `include_overdue` (default true), `policy_id`.

Response:

```json
{
  "secrets": [
    {
      "path": "...",
      "policy_id": "rot_quarterly",
      "policy_name": "quarterly",
      "next_rotation_at": "2026-04-30T00:00:00Z",
      "is_overdue": false
    }
  ]
}
```

**Scope:** `secrets:rotate` or `admin`.

## GET /v1/rotation/pending

Deprecated alias for `/v1/rotation/due`. Same response shape.

## Secret policies (value generation)

### GET /v1/secret-policies

List.

### POST /v1/secret-policies

Create a value-generation policy (length, charset, require classes).

### GET /v1/secret-policies/{id}

### PATCH /v1/secret-policies/{id}

### DELETE /v1/secret-policies/{id}

Attach via `secret_policy_id` on a rotation policy or on a secret's `options`.

## Related

- [Rotation Policies](../api-guides/rotation)
- [Rotation (Concepts)](../core-concepts/rotation)
- [Events and Webhooks](../core-concepts/events-and-webhooks)
