# Clés d'API

> Pour une intégration connue - un partenaire, un batch, un serveur qui n'a pas d'utilisateur - et pas pour un agent (celui-ci reçoit un jeton OAuth, Agents et…

Guide - Depuis la version 0.1.0 - Flexway v1.6.3 - https://flexway.io/docs/operations-api-keys/

> Guide d'exploitation : configurer, déployer et observer la passerelle. Ce que fait la capacité côté produit : [guide produit](https://flexway.io/docs/product-overview/) ; l'appeler : [guide développeur](https://flexway.io/docs/developer-overview/).

Pour une **intégration connue** - un partenaire, un batch, un serveur qui n'a pas d'utilisateur - et
pas pour un agent (celui-ci reçoit un jeton OAuth, [Agents et MCP](https://flexway.io/docs/operations-agents-mcp/)). Une clé est liée à **un tenant**, à **des
opérations nommées** et à une **date de fin** ; elle n'atteint **jamais** l'amont.

**Commande** - créer une clé :

```sh
docker run --rm -it ghcr.io/flexwiz/flexway:<version> api-key   # ou le binaire : flexway api-key
```

La commande **demande** l'identifiant, le tenant, les opérations et la durée (90 jours par défaut),
puis affiche **une seule fois** la clé (`fwk_` + 43 caractères, 256 bits aléatoires) et l'entrée à
ajouter au magasin - son **empreinte SHA-256**, jamais la clé :

```yaml
# api-keys.yaml - en grappe, un Secret synchronisé par ESO, monté en lecture seule
keys:
  - id: acme-billing-2026-10
    hash: sha256:9f2c...
    tenant: acme
    operations: [listInvoices, getInvoice]
    expires_at: 2027-01-01T00:00:00Z
```

La configuration nomme le magasin ; le contrat dit **où** une clé est acceptée, par une alternative
`apiKey` à côté de celle du jeton :

```yaml
# flexway.yaml
auth:
  api_keys: { store: "file:./api-keys.yaml" }
```

```yaml
# contrat
components:
  securitySchemes:
    key: { type: apiKey, in: header, name: Authorization }   # toujours Authorization: ApiKey <clé>
paths:
  /invoices:
    get:
      operationId: listInvoices
      security: [ { customers: [invoices:read] }, { key: [] } ]   # un jeton, ou une clé liée
```

**Vérif** :

| Appel | Réponse |
| --- | --- |
| `Authorization: ApiKey <clé>` sur une opération liée | relayé ; l'amont reçoit `X-Tenant` de la clé, **sans** la clé |
| Clé valide, opération qu'elle ne nomme pas | `403` |
| Clé sur une opération sans alternative `apiKey` | `401`, `WWW-Authenticate: Bearer` |
| Clé inconnue, expirée ou sans le préfixe `fwk_` | `401`, `WWW-Authenticate: ApiKey` ; le journal nomme la clé expirée par son `id`, jamais la clé |
| Clé dans un autre en-tête (`X-Api-Key`) ou dans l'URL | ignorée ; un schéma `apiKey` hors `Authorization` est **refusé au chargement** |

> **Cycle de vie** : le magasin est relu à **chaque rechargement** ([Changer la configuration sans redémarrer](https://flexway.io/docs/operations-live-config/)). Émettre = ajouter une
> entrée ; **révoquer** = la retirer ; **tourner** = deux entrées le temps que l'intégration bascule,
> puis retirer l'ancienne. Une entrée qui nomme une opération qu'aucun contrat ne déclare est refusée
> au chargement, comme une politique. Le débit se compte **par clé** (`apikey:<id>`).
