Lister les rôles
Tous les rôles de l'espace de travail, les rôles intégrés d'abord, avec le nombre de personnes et de clés qui détiennent chacun.
Exécute le véritable appel sur votre espace de travail, avec votre propre clé.
GET /roles
Tous les rôles de l'espace de travail, les rôles intégrés d'abord, avec le nombre de personnes et de clés qui détiennent chacun.
Deux axes, et ce n'est pas la même question
export OE=https://api.openemail.ukexport AUTH="Authorization: Bearer $OPENEMAIL_API_KEY"Un RÔLE dit ce que quelqu'un peut FAIRE dans cet espace de travail : lire le courrier, en envoyer, modifier des modèles, ajouter un domaine. Un OCTROI dit sur quelles ADRESSES il peut le faire ; il se trouve juste à côté, sur /members/{userId}/addresses, sous la forme member (lit l'adresse et envoie en son nom) ou viewer (la lit seulement). Les deux doivent concorder avant qu'un message ne parte : un rôle portant emails:send sans aucun octroi ne peut envoyer depuis rien, et toutes les adresses de l'espace de travail sous un octroi viewer ne permettent pas davantage d'envoyer depuis quoi que ce soit.
Chaque espace de travail est initialisé avec les six mêmes rôles. Owner, Admin, Member et Viewer forment une échelle. Chacun détient tout ce que détient le suivant, si bien que rétrograder quelqu'un restreint son accès au lieu de l'échanger contre une autre tranche. Developer et Billing n'en sont pas des barreaux : Developer construit des intégrations (clés, webhooks, modèles, envoi) et ne lit aucun courrier de l'espace de travail, et Billing voit le plan et les factures, rien d'autre. Les deux tiennent strictement à l'intérieur d'Admin. Ils sont créés à la première lecture plutôt qu'à la création de l'espace de travail, si bien qu'un espace de travail antérieur à cette fonctionnalité les obtient dès que quelque chose les demande. builtin indique de quelle graine provient une ligne, et c'est tout ce qu'il indique : les six sont un point de départ que l'espace de travail est censé façonner, et tous sauf Owner peuvent être renommés, repermissionnés et supprimés. Branchez sur editable et deletable plutôt que sur le nom : un rôle que quelqu'un a renommé répond toujours correctement à ces deux-là, alors que son nom ne vous apprend plus rien.
Owner est la seule exception, et c'en est une dans tous les sens : editable: false, deletable: false, et refusé comme cible sur PATCH /members/{userId}. Il décrit le compte sur lequel l'espace de travail est indexé et détient toutes les permissions, y compris celles ajoutées dans une version ultérieure, raison pour laquelle sa liste est calculée plutôt que stockée. Faire de quelqu'un d'autre le propriétaire relève d'un transfert d'espace de travail ; aucun endpoint ici ne l'effectue.
Les cinq autres acceptent tout : une nouvelle liste de permissions, une nouvelle description, un nouveau nom, un DELETE. Ce sont des valeurs par défaut initiales et non des éléments figés : un espace de travail qui ne construit jamais d'intégration doit pouvoir se débarrasser de Developer, et celui où « Member » désigne quelque chose de plus étroit doit pouvoir le dire avec ses propres mots. Seul le propriétaire refuse, et il refuse l'ensemble sous un seul code : role_immutable, un 409 portant param: "roleId", que le PATCH contienne un nom ou une liste de permissions. Aucun renommage n'est plus refusé à lui seul, il n'y a donc pas d'immuabilité param: "name" à gérer ; le seul 409 qu'un nom peut encore déclencher est role_name_taken, lorsqu'un autre rôle de l'espace de travail répond déjà à ce nom.
Au-delà des six, un espace de travail écrit jusqu'à 24 rôles qui lui sont propres. Le plafond ne compte que ceux-là : supprimer un rôle initial ne libère donc aucune place en dessous. Les permissions sont DÉVELOPPÉES à l'entrée plutôt que prises au pied de la lettre (templates:write seul est stocké comme templates:read et templates:write), relisez donc la liste sur la réponse au lieu de supposer que c'est celle que vous avez envoyée.
Un rôle constitue aussi le plafond d'une clé API. Une clé émise sous un rôle peut faire key.scopes ∩ role.permissions et rien de plus, résolu par requête à la frontière : modifier un rôle change donc ce que ses clés peuvent faire dès leur appel suivant, et une clé sans rôle n'a aucun plafond. La page Portées expose tout cela.
Exemple
Requiert roles:read. Sans curseur. L'enveloppe porte hasMore et nextCursor afin qu'un client puisse la passer au même code de liste que pour toutes les autres collections, et il n'y a jamais de deuxième page.
curl "$OE/roles" -H "$AUTH"{ "object": "list", "data": [ { "object": "role", "id": "role_1c94e05d3862c1f0a44b7f3a", "name": "Owner", "description": "The person the workspace belongs to. Holds everything, including additions.", "permissions": ["emails:send", "emails:read", "…", "workspace:manage"], "builtin": "owner", "editable": false, "deletable": false, "members": 0, "apiKeys": 2, "createdAt": "2026-08-01T09:00:00.000Z", "updatedAt": "2026-08-01T09:00:00.000Z" }, { "object": "role", "id": "role_c40a95f21cc65d31c2a89e07", "name": "Viewer", "description": "Reads the mail on the addresses they hold, and changes nothing.", "permissions": [ "emails:read", "drafts:read", "threads:read", "labels:read", "contacts:read", "calendar:read", "templates:read", "rules:read", "connections:read", "settings:read" ], "builtin": "viewer", "editable": true, "deletable": true, "members": 3, "apiKeys": 1, "createdAt": "2026-08-01T09:00:00.000Z", "updatedAt": "2026-08-01T09:00:00.000Z" } ], "hasMore": false, "nextCursor": null}Trié par rang des rôles intégrés puis par nom (owner, admin, member, viewer, developer, billing, puis le reste par ordre alphabétique) plutôt que du plus récent au plus ancien comme le reste de l'API. Une matrice de permissions se lit comme une échelle, et la trier par createdAt place le rôle le plus large sur une ligne différente chaque semaine.
C'est la lecture de cette liste qui CRÉE les six rôles sur un espace de travail qui n'en a jamais eu. L'insertion entre en conflit sur un index unique et ne fait rien la seconde fois : l'appel est donc idempotent et seul le premier écrit, ce qui explique aussi que POST /members puisse toujours nommer un roleId existant.
Il n'initialise QU'UNE FOIS. L'espace de travail enregistre qu'il a été initialisé : cette lecture complète donc un espace de travail plus ancien que la fonctionnalité, puis n'écrit plus jamais, ce qui rend définitive la suppression d'un rôle initial. Une version antérieure réinsérait à chaque lecture la ligne modèle manquante, si bien qu'un Billing supprimé revenait sous un nouvel id au chargement de page suivant ; ce n'est plus le cas.
members et apiKeys indiquent ce qu'il faudrait déplacer avant que le rôle puisse disparaître, ce qui permet à un client d'avertir avant de proposer la suppression plutôt qu'après le 409. La ligne du propriétaire affiche généralement members: 0 : le propriétaire n'est pas membre de son propre espace de travail, il est le compte sur lequel celui-ci est indexé.
Il existe un plafond strict de 24 rôles personnalisés, précisément pour que cela tienne en une seule réponse. Un espace de travail comptant quarante rôles ne peut pas répondre « qui peut envoyer en tant que billing@ » d'un simple coup d'œil, alors que c'est la seule question à laquelle la fonctionnalité existe pour répondre.