
Admins invite team members from the **Team** settings page. Clicking **Send invite** sends an automated email to the recipient with a link to accept the invitation. For security, that link is never shown in the dashboard — if the email doesn't arrive, use the **resend** control on the invite's row rather than sending a new invite. The invite appears in the **Pending Invitations** list until the recipient accepts or it expires automatically after 14 days.

## Send an invite

Only Admins see the **Invite member** button. If you do not see it, your role is not Admin — see [Roles and permissions](./roles-and-permissions.md).

{% steps %}

### Step 1 — Open the Team page

In the dashboard, go to **Settings → Team**. You will see the current member list and the **Role permissions** card.

### Step 2 — Click Invite member

The **Invite member** button is in the top right of the Team page header. It opens the **Invite team member** dialog.

### Step 3 — Enter the email and pick a role

Type the recipient's email address and choose **Admin**, **Member**, or **Viewer** from the role dropdown. See the [capability matrix](./roles-and-permissions.md#capability-matrix) for exactly what each role can do. **Member** can view reviews; they cannot configure repository settings, change organization settings, manage members, or change notification settings. To change someone's role after they have joined, use the **Change role** option in the three-dot action menu on their row (see [Roles and permissions](./roles-and-permissions.md#changing-someones-role)).

### Step 4 — Click Send invite

Click **Send invite** to submit the dialog. The new invite appears in the **Pending Invitations** list with the recipient's email, the inviting admin, the role badge, and an **Expires** date.

{% /steps %}

ADO Pilot has three organization roles. The **Role permissions** card on the **Team** settings page in the dashboard shows each role's description.

- **Admin** — Full access to all settings, billing, team management, and repository configuration.
- **Member** — Can view reviews. Cannot configure repository settings, change organization settings, manage members, or change notification settings.
- **Viewer** — Read-only access to review history and repository status. Cannot change settings.

| Capability                                  | Admin | Member | Viewer |
| ------------------------------------------- | ----- | ------ | ------ |
| View dashboard, reviews, and findings       | Yes   | Yes    | Yes    |
| View repository status and integration page | Yes   | Yes    | Yes    |
| View team members                           | Yes   | Yes    | Yes    |
| View pending invites                        | Yes   | No     | No     |
| View billing and subscription               | Yes   | Yes    | Yes    |
| Configure repository settings               | Yes   | No     | No     |
| Change notification settings                | Yes   | No     | No     |
| Test webhooks                               | Yes   | No     | No     |
| Invite team members                         | Yes   | No     | No     |
| Cancel pending invites                      | Yes   | No     | No     |
| Remove team members                         | Yes   | No     | No     |
| Start Stripe checkout                       | Yes   | No     | No     |
| Open the Stripe billing portal              | Yes   | No     | No     |
| Change the overage cap                      | Yes   | No     | No     |

## How long invites last

Pending invites expire **14 days** after they are sent. After that, the invite expires automatically and the invite link no longer works. Send a fresh invite if the recipient missed the window.

{% callout type="info" title="Expired invite recovery" %}
You do not need to do anything to clean up an expired invite — it disappears from the **Pending Invitations** list automatically. Just invite the person again from the Team page.
{% /callout %}

## Duplicates and conflicts

If you invite someone who is **already a member** of your org, or whose invite is **already pending**, ADO Pilot tells you and does not create a duplicate. For a pending invite, use the **resend** control on that invite's row rather than sending a new one.

| Situation                                | HTTP status | Message                                     |
| ---------------------------------------- | ----------- | ------------------------------------------- |
| Email is already a member of this org    | 409         | That user is already a member of this org   |
| An invite for the email is still pending | 409         | An invite is already pending for that email |
| Email or role is missing or malformed    | 400         | Invalid email or role                       |
| Caller is not an Admin                   | 403         | Only admins can invite team members         |

If you expected someone to receive an invite and they did not, check the **Members** and **Pending Invitations** lists on the Team page.

## Cancel a pending invite

In the **Pending Invitations** list, click the **Cancel invitation** icon (the red circled ✕) on the invite row, then confirm in the **Cancel invitation?** dialog. Once confirmed, the invite is deleted. If the recipient later opens the invite link, the link no longer resolves to a valid invite and they cannot join the org through it.

There is no undo. Send a new invite if you cancel by mistake.

## What the recipient sees

The recipient receives an email with a link to the dashboard's invite-acceptance flow. They open the link, accept the Terms of Service and Privacy Policy, set a password (or continue with Microsoft SSO if your org has it enabled), and verify a one-time code emailed to the same address before the invite completes. Once accepted, they appear in the **Members** list with the role you selected, the invite is removed from **Pending Invitations**, and they can sign in.

{% callout type="info" title="If a teammate gets stuck" %}
The recipient completes sign-in directly from the invite link — no separate approval step is required. If they run into trouble, open a [support request](../trust/support-and-contact.md) and we'll get them added.
{% /callout %}


