ロールを一覧する
ワークスペース上のすべてのロールを、組み込みから順に、それぞれを何人と何個のキーが持っているかとともに返します。
実際の呼び出しを、ご自身のキーで自分のワークスペースに対して実行します。
GET /roles
ワークスペース上のすべてのロールを、組み込みから順に、それぞれを何人と何個のキーが持っているかとともに返します。
2 つの軸は、同じ問いではない
export OE=https://api.openemail.ukexport AUTH="Authorization: Bearer $OPENEMAIL_API_KEY"ロールは、このワークスペースで誰が何をしてよいかを表します。メールを読む、送る、テンプレートを編集する、ドメインを追加する、といったことです。付与は、それをどのアドレスに対して行ってよいかを表し、隣の /members/{userId}/addresses に member(そのアドレスを読み、そのアドレスとして送信する)または viewer(読むだけ)として存在します。メッセージが出ていくにはその両方が一致している必要があります。emails:send を持つロールでも付与がなければどこからも送信できず、ワークスペース内のすべてのアドレスを viewer 付与で持っていても、やはりどこからも送信できません。
どのワークスペースにも同じ 6 つのロールがシードされます。Owner、Admin、Member、Viewer は梯子を成します。それぞれが次のロールの持つものをすべて含むので、降格させればアクセス権は別の範囲に置き換わるのではなく狭まります。Developer と Billing はその段ではありません。Developer は連携を作り(キー、webhook、テンプレート、送信)、ワークスペースのメールは一切読みません。Billing はプランと請求書だけを見て、それ以外は何も見ません。どちらも厳密に Admin の内側に収まります。ワークスペース作成時ではなく最初の読み取り時にシードされるので、この機能より前に作られたワークスペースでも、何かが要求した瞬間に生えてきます。builtin はその行がどのシードから来たかを示すだけで、それ以上の意味はありません。6 つはワークスペースが自分の形に整えるための出発点であり、Owner を除くすべては名前の変更、パーミッションの変更、削除ができます。名前ではなく editable と deletable で分岐してください。名前を変えられたロールでもその 2 つは正しく返しますが、名前はもう何も教えてくれません。
唯一の例外は Owner で、あらゆる方向で例外です。editable: false、deletable: false であり、PATCH /members/{userId} の対象としても拒否されます。ワークスペースが紐づくアカウントを表し、将来のリリースで追加されるものも含めてすべてのパーミッションを持ちます。だからこそ、その一覧は保存されるのではなく計算されます。他の誰かをオーナーにするのはワークスペースの譲渡であり、それを行うエンドポイントはここにはありません。
残りの 5 つは何でも受け付けます。新しいパーミッション一覧、新しい説明、新しい名前、DELETE。これらは固定物ではなくシードされた既定値です。連携を一度も作らないワークスペースは Developer を消せるべきですし、「Member」がもっと狭い意味を持つワークスペースは、それを自分の言葉で書けるべきです。拒否するのはオーナーだけで、しかもすべてを 1 つのコードで拒否します。role_immutable、409 に param: "roleId" が付き、PATCH が名前を含んでいてもパーミッション一覧を含んでいても同じです。名前の変更だけが単独で拒否されることはもうないので、param: "name" の不変性を扱う必要はありません。名前が起こしうる唯一の 409 は role_name_taken で、ワークスペース上の別のロールがすでにその名前を持っている場合です。
6 つに加えて、ワークスペースは独自のロールを 24 個まで作れます。上限はそれだけを数えるので、シードされたロールを削除しても枠は空きません。パーミッションは字義どおりに受け取られるのではなく、受け入れ時に展開されます(templates:write だけを送っても templates:read と templates:write として保存されます)。したがって、送ったものと同じだと決めつけず、レスポンスから一覧を読み戻してください。
ロールは API キーの上限でもあります。あるロールに対して発行されたキーは key.scopes ∩ role.permissions の範囲でしか動けず、これは境界でリクエストごとに解決されます。そのためロールを編集すると、そのキーにできることは次の呼び出しから変わります。ロールのないキーには上限がまったくありません。詳細はスコープのページにあります。
例
roles:read が必要です。カーソルはありません。エンベロープには hasMore と nextCursor が入るので、クライアントは他のコレクションと同じ一覧処理に渡せます。2 ページ目が来ることはありません。
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}API の他の部分のような新しい順ではなく、組み込みの順位、次に名前で並びます(owner、admin、member、viewer、developer、billing、その後はアルファベット順)。権限マトリクスは梯子として読まれるものであり、createdAt で並べると最も広いロールが毎週違う行に現れます。
この一覧を読むことが、一度もロールを持ったことのないワークスペースに 6 つをシードするきっかけになります。シードは一意インデックスで競合し、2 回目は何もしないので、この呼び出しは冪等で、書き込むのは最初の 1 回だけです。そのおかげで POST /members は常に存在する roleId を指定できます。
シードは一度だけです。ワークスペースはシード済みであることを記録するので、この読み取りは機能より古いワークスペースを埋めたあとは二度と書き込みません。だからこそ、シードされたロールの削除は恒久的になります。以前のビルドでは読み取りのたびに欠けているテンプレート行を挿入し直していたため、削除した Billing が次のページ読み込みで新しい id になって戻ってきていました。今はそうなりません。
members と apiKeys は、ロールを削除する前に移す必要があるものです。そのおかげでクライアントは、409 を受けた後ではなく削除を提示する前に警告できます。オーナーの行はたいてい members: 0 です。オーナーは自分のワークスペースのメンバーではなく、ワークスペースが紐づくアカウントだからです。
カスタムロールには 24 という厳格な上限があり、まさにこれを 1 つのレスポンスに収めるためです。40 個のロールを持つワークスペースは「誰が billing@ として送信できるか」を見て答えられません。この機能は、その問いに答えられるようにするためだけに存在します。