# Créer une clé d'API et brancher votre suite de tests

> Créer une clé, l'utiliser depuis une CI, la renouveler sans coupure et la révoquer. Ce qu'elle atteint, et ce qu'elle n'atteindra jamais.
> https://facteur.eu/aide/cles-api

Une clé d'API permet à vos tests d'appeler l'API sans navigateur et sans session. Elle
appartient à l'**organisation**, ce qui veut dire qu'elle survit au départ de la
personne qui l'a créée : votre intégration continue ne casse pas parce que quelqu'un
change d'entreprise.

Il faut être **propriétaire ou administrateur** de l'organisation pour en créer une.

## Créer une clé

Ouvrez [**Réglages → Clés d'API → Créer une clé**](https://app.facteur.eu/settings/api-keys)
et remplissez quatre champs.

1. **Un nom.** C'est ce qui vous permettra de savoir laquelle révoquer dans six mois :
   « CI GitHub », « recette Camille ».
2. **Ce qu'elle peut faire.** Lecture seule par défaut, ce dont une suite de tests a
   besoin. Une seconde case ouvre la gestion des espaces de travail, pour un script de
   provisionnement.
3. **Où.** Si vous ne précisez rien, la clé ne vise que votre espace principal. La
   réponse vous rappelle toujours la portée obtenue.
4. **Une durée.** 90 jours par défaut, un an au plus.

Le secret s'affiche **une seule fois**, juste après la création. Nous n'en gardons
qu'une empreinte : ni vous ni nous ne pouvons le retrouver ensuite. Copiez-le
directement dans les secrets de votre CI.

## L'utiliser

Un en-tête `Authorization`, et c'est tout :

```bash
curl -H "Authorization: Bearer fk_votre_cle" \
  https://api.facteur.eu/v1/inboxes
```

La forme `Basic` fonctionne aussi, avec la clé en nom d'utilisateur et un mot de passe
vide : c'est ce qu'envoient certains SDK conçus pour d'autres plateformes.

**N'envoyez pas de cookie de session en même temps qu'une clé.** La requête est
refusée avec `AMBIGUOUS_CREDENTIALS` plutôt que tranchée au hasard : deux identités dans
une requête donneraient un test qui prouve quelque chose sur la mauvaise.

Comptez **600 requêtes par minute et par clé**. Au-delà, `429 KEY_RATE_LIMITED`.

Chaque route, sa portée et ses refus sont listés dans la référence d'API, sur
[developers.facteur.eu](https://developers.facteur.eu/reference/). Elle s'ouvre dans
votre langue, et elle est engendrée depuis la spécification contre laquelle l'API est
tenue.

## Choisir la portée

Une clé répond séparément à deux questions, ce qui vous permet de n'en donner que peu à
la fois.

**Ce qu'elle peut faire**, en quatre portées et deux familles :

| Portée | Ce qu'elle ouvre |
|---|---|
| `ws:read` | Lire les messages des espaces visés |
| `ws:write` | Y créer et supprimer des inboxes |
| `org:read` | Lister les espaces de travail, et voir qui accède à chacun |
| `org:write` | En créer un, le renommer, le marquer, et ajouter ou retirer les collègues qui y accèdent |

**Où elle peut le faire** : tous vos espaces de travail, ou seulement ceux que vous
nommez.

Écrire implique lire **dans une famille**, et rien ne traverse les familles.
`org:write` ne donne donc pas accès à votre courrier : un script qui provisionne des
espaces n'a pas à lire les messages qui s'y trouvent.

Si vous choisissez « tous les espaces », la portée inclut aussi ceux que vous créerez
plus tard. Une liste figée à la création serait une clé qui cesse silencieusement de
couvrir vos nouveaux espaces.

## Ce qu'une clé n'atteint jamais

Quelle que soit sa portée.

| Ce que la clé tente | Le refus | Ce que vous faites |
|---|---|---|
| Créer ou révoquer une clé | Route inatteignable | Passez par [l'application](https://app.facteur.eu/settings/api-keys). Une clé volée qui se renouvelle elle-même rendrait sa révocation sans effet |
| Toucher votre compte : mot de passe, second facteur, passkeys | Route inatteignable | Une clé fuitée ne prend pas le compte |
| Écrire alors qu'elle est en lecture seule | `403 SCOPE_INSUFFICIENT` | La réponse nomme la portée manquante et celles que la clé porte |
| Lister les espaces sans `org:*` | `403 SCOPE_INSUFFICIENT` | Créez une clé avec `org:read` |
| Faire entrer quelqu'un dans l'organisation | `403 KEY_CANNOT_INVITE` | Invitez depuis [l'application](https://app.facteur.eu/settings/members). Voir [Membres et sièges](membres-et-sieges) |
| Supprimer un espace de travail | `403 KEY_CANNOT_DELETE_WORKSPACE` | Supprimez depuis [l'application](https://app.facteur.eu/settings/workspaces) : l'opération réattribue l'historique de consommation et demande quelqu'un pour la lire |
| Lire le courrier d'un espace hors de sa portée | `404` | La clé visant « recette » ne lit pas l'espace principal. C'est la même frontière que celle des membres, voir [Espaces de travail](espaces-de-travail) |

Une session d'assistance ne peut pas créer de clé non plus, même avec votre accord
explicite : la clé serait ensuite indiscernable d'une clé que vous auriez créée
vous-même.

## Renouveler sans coupure

**Renouveler** crée une clé neuve et laisse l'ancienne vivre 24 heures. Déployez le
nouveau secret, regardez passer un build vert, et l'ancienne s'éteint seule. Une
rotation qui coupe est une rotation que personne ne fait.

Une clé déjà révoquée ne se renouvelle pas : cela la garderait vivante quelques heures
de plus, ce qui annulerait la révocation.

## Révoquer

Immédiat, sans fenêtre de cache : l'appel suivant échoue, y compris celui d'un pipeline
en cours.

Avant de révoquer, lisez la colonne **« utilisée le »** : elle vous dit si la clé sert
encore.

Ensuite, le refus distingue trois cas, parce que les gestes qu'ils demandent sont
différents :

| Code | Ce que ça veut dire | Ce que vous faites |
|---|---|---|
| `KEY_REVOKED` | Quelqu'un l'a retirée | Créez-en une nouvelle |
| `KEY_EXPIRED` | Elle a atteint sa date | Renouvelez-la |
| `KEY_UNKNOWN` | Cette clé n'a jamais existé | Vérifiez ce que votre CI envoie |

## Supprimer un espace visé par une clé

Refusé, avec `409 WORKSPACE_HAS_ACTIVE_KEYS` et le nom des clés qui bloquent.

Deux gestes possibles avant de réessayer : révoquer la clé, ou retirer cet espace de sa
portée. Une clé déjà révoquée ou expirée ne bloque rien, puisqu'elle n'ouvre plus rien.

## Provisionner un espace de travail par branche

C'est ce que `org:write` sert à faire :

```bash
# Ouvrir un espace pour la branche courante
curl -X POST https://api.facteur.eu/v1/workspaces \
  -H "Authorization: Bearer fk_votre_cle" \
  -H "content-type: application/json" \
  -d '{"name": "recette-PR-1234"}'
```

Deux choses à savoir :

- **L'espace créé n'entre pas dans la portée de la clé.** Une clé ne s'élargit pas
  elle-même. Si vos tests doivent lire le courrier de ce nouvel espace, visez « tous les
  espaces » à la création de la clé.
- **Le plafond du plan s'applique.** Un plan qui ne vend qu'un espace répond `402`, en
  nommant le plan à partir duquel c'est possible.

## Gérer qui accède à un espace de travail

Une clé portant `org:write` peut lister les membres d'un espace de travail, en ajouter
un et en retirer un.

**Cela ne fait entrer personne dans votre organisation.** La personne que vous nommez
doit déjà en être membre ; toute autre est refusée avec `NOT_AN_ORGANIZATION_MEMBER`. Ce
qui change, c'est quels espaces un collègue déjà présent peut ouvrir, et cela ne
consomme aucun siège.

Inviter reste l'acte qu'une clé n'accomplit jamais.

## Limites connues

- **Pas de restriction d'adresse IP.** Une liste d'adresses autorisées, pour les
  runners qui sortent par une adresse fixe, est annoncée sur l'écran comme à venir.
