Skip to content

Authentification ​

L’interface web s’authentifie par un cookie de session. Un programme s’authentifie par une clé d’API : un secret créé par un membre, envoyé à chaque requête, qui agit au nom de ce membre dans la limite des portées qu’on lui a données. Cette page traite de la clé ; le cookie de session est décrit à la fin, pour mémoire.

Créer une clé ​

Chaque membre crée ses propres clés dans Réglages › Clés d’API. Une clé a :

  • un nom, pour la reconnaître plus tard (1 à 120 caractères) ;
  • les portées qu’elle peut utiliser, choisies domaine par domaine : rien, lecture seule, ou lecture et écriture. Voir Portées. Une clé porte au plus 20 portées, et au moins une ;
  • une expiration facultative : 30, 90 ou 365 jours dans l’interface (l’API accepte de 1 à 730 jours par expiresInDays). Sans expiration, la clé vit jusqu’à sa révocation.

Le secret n’est affiché qu’une fois, à la création. Mankomail n’en conserve qu’une empreinte : personne, pas même un administrateur, ne peut le relire. Copiez-le avant de fermer la fenêtre ; s’il est perdu, révoquez la clé et créez-en une autre. Le secret commence par mk_ ; la liste des clés n’en montre que les huit premiers caractères, comme repère.

Les clés se créent aussi par l’API, par une session seulement : POST /api/v1/api-keys avec name, scopes et, facultativement, expiresInDays. Une clé ne peut pas créer de clés (voir Ce qui refuse une clé).

Les administrateurs voient toutes les clés de l’instance, avec le membre de chacune, dans Administration › Clés d’API, et peuvent révoquer n’importe laquelle. Création et révocation sont tracées au journal d’audit (api_key.created, api_key.revoked).

Envoyer la clé ​

Envoyez le secret dans l’en-tête Authorization, comme jeton porteur, à chaque requête :

http
GET /api/v1/workflows HTTP/1.1
Host: <PUBLIC_BASE_URL>
Authorization: Bearer mk_Qm9uam91cl9jZXN0X3VuX2V4ZW1wbGVfZGVfY2xl
Accept: application/json

Une requête qui porte une clé d’API n’a besoin ni de cookie ni de jeton CSRF. Le cookie de session se protège lui-même par SameSite=Lax ; une clé n’est jamais envoyée d’elle-même par un navigateur, il n’y a donc rien contre quoi se protéger.

Quand une requête porte un en-tête Authorization: Bearer, c’est la clé qui décide : une clé invalide est refusée même si un cookie de session valide voyage dans la même requête. Un en-tête explicite est une intention explicite ; retomber en silence sur un cookie cacherait les erreurs.

La clé agit comme son membre ​

Pour la route, une requête authentifiée par une clé est une requête du membre qui l’a créée. La clé voit les workflows, les boîtes, les tables et les exécutions du membre, et rien d’autre : le workflow d’un autre membre est un 404, comme il le serait pour le membre dans l’interface. Les routes d’administration (/api/v1/admin/…) exigent que le membre soit administrateur : une portée admin:* sur la clé d’un membre ordinaire n’accorde rien, et l’interface ne la lui laisse pas cocher.

Les portées n’ajoutent donc jamais de droits ; elles en retirent. La clé d’un administrateur limitée à executions:read ne peut pas inviter un membre, même si son propriétaire le pourrait.

Les actions faites avec une clé sont attribuées à son membre dans le journal d’audit. Le lastUsedAt de la clé est mis à jour au fil de son usage, à la minute près, pour repérer et révoquer les clés qui ne servent plus.

Expiration et révocation ​

  • Une clé expirée est refusée comme une clé inconnue. Sa ligne reste dans la liste avec son expiresAt, pour voir quelle intégration a besoin d’une nouvelle clé.
  • Révoquer une clé est immédiat et définitif : la requête suivante est refusée. Révoquer deux fois garde la première date. La ligne est conservée, pour le journal d’audit ; elle ne disparaît jamais de la liste.
  • Une clé révoquée ou expirée ne se réactive pas. Créez-en une nouvelle et remplacez le secret dans le système appelant.

Limite de débit ​

Chaque clé peut faire 600 requêtes par minute glissante. La limite est par clé, pas par membre : deux intégrations du même membre ne se partagent pas un quota. Au-delà, la réponse est 429 avec le code api_key.rate_limited, un en-tête Retry-After en secondes et la même valeur dans details.retryAfterSeconds. La limite est comptée avant la vérification de portée : un script qui boucle sur un 403 coûte autant qu’un script qui boucle sur un 200.

Les refus ​

StatutCodeSens
401auth.unauthenticatedPas de clé, ou une clé inconnue, mal formée, expirée ou révoquée. Les quatre cas sont volontairement indistinguables.
403api_key.scope_missingLa clé est valide mais aucune de ses portées ne couvre la route. details.required nomme la portée à ajouter, par exemple "workflows:write". Créez une clé avec cette portée ; la clé actuelle n’est pas cassée.
403api_key.session_requiredLa route est réservée à une session de membre.
403api_key.route_not_allowedLa route n’est pas ouverte aux clés d’API.
403auth.forbiddenLe membre derrière la clé n’a pas le rôle que la route exige (une route d’administration appelée avec la clé d’un membre ordinaire).
429api_key.rate_limitedTrop de requêtes dans la dernière minute. Attendez Retry-After secondes.

Ce qui refuse une clé ​

Une poignée de routes n’ont de sens que pour une personne dans un navigateur et refusent les clés avec 403 api_key.session_required :

  • gérer ses propres clés : GET /api/v1/api-keys, POST /api/v1/api-keys, POST /api/v1/api-keys/{id}/revoke — une clé qui fabriquerait des clés serait une clé qu’on ne sait plus révoquer, puisqu’elle se serait déjà remplacée ;
  • POST /api/v1/auth/logout et POST /api/v1/me/password ;
  • lancer une connexion OAuth dans le navigateur, POST /api/v1/oauth/{provider}/start ;
  • le WebSocket de l’interface, /api/v1/ws.

Les administrateurs peuvent lister et révoquer les clés par l’API avec une portée admin : GET /api/v1/admin/api-keys (admin:read) et POST /api/v1/admin/api-keys/{id}/revoke (admin:write).

Dans la référence, chaque route donne sa règle d’accès : une portée, « session de membre seulement », « aucune authentification » (connexion, sondes de santé) ou « autorisée par le jeton porté dans l’URL » (liens d’approbation, déclencheurs webhook).

Un membre se connecte avec POST /api/v1/auth/login, en envoyant email et password. La réponse pose un cookie nommé session (HttpOnly, SameSite=Lax, Secure en production), qui authentifie les requêtes suivantes ; GET /api/v1/auth/me renvoie le membre connecté et POST /api/v1/auth/logout termine la session. Les tentatives de connexion sont limitées par adresse IP (429 auth.too_many_attempts avec Retry-After), et une connexion qui n’arrive pas en HTTPS est refusée en production (auth.https_required).

Le cookie est fait pour l’interface. Pour tout ce qui est automatisé, créez une clé.