---
title: Invitations
description: Inviting people to a workspace, setting their role and board access, and managing invitations until they are accepted.
section: Workspaces and access
order: 2
---

# Invitations

Nobody joins a workspace without being invited and accepting. Inviting an address
that already has a Laver account does **not** silently add them — they get a
prompt and choose.

**You need to be an owner or an admin.** Everyone else gets
`403 {"error": "Admin access required."}`.

## Send an invitation

1. Open **Admin**, then the **Invite someone** panel.
2. Enter the email address.
3. Choose the role: **admin**, **member** or **viewer**.
4. If the role is member or viewer, tick the boards they should reach.
5. Send.

The invitation is saved first and the email is sent second, so a bounced or
delayed email never means the invitation quietly failed to exist. If sending
fails you will be told, and the invitation is waiting in the **Invitations** tab
to resend.

## Choosing their role

You can invite someone as an **admin**, a **member** or a **viewer**. You cannot
invite someone as an owner — a workspace has one owner and ownership only moves
by transfer.

Pick with the seat cost in mind: admins and members are billable seats, viewers
are free. See [Roles and permissions](/docs/workspaces-and-access/roles-and-permissions).

## Granting board access at invite time

Board access is part of the invitation, so people land with the right boards
already open rather than needing a second round of admin.

- **Admins** get every board automatically. Any boards you tick for an admin
  invitation are ignored and stored as an empty list.
- **Members and viewers** get exactly the boards you tick, and nothing else.
  Ticking none is allowed — they will join and see no boards until someone grants
  them access.
- Every board you tick has to belong to this workspace and not be archived.
  Otherwise the invitation is refused with
  `400 {"error": "One or more boards do not belong to this workspace."}`.

Board access can be changed at any time afterwards from **Admin → People**.

## What the invitee receives

An email from your workspace, naming the workspace and whoever invited them. The
link it carries depends on whether the address already has a Laver account:

| The address                 | The link goes to                          | What they do                                                                         |
| --------------------------- | ----------------------------------------- | ------------------------------------------------------------------------------------ |
| Has no Laver account        | The sign-up page, carrying the invitation | They create their account, and the invitation is accepted as part of signing up      |
| Already has a Laver account | The sign-in page                          | They sign in, and the invitation is waiting for them in the app to accept or decline |

An invited person does not have to verify their email address separately —
clicking a link that arrived in their own inbox already proves the address.

## Expiry

An invitation is valid for **7 days**. After that both the emailed link and the
invitation itself stop working, and the invitee is told it is invalid or expired.

Expired invitations stay listed in the **Invitations** tab, marked as expired, so
you can resend rather than retype.

## Resending

Resending an invitation sends the email again _and_ resets the clock: the
invitation becomes valid for a fresh 7 days from the moment you resend. That is
how you revive an expired one.

## Revoking

Revoking an invitation withdraws it immediately. The emailed link stops working
even if it has not expired, and the invitation disappears from the pending list.
Revoking is recorded in the audit log.

Three other things revoke a pending invitation automatically:

- **Re-inviting the same address to the same workspace.** The new invitation
  supersedes the old one, so there is only ever one live invitation per address
  per workspace. Use this to correct a role or a board list — just invite again.
- **The invitee declining it.**
- **Removing that person from the workspace**, if they were already a member.

## What happens on acceptance

When the invitation is accepted:

- A membership is created with the role from the invitation.
- Board access is set to exactly the boards on the invitation — for a member or
  viewer, any board access they previously had in this workspace is replaced, not
  added to. (Admins get every board and no explicit grants.)
- If they were already a member of the workspace, their role and active status are
  updated to match the invitation. Accepting an invitation can therefore promote,
  demote or reactivate an existing member.
- The invitation is marked accepted and stops being usable.
- Seats are recounted and, if the workspace has a subscription, sent to Stripe
  straight away. A mid-cycle addition is prorated.
- `member.joined` is written to the audit log. Declining writes `member.declined`.

## Outstanding invitations hold a seat

An invitation for an **admin** or **member** counts against your plan's seat limit
from the moment you send it, not from the moment it is accepted.

This is why: without it, ten pending invitations could take a workspace well past
its seat limit before a single person accepted, and the bill would only catch up
afterwards. Viewer invitations do not count, because viewers are never billed.

An invitation stops holding a seat as soon as it is accepted (at which point the
membership holds it instead), revoked, or expired.

If you are at the limit, the invitation is refused with **402** and a message
naming the plan, the limit and the current count, along with the current prices.
Free up a seat — or [upgrade](/docs/administration/billing) — and send it again.

## Limits and errors

| What happened                                                                 | Response                                                                                              |
| ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| You are not an owner or admin                                                 | `403 Admin access required.`                                                                          |
| A board does not belong to this workspace, or is archived                     | `400 One or more boards do not belong to this workspace.`                                             |
| The workspace is at its seat limit                                            | `402` with the plan message and current prices                                                        |
| The workspace has an unpaid invoice                                           | `402 This workspace has an unpaid invoice. Update the payment method in Billing to add anything new.` |
| Resending or revoking an invitation that is already accepted, revoked or gone | `404 Pending invitation not found.`                                                                   |

Invitation sending is rate limited to **20 per hour** per person, on top of the
usual API rate limit.

## Using the API

Invitations are managed under `/admin`, which accepts **session tokens only** — an
API key cannot send, resend or revoke an invitation.

| Action                           | Call                                                                                      |
| -------------------------------- | ----------------------------------------------------------------------------------------- |
| List pending invitations         | `GET /admin/workspaces/<workspace-uuid>/invitations`                                      |
| Send one                         | `POST /admin/workspaces/<workspace-uuid>/invitations` with `email`, `role`, `board_uuids` |
| Resend one                       | `POST /admin/workspaces/<workspace-uuid>/invitations/<invitation-uuid>/resend`            |
| Revoke one                       | `DELETE /admin/workspaces/<workspace-uuid>/invitations/<invitation-uuid>`                 |
| See invitations addressed to you | `GET /workspaces/invitations`                                                             |
| Accept or decline one            | `POST /workspaces/invitations/<invitation-uuid>/respond` with `{"accept": true}`          |

`board_uuids` is required on send, even for an admin invitation — pass `[]`.
Sending any field that is not declared is rejected with 400.
