# Members and invitations

Memberships live on the LIVE organization and govern its test twin: manage them with the live id.

| Role | Scopes |
| --- | --- |
| `owner` | `organization:read`, `organization:write`, `members:read`, `members:write`, `service_accounts:read`, `service_accounts:write`, `issuers:read`, `issuers:write`, `series:read`, `series:write`, `invoices:read`, `invoices:emit`, `invoices:void`, `invoices:correct`, `events:read`, `webhooks:read`, `webhooks:write` |
| `admin` | `organization:read`, `organization:write`, `members:read`, `members:write`, `service_accounts:read`, `service_accounts:write`, `issuers:read`, `issuers:write`, `series:read`, `series:write`, `invoices:read`, `invoices:emit`, `invoices:void`, `invoices:correct`, `events:read`, `webhooks:read`, `webhooks:write` |
| `operator` | `organization:read`, `issuers:read`, `series:read`, `invoices:read`, `invoices:emit`, `invoices:correct`, `events:read` |
| `viewer` | `organization:read`, `issuers:read`, `series:read`, `invoices:read` |

## A person joins by invitation

1. An owner or admin calls `POST /v1/invitations` (permission `members:write`; `Idempotency-Key` required) with the `email` and the `role`. The service writes to that address with a code. The code is never returned by the API; `delivery` says whether the email went out.

2. The invited person signs in (see [getting a credential](https://api.invox.page/v1/docs/start)) and calls `POST /v1/invitations/accept` (a person's access token) with that code as `token`. The email of their account must be VERIFIED and equal to the invited one. The answer carries the id of the organization to send in `X-Organization`.

An invitation lasts 7 days. `GET /v1/invitations` lists them; `POST /v1/invitations/{id}/resend` sends a new code (the previous one stops working); `DELETE /v1/invitations/{id}` revokes it.

Accepting can refuse with: [`invitation_not_found`](https://api.invox.page/v1/errors/invitation_not_found), [`invitation_expired`](https://api.invox.page/v1/errors/invitation_expired), [`email_not_verified`](https://api.invox.page/v1/errors/email_not_verified), [`invitation_email_mismatch`](https://api.invox.page/v1/errors/invitation_email_mismatch). Inviting can refuse with: [`live_organization_required`](https://api.invox.page/v1/errors/live_organization_required), [`scope_not_grantable`](https://api.invox.page/v1/errors/scope_not_grantable), [`already_member`](https://api.invox.page/v1/errors/already_member).

## Changing and removing

`PUT /v1/members/{user_id}` (permission `members:write`) changes the role of someone who is already a member; `DELETE /v1/members/{user_id}` (permission `members:write`) removes them. Only an owner grants or removes the owner role, and an organization always keeps one ([`last_owner`](https://api.invox.page/v1/errors/last_owner)). The service accounts and keys a person created keep working: they belong to the organization.
