---
title: "Grant and revoke a domain"
description: "A whole domain at once: every address on it, including ones added later."
url: "https://openemail.uk/docs/api/members/domains"
area: "API"
category: "Roles & access"
---

# Grant and revoke a domain

A whole domain at once: every address on it, including ones added later.

`POST /members/{userId}/domains`

**Also documents:** `DELETE /members/{userId}/domains/{domainId}`

## POST /members/{userId}/domains

A whole domain at once: every address on it, including ones added later.

## Grant a domain

Needs `members:write`. `POST /members/{userId}/domains` with `{ domainId, access }`; `access` defaults to `member`. Returns the whole member as they now stand, with the grant in `domains`.

**curl**

```
curl -X POST "$OE/members/nQ8vBz1aRd4tYwKx7fQ2mN8vBz1aRd4t/domains" -H "$AUTH" \
    -H "Content-Type: application/json" \
    -d '{ "domainId": "7d2a9c41-5b3e-4f8a-9c06-1e2b3c4d5e6f", "access": "viewer" }'
```

**Response**

```
{
    "object": "member",
    "userId": "nQ8vBz1aRd4tYwKx7fQ2mN8vBz1aRd4t",
    "email": "sam@acme.com",
    "role": { "id": "role_2b81de079c1f0a4b7e05d386", "name": "Support", "builtin": null },
    "addresses": [],
    "domains": [
      {
        "domainId": "7d2a9c41-5b3e-4f8a-9c06-1e2b3c4d5e6f",
        "domain": "acme.com",
        "access": "viewer"
      }
    ]
  }
```

> An upsert, like an address grant: posting again with a different `access` changes the grant rather than adding a second one.

> A domain grant reaches every address on the domain, including addresses added after it, so it is the grant for somebody who looks after a whole domain. Addresses granted one by one stay as they are beside it.

> The person has to be in the workspace already, so invite them with `POST /members` first. The owner is refused with `member_is_owner`, because they reach every domain, and a workspace whose plan has no team access is refused with 403 `plan_required`.

> A key or an app limited to particular addresses or domains is refused with 422 `capability_unsupported`, and an app acting for a member can only give a domain that member reaches.

> An OAuth access token needs a verification code for this call. Until the app has verified one in the last 60 minutes, the call answers `403` `step_up_required` and changes nothing. An API key is never asked. The Authentication page shows how to ask for a code and verify it.

## Revoke a domain

Needs `members:write`. `DELETE /members/{userId}/domains/{domainId}`. Returns the member, minus that domain.

**curl**

```
curl -X DELETE \
    "$OE/members/nQ8vBz1aRd4tYwKx7fQ2mN8vBz1aRd4t/domains/7d2a9c41-5b3e-4f8a-9c06-1e2b3c4d5e6f" \
    -H "$AUTH"
```

**Response**

```
{
    "object": "member",
    "userId": "nQ8vBz1aRd4tYwKx7fQ2mN8vBz1aRd4t",
    "email": "sam@acme.com",
    "role": { "id": "role_2b81de079c1f0a4b7e05d386", "name": "Support", "builtin": null },
    "addresses": [],
    "domains": []
  }
```

> Addresses on the domain that were granted one by one stay granted, and the person keeps their role.

> A domain that is not on this workspace is refused with 422 `member_not_found` rather than quietly ignored.

> An OAuth access token needs a verification code for this call. Until the app has verified one in the last 60 minutes, the call answers `403` `step_up_required` and changes nothing. An API key is never asked. The Authentication page shows how to ask for a code and verify it.

## Reference

- [`POST /members/{userId}/domains`](https://openemail.uk/docs/api/reference/members#post-members-userid-domains): full reference
- [`DELETE /members/{userId}/domains/{domainId}`](https://openemail.uk/docs/api/reference/members#delete-members-userid-domains-domainid): full reference
