پرش به مستندات
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 است و شناسهٔ سطر چیزی نیست که فراخوان‌کننده هرگز نامش را ببرد. ارسال دوبارهٔ همان درخواست با 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} نقش و همهٔ دسترسی‌های اعطاشده را با هم برمی‌دارد و گزارش می‌کند چند تا رفت.