# Workspace and members

<!-- docs-test setup: owner -->
<!-- docs-test account: sam@example.com as SAM -->

A workspace holds sites and the people who work on them. Each person has a role, and the role decides their scopes:

| Role | Scopes |
|---|---|
| owner | everything (`account:admin`) |
| admin | everything except `billing:write` and deleting the account |
| member | every `:read` scope, plus `sites:write`, `bot:write`, `search:write` |
| viewer | `analytics:read`, `sites:read`, `bot:read`, `search:read` |

Only an owner (or a token with `account:admin`) makes, changes or removes an owner, and the last owner can neither be
demoted nor leave. Removing someone revokes every API token they made in the workspace; demoting them revokes those
that hold scopes the new role lacks. Plans limit members, counting pending invitations: Free 2, Starter 5, Growth
15, Business unlimited (`402` past the limit).

| Route | Scope |
|---|---|
| `GET /v1/workspace` | any member or token of the workspace |
| `PATCH /v1/workspace` | `members:write` |
| `GET /v1/members` | `members:read` |
| `POST /v1/members/invites` | `members:write` |
| `DELETE /v1/members/invites/{id}` | `members:write` |
| `POST /v1/invites/accept` | the invited person, signed in |
| `PATCH /v1/members/{userId}` | `members:write` |
| `DELETE /v1/members/{userId}` | `members:write`, or your own id to leave |

Changes to members are not available to site-restricted tokens. The examples assume `$US_TOKEN` holds a token with
`account:admin`, and that Sam (`sam@example.com`) has an account and is signed in with `sam-cookies.txt`.

## The workspace

```sh
curl https://api.usherstats.com/v1/workspace \
  -H "Authorization: Bearer $US_TOKEN"
```
<!-- expect 200 -->

The answer includes the plan, its `limits` (`null` is unlimited) and current `usage`.

```sh
curl -X PATCH https://api.usherstats.com/v1/workspace \
  -H "Authorization: Bearer $US_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Field Notes Ltd"}'
```
<!-- expect 200 -->

## Invite someone

The invitation email links to `https://app.usherstats.com/invite?token=...`; it expires in 7 days. Withdraw one
that is no longer wanted:

```sh
curl https://api.usherstats.com/v1/members/invites \
  -H "Authorization: Bearer $US_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"email": "alex@example.com", "role": "viewer"}'
```
<!-- expect 201; ALEX_INVITE=.invite.id -->

```sh
curl -X DELETE https://api.usherstats.com/v1/members/invites/$ALEX_INVITE \
  -H "Authorization: Bearer $US_TOKEN"
```
<!-- expect 204 -->

```sh
curl https://api.usherstats.com/v1/members/invites \
  -H "Authorization: Bearer $US_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"email": "sam@example.com", "role": "member"}'
```
<!-- expect 201 -->

Sam accepts while signed in with the invited address (an invitation for another address is `404`):

```sh
curl https://api.usherstats.com/v1/invites/accept -b sam-cookies.txt \
  -H "Content-Type: application/json" \
  --data @- <<EOF
{"token": "$INVITE_TOKEN"}
EOF
```
<!-- expect 200 -->

Sam now belongs to two workspaces, and picks this one per request with `X-Workspace`:

```sh
curl https://api.usherstats.com/v1/me -b sam-cookies.txt \
  -H "X-Workspace: $WORKSPACE_ID"
```
<!-- expect 200 -->

## Members

```sh
curl https://api.usherstats.com/v1/members \
  -H "Authorization: Bearer $US_TOKEN"
```
<!-- expect 200 -->

```sh
curl -X PATCH https://api.usherstats.com/v1/members/$SAM_ID \
  -H "Authorization: Bearer $US_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"role": "viewer"}'
```
<!-- expect 200 -->

The last owner cannot step down:

```sh
curl -X PATCH https://api.usherstats.com/v1/members/$OWNER_ID \
  -H "Authorization: Bearer $US_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"role": "admin"}'
```
<!-- expect 409 -->

Remove a member (or, with your own user id, leave):

```sh
curl -X DELETE https://api.usherstats.com/v1/members/$SAM_ID \
  -H "Authorization: Bearer $US_TOKEN"
```
<!-- expect 204 -->
