Перейти к документации
API

Выдать и отозвать адрес

Вторая ось: к каким адресам один человек может обращаться и на каком уровне.

POSTapi.openemail.uk/members/{userId}/addresses

Выполняет любой из 2 запросов на этой странице в вашем рабочем пространстве, с вашим собственным ключом.

POST /members/{userId}/addresses

Вторая ось: к каким адресам один человек может обращаться и на каком уровне.

Доступ к адресу — это не роль

access — это более старый словарь уровней доступа к отдельному адресу, и он намеренно не пересекается с названиями разрешений: member читает адрес и отправляет от его имени, viewer только читает его. Он ничего не говорит о том, может ли человек вообще отправлять почту — это определяет его роль, и обе стороны должны разрешить отправку, прежде чем она произойдёт.

Их рольИх доступ к billing@Могут ли они отправлять от billing@
есть `emails:send`memberДа.
есть `emails:send`viewerНет, доступ к адресу этого не позволяет.
нет `emails:send`memberНет, роль этого не позволяет.
есть `emails:send`доступа нет вовсеНет, этот адрес вообще не попадает в список, по которому проверяется отправка.

Выдача роли не даёт человеку ни одного адреса. Участник с ролью и без выданных адресов откроет ПУСТОЙ почтовый ящик, а не ящик всех подряд, — и это правильный вид отказа, пока вы ещё решаете, что именно он должен видеть.

Выдать доступ к адресу

Требует members:write. POST /members/{userId}/addresses с { addressId, access }; access по умолчанию member. Возвращает участника целиком в его текущем состоянии.

curl
curl -X POST "$OE/members/nQ8vBz1aRd4tYwKx7fQ2mN8vBz1aRd4t/addresses" -H "$AUTH" \    -H "Content-Type: application/json" \    -d '{ "addressId": "c40a95f2-1cc6-4d31-82a8-9e075d31c2a8", "access": "viewer" }'
Ответ
{    "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"],    "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"  }

POST по подколлекции, а не PUT по паре, потому что это в любом случае upsert, а идентификатор строки клиент никогда не называет. Повторный POST с другим access — это способ превратить viewer в member: на пару (адрес, человек) существует ровно одна строка, поэтому второй вызов меняет уровень, а не добавляет второй доступ. Это же делает его тем редким POST, который безопасно повторять.

Ограничен members:write, а не владением адресом, — в этом и разница между ним и более старым путём выдачи доступа на роутере доменов. Владение — правильный критерий для того, кто добавил домен, и неправильный для администратора, который не владеет ничем и управляет доступом в рабочем пространстве от имени владельца. Оба пишут одну и ту же строку.

Возвращается участник целиком, а не один выданный доступ, чтобы строку на экране можно было перерисовать без второго запроса и чтобы ответ читался одинаково и при новой выдаче, и при её изменении.

Адрес, которого нет в этом рабочем пространстве, — это member_not_found, 422, с param: "addressId". Ключ может раздавать только адреса того рабочего пространства, для которого он был выпущен.

Выдача доступа ВЛАДЕЛЬЦУ рабочего пространства — это member_is_owner, 422. У него уже есть все адреса в нём, так что этот вызов ничего не смог бы добавить.

Отозвать адрес

Требует members:write. DELETE /members/{userId}/addresses/{addressId}. Возвращает участника без этого адреса.

curl
curl -X DELETE \    "$OE/members/nQ8vBz1aRd4tYwKx7fQ2mN8vBz1aRd4t/addresses/c40a95f2-1cc6-4d31-82a8-9e075d31c2a8" \    -H "$AUTH"
Ответ
{    "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"],    "addresses": [      {        "addressId": "2b81de07-9c1f-4a4b-8e05-d3862c1f0a44",        "address": "[email protected]",        "access": "member"      }    ],    "createdAt": "2026-08-12T14:20:00.000Z"  }

Узкий отзыв доступа, к которому стоит прибегать, когда человек переходит в другую команду: он сохраняет свою роль и остальные адреса и перестаёт видеть этот.

Адрес, которого нет в этом рабочем пространстве, отклоняется, а не игнорируется молча. Иначе опечатка в идентификаторе сообщала бы об успешном отзыве, которого не было, — а именно этот сбой данный эндпоинт и призван предотвратить.

Возвращается участник, а не надгробный камень, потому что интересен ответ на вопрос, до чего он всё ещё может дотянуться. { deleted: true } здесь заставило бы клиента вычислять это вычитанием.

Чтобы отобрать всё сразу, DELETE /members/{userId} снимает и роль, и все выданные доступы вместе и сообщает, сколько их было.