
# Mettre à jour une API

`PATCH /v1/apis/{api_id}` · permission `apis:write`

Met à jour une API avec un correctif de fusion JSON (RFC 7396, `application/merge-patch+json`) : les champs que vous envoyez changent, les champs omis restent. `If-Match` est obligatoire. `key` et `identifier` ne peuvent pas changer après la création, et l'API système ne peut pas être modifiée. Un correctif qui ne change rien n'écrit rien et conserve la version.

## Demande

| Paramètre | Dans | Description |
|---|---|---|
| `api_id` | path | L'identifiant de l'API. |
| `If-Match` | header | L'`ETag` de la dernière lecture (obligatoire). |

Corps : tout champ writable ci-dessous (tous optionnels). Un champ ne peut pas être supprimé avec `null`.

| Champ | Type | Obligatoire | Description |
|---|---|---|---|
| `key` | string | non | Clé de configuration stable, `^[a-z0-9_-]{1,64}$`. Immuable. |
| `identifier` | string | non | Public cible du jeton : une URL https (sans requête ni fragment) ou `urn:<nid>:<nss>` ; stockée sous forme canonique. Immuable. L'espace de noms `urn:idp:` est réservé. |
| `name` | string | non | 1-128 caractères. |
| `access_token_lifetime_s` | integer | non | 60-86400. Par défaut 3600 (600 avec `mcp_profile`). |
| `token_format` | string | non | `jwt` (par défaut) ou `opaque`. |
| `rbac_mode` | string | non | Mode par lequel les rôles et permissions atteignent le jeton : `claims` (par défaut) ajoute `permissions` et `org_permissions` ; `off` n'ajoute aucun des deux (`org_roles` est toujours ajouté) ; `enforce` les ajoute et limite en plus les scopes accordés aux permissions effectives de l'utilisateur. |
| `allow_offline_access` | boolean | non | Par défaut `true`. |
| `require_resource_indicator` | boolean | non | Par défaut `false` (`true` avec `mcp_profile`). |
| `dpop_required` | boolean | non | Par défaut `false`. |
| `mcp_profile` | boolean | non | Nécessite un `identifier` https et `require_resource_indicator: true`. |
| `first_party_access` | string | non | `all` (par défaut) ou `granted_only`. |
| `introspection_applications` | array | non | Applications (`app_…`) pouvant introspect les jetons de cette API, au maximum 50, pas de doublons. Uniquement des applications `web` et `m2m` du même environnement. La liste est remplacée en tant que tout ; `[]` la vide, `null` est refusé. |

### Applications d'introspection

Le point de terminaison d'introspection (`POST <issuer>/oauth2/introspect`, RFC 7662) répond `active: true` pour un jeton d'accès uniquement à deux appelants : l'application à laquelle le jeton a été émis, ou une application dans la liste `introspection_applications` de l'API nommée dans le `aud` du jeton. Tous les autres appelants reçoivent `active: false`, de sorte que les API ne peuvent pas lire les jetons les uns des autres. Seules les applications confidentielles (`web`, `m2m`) du même environnement peuvent être répertoriées ; la liste est stockée sous forme d'ensemble et renvoyée dans l'ordre des identifiants. Une application suspendue reste sur la liste mais ne peut pas introspect. La liste de l'API système ne peut pas être écrite.

## Réponse

`200 OK` avec le nouvel `ETag` :

```json
{
  "id": "api_01h455vb4pex5vsknk084sn02q",
  "key": "orders",
  "identifier": "https://api.example.com/orders",
  "name": "Orders API",
  "is_system": false,
  "access_token_lifetime_s": 3600,
  "token_format": "jwt",
  "rbac_mode": "off",
  "allow_offline_access": true,
  "require_resource_indicator": false,
  "dpop_required": false,
  "mcp_profile": false,
  "first_party_access": "all",
  "introspection_applications": ["app_01h455vb4pex5vsknk084sn02r"],
  "created_at": "2026-10-05T12:00:00Z",
  "updated_at": "2026-10-05T12:00:00Z"
}
```

## Erreurs

| HTTP | code | Quand |
|---|---|---|
| 400 | `unknown_field` | Le correctif contient un champ en lecture seule ou inconnu. |
| 404 | `not_found` | Aucune API avec cet identifiant dans cet environnement. |
| 409 | `conflict` | L'API est l'API système. |
| 412 | `precondition_failed` | `If-Match` ne correspond pas à la version actuelle. |
| 415 | `unsupported_media_type` | Le type de contenu n'est pas `application/merge-patch+json`. |
| 422 | `validation_failed` | Une valeur est invalide, un champ a été défini sur `null`, ou `key` / `identifier` a été modifié. |
| 422 | `validation_failed` | Un élément `introspection_applications` n'existe pas dans cet environnement (`unknown_application`), n'est pas confidentiel (`not_confidential`), est un doublon (`duplicate`) ou n'est pas un identifiant `app_…` (`invalid_value`) ; le pointeur nomme l'index dans la demande. |
| 428 | `precondition_required` | `If-Match` manque. |

## Exemple

```bash
curl -X PATCH https://api.eu.keenauth.com/v1/apis/api_01h455vb4pex5vsknk084sn02q \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -H "Content-Type: application/merge-patch+json" \
  -H 'If-Match: "1"' \
  -d '{"access_token_lifetime_s":900}'
```
