Saltar para a documentação
API

Listar membros

Toda a gente no espaço de trabalho, a função que cada um tem, e os endereços que a cada um foram dados.

GETapi.openemail.uk/members

Executa a chamada real contra o seu espaço de trabalho, com a sua própria chave.

GET /members

Toda a gente no espaço de trabalho, a função que cada um tem, e os endereços que a cada um foram dados.

Um membro são duas concessões, não uma

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

role é o que PODEM FAZER: uma linha, uma função, o mesmo objeto que /roles descreve. addresses é AQUILO A QUE o podem fazer: uma entrada por endereço, cada uma com o seu próprio access. Um cliente não os deve juntar: uma função com emails:send e um array addresses vazio é alguém que pode enviar a partir de nada, e um array addresses cheio sob uma função de viewer é também alguém que pode enviar a partir de nada. O caminho de envio verifica ambos, e um ecrã que mostre apenas um deles vai explicar com toda a confiança a recusa errada.

As linhas de endereço dizem access onde a coluna guardada diz role, e a mudança de nome é o ponto e não uma arrumação: este objeto já tem um campo role que significa outra coisa completamente diferente, e dois role a um nível de aninhamento de distância com valores de dois vocabulários diferentes é um bug à espera da primeira pessoa que o leia depressa. access é member, que lê o endereço e envia como ele, ou viewer, que apenas o lê.

implied: true significa que NINGUÉM ESCOLHEU ESTA FUNÇÃO. A partilha existia muito antes das funções, por isso a maioria das pessoas com acesso a uma caixa de correio tem concessões de endereço e nenhuma linha de membro; em vez de lhes negar o correio até uma migração ter corrido, o serviço infere uma função integrada a partir da concessão mais ampla que detêm e comunica-a com role.id a null. Mostre isso como "implícito pelo acesso" e não como uma função que alguém escolheu. Até um PATCH transformar a inferência numa decisão, alargar o acesso aos endereços alarga em silêncio o que podem fazer.

O PROPRIETÁRIO é a PRIMEIRA linha, marcada com isOwner: true, com role.builtin igual a owner. É a conta em que o espaço de trabalho está ancorado, tem todas as permissões por definição, e POST, PATCH e DELETE recusam-no a todos com member_is_owner. Por isso um espaço de trabalho não partilhado comunica um membro em vez de nenhum. Conte os lugares excluindo isOwner.

Exemplo

Requer members:read. O proprietário vem primeiro, depois toda a gente por email e não pela data de entrada, porque esta lista é lida para encontrar uma pessoa e não para ver o que mudou.

curl
curl "$OE/members" -H "$AUTH"
Resposta
{  "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}

Duas populações numa só lista, e tem de ser assim: alguém pode ter uma função e nenhum endereço, e alguém pode ter um endereço e nenhuma linha de função. Listar apenas a interseção esconderia ambas, e na maioria dos espaços de trabalho o segundo grupo é o maior.

createdAt é null para quem tem concessões mas nunca teve uma linha de membro escrita, as mesmas pessoas para quem implied é true. É quando lhes foi dada uma FUNÇÃO, não quando lhes foi partilhado o primeiro endereço.

permissions é a lista plana já resolvida em vez de um conjunto de booleans. Um cliente que pergunta "isto inclui templates:write" não pode ficar atrasado em relação ao vocabulário; um cliente a quem se entrega { canEditTemplates: true } fica, e em silêncio.

Sem cursor, com o envelope habitual. Os membros de um espaço de trabalho estão limitados pelo número de pessoas com quem o proprietário efetivamente o partilhou, e paginar isso seria cerimónia à frente de algo que um cliente vai buscar uma vez e apresenta inteiro.