Aller à la documentation
API

Lister les membres

Toutes les personnes de l'espace de travail, le rôle que chacune détient et les adresses qui lui ont été données.

GETapi.openemail.uk/members

Exécute le véritable appel sur votre espace de travail, avec votre propre clé.

GET /members

Toutes les personnes de l'espace de travail, le rôle que chacune détient et les adresses qui lui ont été données.

Un membre, ce sont deux octrois, pas un

shell
export OE=https://api.openemail.ukexport AUTH="Authorization: Bearer $OPENEMAIL_API_KEY"

role est ce qu'ils peuvent FAIRE : une ligne, un rôle, le même objet que décrit /roles. addresses est ce SUR QUOI ils peuvent le faire : une entrée par adresse, chacune portant son propre access. Un client ne doit pas les confondre : un rôle détenant emails:send avec un tableau addresses vide, c'est quelqu'un qui peut envoyer depuis rien, et un tableau addresses bien rempli sous un rôle viewer, c'est aussi quelqu'un qui peut envoyer depuis rien. Le chemin d'envoi vérifie les deux, et un écran qui n'en montre qu'un expliquera avec assurance le mauvais refus.

Les lignes d'adresses disent access là où la colonne stockée dit role, et ce renommage est le fond du sujet plutôt qu'un simple toilettage : cet objet possède déjà un champ role qui signifie tout autre chose, et deux role distants d'un niveau d'imbrication portant des valeurs issues de deux vocabulaires différents, c'est un bug qui attend la première personne qui lira vite. access vaut member, qui lit l'adresse et envoie en son nom, ou viewer, qui se contente de la lire.

implied: true signifie que PERSONNE N'A CHOISI CE RÔLE. Le partage existait bien avant les rôles, si bien que la plupart des personnes ayant accès à une boîte aux lettres détiennent des octrois d'adresses et aucune ligne de membre ; plutôt que de leur refuser leur courrier en attendant qu'une reprise de données soit passée, le service infère un rôle intégré à partir du plus large octroi qu'elles détiennent et le signale avec un role.id à null. Affichez cela comme « impliqué par l'accès » plutôt que comme un rôle que quelqu'un a choisi. Tant qu'un PATCH ne transforme pas l'inférence en décision, élargir leur accès aux adresses élargit silencieusement ce qu'elles peuvent faire.

Le PROPRIÉTAIRE est la PREMIÈRE ligne, marquée isOwner: true, avec un role.builtin valant owner. C'est le compte sur lequel l'espace de travail est indexé, il détient par définition toutes les permissions, et POST, PATCH et DELETE le refusent tous avec member_is_owner. Un espace de travail non partagé signale donc un membre plutôt qu'aucun. Comptez les sièges en excluant isOwner.

Exemple

Nécessite members:read. Le propriétaire vient en premier, puis tous les autres par e-mail plutôt que par date d'arrivée, parce que cette liste est lue pour trouver une personne plutôt que pour voir ce qui a changé.

curl
curl "$OE/members" -H "$AUTH"
Réponse
{  "object": "list",  "data": [    {      "object": "member",      "userId": "nQ8vBz1aRd4tYwKx7fQ2mN8vBz1aRd4t",      "email": "[email protected]",      "name": "Sam Okonjo",      "image": null,      "role": {        "id": "role_2b81de079c1f0a4b7e05d386",        "name": "Support",        "builtin": null      },      "implied": false,      "permissions": [        "emails:send",        "emails:read",        "threads:read",        "threads:write",        "labels:read",        "labels:write",        "contacts:read"      ],      "addresses": [        {          "addressId": "2b81de07-9c1f-4a4b-8e05-d3862c1f0a44",          "address": "[email protected]",          "access": "member"        },        {          "addressId": "c40a95f2-1cc6-4d31-82a8-9e075d31c2a8",          "address": "[email protected]",          "access": "viewer"        }      ],      "createdAt": "2026-08-12T14:20:00.000Z"    },    {      "object": "member",      "userId": "7fQ2mN8vBz1aRd4tYwKx7fQ2mN8vBz1a",      "email": "[email protected]",      "name": null,      "image": null,      "role": { "id": null, "name": "Viewer", "builtin": "viewer" },      "implied": true,      "permissions": [        "emails:read",        "drafts:read",        "threads:read",        "labels:read",        "contacts:read",        "calendar:read",        "templates:read",        "rules:read",        "connections:read",        "settings:read"      ],      "addresses": [        {          "addressId": "c40a95f2-1cc6-4d31-82a8-9e075d31c2a8",          "address": "[email protected]",          "access": "viewer"        }      ],      "createdAt": null    }  ],  "hasMore": false,  "nextCursor": null}

Deux populations dans une seule liste, et il ne peut en être autrement : quelqu'un peut détenir un rôle et aucune adresse, et quelqu'un peut détenir une adresse et aucune ligne de rôle. Ne lister que l'intersection masquerait les deux, et dans la plupart des espaces de travail le second groupe est le plus grand.

createdAt vaut null pour quelqu'un qui a des octrois mais pour qui aucune ligne de membre n'a jamais été écrite, les mêmes personnes pour lesquelles implied vaut true. C'est la date à laquelle un RÔLE leur a été donné, pas celle du premier partage d'une adresse.

permissions est la liste résolue à plat plutôt qu'un ensemble de booléens. Un client qui demande « est-ce que cela inclut templates:write » ne peut pas prendre de retard sur le vocabulaire ; un client à qui l'on remet { canEditTemplates: true } le peut, silencieusement.

Sans cursor, avec l'enveloppe standard. Le nombre de membres d'un espace de travail est borné par le nombre de personnes avec qui son propriétaire l'a effectivement partagé, et paginer cela reviendrait à mettre du cérémonial devant quelque chose qu'un client récupère une fois et affiche en entier.