メンバーを一覧する
ワークスペースの全員と、各自が持つロール、各自に与えられたアドレスです。
実際の呼び出しを、ご自身のキーで自分のワークスペースに対して実行します。
GET /members
ワークスペースの全員と、各自が持つロール、各自に与えられたアドレスです。
メンバーは 1 つではなく 2 つの付与でできている
export OE=https://api.openemail.ukexport AUTH="Authorization: Bearer $OPENEMAIL_API_KEY"role はその人が「何をしてよいか」です。1 行につき 1 つのロールで、/roles が記述するのと同じオブジェクトです。addresses はそれを「何に対して」してよいかです。アドレスごとに 1 エントリで、それぞれが自分の access を持ちます。クライアントはこの 2 つを一緒くたにしてはいけません。emails:send を持つロールと空の addresses 配列は、どこからも送信できない人を意味し、viewer ロールの下にある満杯の addresses 配列も、やはりどこからも送信できない人を意味します。送信パスは両方を確認するので、片方だけを表示する画面は自信満々に誤った拒否理由を説明することになります。
アドレスの行は、保存された列名が role であるのに対して access と呼びます。この改名は整理のためではなく、それ自体が要点です。このオブジェクトにはすでにまったく別の意味の role フィールドがあり、ネストが 1 段違うだけの 2 つの 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 が必要です。オーナーが先頭に来て、その後は参加日時ではなくメールアドレス順に全員が並びます。この一覧は変更点を見るためではなく、1 人を探すために読まれるからです。
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}1 つの一覧に 2 つの集団が入っており、そうならざるを得ません。ロールだけを持つ人もいれば、アドレスだけを持ちロール行がない人もいます。重なり部分だけを列挙すると両方が隠れ、たいていのワークスペースでは後者のほうが大きな集団です。
createdAt は、付与は持つがメンバー行が一度も書かれたことのない人では null になります。implied が true になるのと同じ人たちです。これはアドレスを最初に共有された時点ではなく、ロールを与えられた時点を表します。
permissions は真偽値の集合ではなく、解決済みのフラットな一覧です。「これに templates:write は含まれるか」と尋ねるクライアントは語彙に取り残されませんが、{ canEditTemplates: true } を渡されたクライアントは静かに取り残されます。
カーソルなしで、標準のエンベロープを使います。ワークスペースのメンバー数は、オーナーが実際に共有した人数までしか増えません。それをページ分割するのは、クライアントが一度取得してまとめて描画するものの前に置かれた儀式でしかありません。