Výpis rolí
Všechny role v pracovním prostoru, vestavěné první, s počtem lidí a klíčů, které každou z nich drží.
Spustí skutečné volání proti vašemu pracovnímu prostoru, s vaším vlastním klíčem.
GET /roles
Všechny role v pracovním prostoru, vestavěné první, s počtem lidí a klíčů, které každou z nich drží.
Dvě osy, a není to tatáž otázka
export OE=https://api.openemail.ukexport AUTH="Authorization: Bearer $OPENEMAIL_API_KEY"ROLE říká, co někdo v tomto pracovním prostoru SMÍ DĚLAT: číst poštu, odesílat ji, upravovat šablony, přidat doménu. GRANT říká, ke kterým ADRESÁM to smí dělat, a bydlí hned vedle na /members/{userId}/addresses jako member (čte adresu a odesílá jako ona) nebo viewer (jen ji čte). Než zpráva odejde, musí se shodnout obojí: role s emails:send a bez jediného grantu neodešle z ničeho a z každé adresy v pracovním prostoru pod grantem viewer se také odeslat nedá.
Každý pracovní prostor dostane stejných šest základních rolí. Owner, Admin, Member a Viewer tvoří žebřík. Každá drží všechno, co ta následující, takže degradace někomu přístup zúží, místo aby ho vyměnila za jiný výsek. Developer a Billing na něm příčky nejsou: Developer staví integrace (klíče, webhooky, šablony, odesílání) a z pošty pracovního prostoru nečte nic, Billing vidí tarif a faktury a nic jiného. Obě leží striktně uvnitř Admin. Zakládají se při prvním čtení, ne při vzniku pracovního prostoru, takže prostor vytvořený dřív, než tato funkce existovala, je získá ve chvíli, kdy se na ně cokoli zeptá. builtin pojmenovává, z které předlohy řádek vznikl, a nic víc: těch šest je výchozí bod, který si má prostor přetvořit, a všechny kromě Owner lze přejmenovat, přenastavit jim oprávnění i smazat. Větvete podle editable a deletable, ne podle jména: přejmenovaná role na tyto dvě otázky stále odpovídá správně, zatímco její jméno vám už neřekne nic.
Owner je jediná výjimka, a to výjimka na všechny strany: editable: false, deletable: false, a jako cíl PATCH /members/{userId} je odmítnut. Popisuje účet, na který je pracovní prostor navázán, a drží všechna oprávnění včetně těch přidaných v pozdějším vydání — proto se jeho seznam počítá, místo aby se ukládal. Udělat vlastníkem někoho jiného znamená převést pracovní prostor; endpoint, který by to udělal, tu není.
Zbylých pět přijme cokoli: nový seznam oprávnění, nový popis, nové jméno, DELETE. Jsou to výchozí předlohy, ne pevné inventáře: prostor, který nikdy nestaví integraci, se má umět Developer zbavit, a ten, kde „Member“ znamená něco užšího, to má umět říct vlastními slovy. Odmítá jen vlastník, a odmítá všechno pod jedním kódem: role_immutable, 409 s param: "roleId", ať už PATCH nesl jméno, nebo seznam oprávnění. Samotné přejmenování se už neodmítá, takže žádnou neměnnost s param: "name" řešit nemusíte; jediná 409, kterou jméno ještě může vyvolat, je role_name_taken, když už na ně v pracovním prostoru slyší jiná role.
Nad rámec těch šesti si prostor zapíše až 24 vlastních rolí. Strop počítá jen je, takže smazáním základní role se pod ním místo neuvolní. Oprávnění se na vstupu ROZBALUJÍ, neberou se doslova (samotné templates:write se uloží jako templates:read a templates:write), takže si seznam přečtěte zpátky z odpovědi, místo abyste předpokládali, že je to ten, který jste poslali.
Role je zároveň strop pro API klíč. Klíč vydaný pod ní smí key.scopes ∩ role.permissions a nic víc; vyhodnocuje se to na hranici při každém požadavku, takže úprava role mění, co její klíče smějí, hned při jejich dalším volání, a klíč bez role nemá strop žádný. Celé je to na stránce Rozsahy.
Příklad
Vyžaduje roles:read. Bez kurzoru. Obálka nese hasMore a nextCursor, aby ji klient mohl předat stejnému kódu pro seznamy jako každou jinou kolekci, a druhá stránka nikdy nepřijde.
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}Řazeno podle pořadí vestavěných rolí, pak podle jména (owner, admin, member, viewer, developer, billing, zbytek abecedně), ne od nejnovějšího jako zbytek API. Matice oprávnění se čte jako žebřík a řazení podle createdAt by nejširší roli každý týden posunulo na jiný řádek.
Právě čtení tohoto seznamu ZALOŽÍ těch šest rolí v prostoru, který žádné neměl. Zakládání koliduje na unikátním indexu a podruhé neudělá nic, takže je volání idempotentní a zapisuje jen to první — proto také POST /members může vždy uvést roleId, které existuje.
Zakládá se JEDNOU. Prostor si poznamená, že už založeno bylo, takže toto čtení doplní prostor starší než tato funkce a pak už nikdy nezapíše — a právě proto je smazání základní role trvalé. Starší sestavení při každém čtení znovu vkládalo chybějící řádek z předlohy, takže smazaný Billing se při dalším načtení stránky vrátil pod novým id; to už se neděje.
members a apiKeys říkají, co by se muselo přesunout, než role může zmizet — díky tomu může klient varovat, ještě než smazání nabídne, a ne až po 409. Řádek vlastníka obvykle uvádí members: 0: vlastník není členem vlastního pracovního prostoru, je to účet, na který je prostor navázán.
Tvrdý strop 24 vlastních rolí existuje právě proto, aby se tohle vešlo do jedné odpovědi. Prostor se čtyřiceti rolemi neodpoví pohledem na otázku „kdo smí odesílat jako billing@“, a přitom je to jediná otázka, kvůli které tato funkce existuje.