Skip to content

POST /v1/keys/{id}/rotate

Call POST /v1/keys/{id}/rotate
Price free
Scope keys:manage
Operation id rotateKey

Create a replacement key with the same scopes and limits; the old key keeps working for grace_period_hours (default 24) and then stops. The new secret is shown once. Audited. Free. Scope: keys:manage.

Copy it as curl. Set VERDICT_API_KEY first; uuidgen makes a fresh Idempotency-Key.

Request
curl -X POST 'https://api.askverdict.io/v1/keys/key_01JC3Z4Y8R9K2M5N7P1Q3S5T7V/rotate' \
-H "Authorization: Bearer $VERDICT_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H 'Content-Type: application/json' \
-d '{
"grace_period_hours": 24
}'

201: The replacement key and the old key’s grace window.

201 response
{
"key": {
"id": "key_01JC3Z4Y8R9K2M5N7P1Q3S5T7V",
"project_id": "prj_01JC3Z4Y8R9K2M5N7P1Q3S5T7V",
"name": "outbound-agent prod",
"environment": "live",
"prefix": "vd_live_Ab12Cd",
"scopes": [
"decisions:write",
"index:read",
"outcomes:write"
],
"status": "active",
"rate_limit_per_minute": 600,
"daily_spend_cap_usd": 25,
"ip_allowlist": [],
"expires_at": null,
"last_used_at": null,
"created_at": "2026-11-07T14:00:00Z",
"secret": "vd_live_<shown-once>"
},
"previous_key": {
"id": "key_01JC3Z4Y8R9K2M5N7P1Q3S5T7W",
"valid_until": "2026-11-08T14:00:00Z"
}
}
Name In Type Required Description
id path string yes The key id.
idempotency-key header string (uuid) yes A UUID you generate per logical request. Required on every POST. Repeating it within 24 hours returns the stored response and bills nothing; reusing it with a different body returns 409 idempotency_conflict.
x-verdict-version header string no API version to use, a date. Defaults to the version current when the key was created. The current version is 2026-11-01.

Schema RotateKeyRequest. Rotation options.

Field Type Required Description
grace_period_hours integer no Hours the old key stays valid; default 24.

Schema RotateKeyResponse.

Field Type Required Description
key CreatedApiKey yes A new API key with its secret (shown once).
key.id string yes The key id.
key.project_id string yes Project the key belongs to.
key.name string yes Name.
key.environment enum: “live”, “test” yes live or test.
key.prefix string yes The key’s first characters, to recognize it.
key.scopes array of enum: “decisions:write”, “index:read”, “outcomes:write”, “watches:manage”, “vendors:call”, “account:read”, “account:manage”, “keys:manage” yes Scopes granted.
key.status enum: “active”, “rotating”, “revoked”, “expired” yes Lifecycle status.
key.rate_limit_per_minute integer yes Requests per minute allowed.
key.daily_spend_cap_usd number or null yes Daily spend cap, or null for none. US dollars, up to 6 decimals.
key.ip_allowlist array of string yes CIDR blocks the key may be used from; empty means anywhere.
key.expires_at string or null (date-time) yes Expiry, or null for none.
key.last_used_at string or null (date-time) yes Last successful use, or null.
key.created_at string (date-time) yes When the key was created.
key.secret string yes The API key: vd_live_ or vd_test_ plus a base62 body. Shown once; store it now.
previous_key object yes The old key and the end of its grace window.
previous_key.id string yes The rotated key.
previous_key.valid_until string (date-time) yes When the old key stops working.

Errors are RFC 9457 problem details and are never billed. Branch on type. See Errors.

Status Meaning
400 Invalid request: malformed JSON, an unknown field, a failed constraint or a size limit (invalid_request).
401 Missing, malformed, revoked or expired API key, or a bad webhook signature (unauthorized).
403 The key lacks the scope this operation needs (forbidden_scope).
404 The resource does not exist in this organization (not_found).
409 The Idempotency-Key was reused with a different request, or the first request is still running (idempotency_conflict).
429 Rate limited (rate_limited). Wait Retry-After seconds.
500 Unexpected server error (internal). Not billed; retry with the same Idempotency-Key.

Open the interactive reference to send this request from the browser. The full document is at /openapi.json.