멤버 목록
워크스페이스에 있는 모든 사람과, 각자가 가진 역할, 그리고 부여받은 주소.
본인 키로 워크스페이스에 실제 호출을 실행합니다.
GET /members
워크스페이스에 있는 모든 사람과, 각자가 가진 역할, 그리고 부여받은 주소.
멤버는 하나가 아니라 두 개의 권한이다
export OE=https://api.openemail.ukexport AUTH="Authorization: Bearer $OPENEMAIL_API_KEY"role은 그 사람이 무엇을 할 수 있는지입니다. 한 행에 역할 하나이며, /roles가 설명하는 것과 같은 객체입니다. addresses는 그것을 어디에 할 수 있는지입니다. 주소마다 항목이 하나씩이고 각자 자기 access를 갖습니다. 클라이언트는 둘을 합쳐서는 안 됩니다. addresses가 빈 배열인데 emails:send를 가진 역할은 아무 주소로도 보낼 수 없는 사람이고, viewer 역할 아래 addresses가 가득한 사람도 마찬가지로 아무 주소로도 보낼 수 없습니다. 발송 경로는 둘 다 검사하며, 하나만 보여주는 화면은 엉뚱한 거부 사유를 자신 있게 설명하게 됩니다.
주소 행은 저장된 컬럼 이름이 role인데도 access라고 말하며, 그 이름 변경 자체가 핵심입니다. 이 객체에는 이미 전혀 다른 의미의 role 필드가 있고, 중첩 한 단계 차이로 서로 다른 어휘의 값을 담은 role이 둘이면 빨리 읽는 첫 번째 사람에게 버그가 됩니다. access는 주소를 읽고 그 주소로 보내는 member, 또는 읽기만 하는 viewer입니다.
implied: true는 아무도 이 역할을 고르지 않았다는 뜻입니다. 공유 기능은 역할보다 훨씬 먼저 출시됐기 때문에, 메일함에 접근할 수 있는 사람 대부분은 주소 권한만 갖고 멤버 행은 아예 없습니다. 백필이 돌 때까지 메일을 못 보게 하는 대신, 서비스는 그들이 가진 가장 넓은 권한에서 내장 역할을 추론해 role.id를 null로 두고 보고합니다. 그것은 누군가 고른 역할이 아니라 "접근 권한에서 추론됨"으로 표시하십시오. PATCH가 그 추론을 결정으로 바꾸기 전까지는, 주소 접근을 넓히면 그 사람이 할 수 있는 일도 조용히 넓어집니다.
소유자는 첫 번째 행이며 isOwner: true로 표시되고 role.builtin이 owner입니다. 워크스페이스가 귀속된 계정이고 정의상 모든 권한을 가지며, POST, PATCH, DELETE가 모두 member_is_owner로 거부합니다. 그래서 공유되지 않은 워크스페이스도 멤버가 0명이 아니라 1명으로 보고됩니다. 좌석 수를 셀 때는 isOwner를 제외하십시오.
예제
members:read가 필요합니다. 소유자가 먼저 오고, 나머지는 가입 시점이 아니라 이메일 순으로 정렬됩니다. 이 목록은 무엇이 바뀌었는지 보려고가 아니라 한 사람을 찾으려고 읽기 때문입니다.
curl "$OE/members" -H "$AUTH"{ "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}한 목록에 두 집단이 섞여 있고, 그럴 수밖에 없습니다. 역할만 있고 주소가 없는 사람도, 주소만 있고 역할 행이 없는 사람도 있습니다. 교집합만 나열하면 둘 다 숨겨지고, 대부분의 워크스페이스에서는 두 번째 집단이 더 큽니다.
createdAt은 권한은 있지만 멤버 행이 한 번도 쓰인 적 없는 사람, 즉 implied가 true인 바로 그 사람들에게 null입니다. 이 값은 역할을 받은 시점이지, 주소를 처음 공유받은 시점이 아닙니다.
permissions는 불리언 묶음이 아니라 평탄하게 해석된 목록입니다. "여기에 templates:write가 있나"를 묻는 클라이언트는 어휘가 늘어나도 뒤처지지 않지만, { canEditTemplates: true }를 받는 클라이언트는 조용히 뒤처집니다.
커서가 없고 표준 엔벌로프를 씁니다. 워크스페이스 멤버 수는 소유자가 실제로 공유한 인원만큼으로 한정되며, 클라이언트가 한 번 받아 통째로 그리는 것 앞에 페이지네이션을 두는 것은 형식일 뿐입니다.