Inviter une personne dans une organisation
POST /v1/invitations · autorisation invitations:write
Crée une invitation pour qu'une adresse e-mail rejoigne l'organisation. Sans organization_id, l'invitation est une invitation d'environnement : c'est le lien d'inscription pour le mode d'inscription sur invitation uniquement, elle n'ouvre aucune adhésion et ne peut pas porter de rôles (role_ids renvoie 422 validation_failed), et la réponse contient organization_id: null. delivery est obligatoire : email envoie l'e-mail d'invitation avec le modèle d'invitation de l'environnement (delivery_status: queued), le lien ne figure que dans l'e-mail et la réponse ne contient pas de accept_url ; link_only n'envoie aucun e-mail et renvoie le lien pour que vous le partagiez. Le lien d'acceptation (accept_url) n'est renvoyé que dans cette réponse, une seule fois ; aucun point de terminaison ne le renvoie ensuite. La réponse contient Cache-Control: no-store, et une réponse rejouée pour la même Idempotency-Key omet le lien et contient secret_redacted: true. Si l'envoi d'e-mails d'invitation n'est pas configuré pour le déploiement (uniquement dans les configurations hors production), la livraison email renvoie 501 not_implemented et rien n'est enregistré. Si une invitation en attente avec les mêmes rôles existe déjà pour l'organisation et l'adresse e-mail, elle est renvoyée avec un nouveau lien et la réponse est 200. Une invitation en attente arrivée à expiration mais pas encore traitée est marquée expired dans la même requête et une nouvelle invitation est enregistrée (journalisée sous invitation.expired). Une invitation email en attente avec les mêmes rôles est renvoyée par e-mail : la réponse est 200 avec delivery: email et sans accept_url. L'écriture est journalisée sous invitation.created.
Requête
| Champ | Type | Obligatoire | Description |
|---|---|---|---|
organization_id |
string | non | Identifiant de l'organisation (org_…) ; omettez-le pour une invitation d'environnement (sans rôles). |
email |
string | oui | Adresse e-mail de la personne invitée, 320 caractères au maximum. |
delivery |
string | oui | email (lien uniquement dans l'e-mail) ou link_only (lien uniquement dans cette réponse). |
role_ids |
string[] | non | Rôles accordés à l'acceptation (rol_…), 10 au maximum ; rôle de membre par défaut si la liste est vide. |
application_id |
string | non | Application dans laquelle atterrit la personne invitée (app_…) ; elle doit exister dans cet environnement. |
ttl_days |
integer | non | 1 à 30 ; la valeur par défaut est invitation_ttl_days de l'environnement (7). |
Réponse
201 Created avec l'invitation et son lien d'acceptation (200 OK lorsqu'une invitation en attente a été renvoyée).
{
"id": "inv_01j9xt9v3w4y8z0a2b4c6d8e0g",
"organization_id": "org_01j9xk3m7q8r2s4t6v8w0y2z4a",
"email": "ada@example.com",
"role_ids": [
"rol_01j9xr7s1t2w6x8y0z2a4b6c8e"
],
"application_id": null,
"delivery": "link_only",
"delivery_status": "not_sent",
"status": "pending",
"send_count": 1,
"last_sent_at": "2026-10-12T09:31:00.123456Z",
"expires_at": "2026-10-19T09:31:00.123456Z",
"accepted_user_id": null,
"accepted_at": null,
"revoked_at": null,
"created_at": "2026-10-12T09:31:00.123456Z",
"updated_at": "2026-10-12T09:31:00.123456Z",
"version": 1,
"accept_url": "https://acme.eu.keenauth.app/u/login?invitation=<token>"
}
Erreurs
| HTTP | code | Quand |
|---|---|---|
| 404 | not_found |
L'organisation ou l'application n'existe pas dans cet environnement. |
| 409 | invitation_already_pending |
Une invitation en attente avec des rôles différents existe pour cette adresse e-mail. |
| 409 | membership_already_exists |
L'adresse e-mail appartient déjà à un membre. |
| 409 | organization_disabled |
L'organisation est désactivée. |
| 422 | invitation_invalid |
L'invitation ne peut pas être créée avec ces valeurs. |
| 422 | validation_failed |
Un champ est manquant ou invalide. |
| 429 | invite_rate_limited |
L'invitation a été renvoyée il y a moins de 10 minutes ou a déjà été renvoyée 5 fois. |
| 501 | not_implemented |
delivery vaut email et l'envoi d'e-mails d'invitation n'est pas configuré pour le déploiement. |
| 401 | unauthenticated |
L'identifiant d'authentification est absent, invalide ou révoqué. |
| 403 | insufficient_permissions |
L'identifiant d'authentification ne dispose pas de l'autorisation requise. L'attribution d'un rôle privilégié (is_privileged) exige aussi roles:write ; sans cette autorisation, rien n'est enregistré et required_permissions liste les deux autorisations. |
| 429 | rate_limited |
La limite de débit a été dépassée ; réessayez après la durée indiquée par Retry-After. |
| 503 | service_unavailable |
Une dépendance est temporairement indisponible ; réessayez après la durée indiquée par Retry-After. |
Exemple
curl -i -X POST "https://api.eu.keenauth.com/v1/invitations" \
-H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{"organization_id":"org_01j9xk3m7q8r2s4t6v8w0y2z4a","email":"ada@example.com","delivery":"link_only","role_ids":["rol_01j9xr7s1t2w6x8y0z2a4b6c8e"]}'
Données personnelles
Ce point de terminaison traite des données personnelles : adhésions aux organisations et invitations. Données personnelles dans les API KeenAuth décrit ce qui est stocké, la durée de conservation et la manière dont elles sont supprimées. N'envoyez pas de catégories particulières de données personnelles (santé, données biométriques, religion, opinions politiques, orientation sexuelle) dans aucun champ.