
# Renouveler une clé d'API

`POST /v1/api-keys/{key_id}:rotate` · autorisation `api-keys:write` · `Idempotency-Key` facultatif

Renouvelle une clé : crée une NOUVELLE clé avec le même nom, le même type, les mêmes autorisations et les mêmes `allowed_cidrs`, puis la renvoie. L'ancienne clé reste valide pendant `overlap_hours`, puis cesse de fonctionner.

- **Nouvelle clé.** La réponse décrit la nouvelle clé ; `rotated_from` est l'identifiant de l'ancienne clé et `key` contient la clé brute une seule fois (`Cache-Control: no-store`). Déployez-la, puis laissez l'ancienne clé expirer.
- **Chevauchement.** L'ancienne clé reçoit un `revoked_at` dans le futur et `revoke_reason: rotated` ; avec `overlap_hours: 0`, elle est révoquée immédiatement.
- **Pas d'élévation de privilèges.** Une clé ne peut pas renouveler une clé dont les autorisations dépassent les siennes, et une clé `restricted` ne peut pas renouveler une clé `secret`. La nouvelle clé ne peut pas expirer après la clé appelante, même lorsqu'une clé se renouvelle elle-même (prolongez une durée de vie dans le tableau de bord), et une clé appelante avec `allowed_cidrs` ne peut renouveler que des clés limitées à des réseaux inclus dans les siens. Une clé créée dans le tableau de bord, ainsi que chaque clé renouvelée à partir de celle-ci, ne peut être renouvelée que par elle-même ou dans le tableau de bord (`permission_escalation`). La nouvelle clé conserve le `created_by` de l'ancienne clé ; la clé qui effectue le renouvellement est consignée dans le journal d'audit.
- **Rejeu idempotent.** Un rejeu avec le même `Idempotency-Key` omet `key` et renvoie `secret_redacted: true`.

## Requête

| Paramètre | Dans | Description |
|---|---|---|
| `key_id` | chemin | Identifiant de la clé d'API (`key_…`). |

Corps :

Le corps est facultatif ; sans lui, toutes les valeurs par défaut s'appliquent.

| Champ | Type | Description |
|---|---|---|
| `overlap_hours` | entier | Facultatif, de 0 à 168, valeur par défaut 24. Nombre d'heures pendant lesquelles l'ancienne clé reste valide. |
| `expires_at` | chaîne (date-time) | Facultatif. Expiration de la NOUVELLE clé ; valeur par défaut : maintenant + 365 jours, au plus l'expiration de la clé appelante et au plus 730 jours. |

## Réponse

`200 OK` avec `Cache-Control: no-store`. L'objet de la NOUVELLE clé, accompagné de `key`.

```json
{
  "id": "key_0000000000000000000000001z",
  "name": "ci",
  "type": "restricted",
  "permissions": ["users:read"],
  "allowed_cidrs": [],
  "last4": "xxxx",
  "created_by": "key_…",
  "created_at": "2026-10-01T10:00:00Z",
  "expires_at": "2027-10-01T10:00:00Z",
  "last_used_at": null,
  "last_used_ip": null,
  "rotated_from": "key_…",
  "revoked_at": null,
  "revoke_reason": null,
  "key": "<shown once>"
}
```

## Erreurs

| HTTP | `code` | Quand |
|---|---|---|
| 401 | `unauthenticated` | La clé est absente, invalide ou révoquée. |
| 403 | `insufficient_permissions` | La clé ne dispose pas de l'autorisation requise. |
| 403 | `permission_escalation` | La requête donnerait à une clé plus d'autorisations, une plage réseau plus large ou une expiration plus lointaine que la clé appelante, une clé `restricted` tente de créer, renouveler ou révoquer au-delà de ses propres autorisations, ou une autre clé tente de renouveler ou révoquer une clé créée dans le tableau de bord. |
| 404 | `not_found` | La clé n'existe pas dans cet environnement. |
| 409 | `conflict` | La clé est déjà révoquée, expirée ou déjà renouvelée (non active). |
| 409 | `api_key_limit_reached` | L'environnement compte déjà le maximum de 50 clés actives. |
| 422 | `validation_failed` | Le corps est invalide : `overlap_hours` est en dehors de 0 à 168, ou `expires_at` est dans le passé ou à plus de 730 jours. |

## Exemple

```bash
curl -X POST "https://api.eu.keenauth.com/v1/api-keys/key_0000000000000000000000001z:rotate" \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"overlap_hours":24}'
```
