---
title: Managing your team
eyebrow: Organizations
description: "Members and invites, verified domains and SSO, organization API keys, and bringing your own storage."
---

# Managing your team

Everything an owner or admin does after the organization exists: who is in it, how they get in, what authenticates on its behalf, and where its files live. [Teams and organizations](./organizations.html) covers the context itself, the roles, and the shared credits and usage every member can read.

![Shared organization work connected around one context](../assets/art/organizations.jpg)

> [!NOTE]
> Every write on this page needs the `owner` or `admin` role, and none of them can be made by an agent credential: those receive `403` with `agent_cannot_change_organization`. Do it in the app or with your own token.

## Members

<!-- gen:endpoints paths=/organizations/{id}/members,/organizations/{id}/members/{user_id},/organizations/{id}/transfer-ownership -->
| Method | Path | What it does |
| --- | --- | --- |
| [GET](../api/#tag/organizations/get/organizations/{id}/members) | `/organizations/{id}/members` | List an organization's members (any member may read). |
| [PATCH](../api/#tag/organizations/patch/organizations/{id}/members/{user_id}) | `/organizations/{id}/members/{user_id}` | Change a member's role or monthly credit budget (owner or admin). |
| [DELETE](../api/#tag/organizations/delete/organizations/{id}/members/{user_id}) | `/organizations/{id}/members/{user_id}` | Remove a member (owner or admin), or leave the organization (self). |
| [POST](../api/#tag/organizations/post/organizations/{id}/transfer-ownership) | `/organizations/{id}/transfer-ownership` | Transfer ownership to another member (owner only). |
<!-- /gen -->

Any member may read the member list. As an owner or admin you can change a member's role or their monthly credit budget, and remove them. A member can also remove themselves, which is how you leave an organization.

The owner is the exception: transfer ownership first, with `POST /organizations/{id}/transfer-ownership`, and the previous owner becomes an admin. Removing someone also stops their organization API keys from authenticating, so revoking access is one action rather than two.

## Invites

<!-- gen:endpoints paths=/organizations/{id}/invites,/organizations/{id}/invites/{invite_id},/organizations/{id}/invites/{invite_id}/resend -->
| Method | Path | What it does |
| --- | --- | --- |
| [GET](../api/#tag/organizations/get/organizations/{id}/invites) | `/organizations/{id}/invites` | List pending invites (owner or admin). |
| [POST](../api/#tag/organizations/post/organizations/{id}/invites) | `/organizations/{id}/invites` | Invite an email address to the organization (owner or admin). |
| [DELETE](../api/#tag/organizations/delete/organizations/{id}/invites/{invite_id}) | `/organizations/{id}/invites/{invite_id}` | Revoke a pending invite (owner or admin). |
| [POST](../api/#tag/organizations/post/organizations/{id}/invites/{invite_id}/resend) | `/organizations/{id}/invites/{invite_id}/resend` | Rotate a pending invite's token, extend its expiry and re-send the email (owner or admin). |
<!-- /gen -->

An invite is addressed to one email address and lasts seven days. Its plaintext token and URL are returned **once**, when the invite is created or resent, so capture them from that response; resending rotates the token and extends the expiry. The signed-in account accepting an invite has to match the address it was sent to.

Pending invites that consume a seat count against the seat limit before they are accepted, so an organization cannot oversubscribe itself by inviting. Viewer invites do not consume a seat.

## Verified domains

<!-- gen:endpoints paths=/organizations/{id}/domains,/organizations/{id}/domains/{domain},/organizations/{id}/domains/{domain}/verify -->
| Method | Path | What it does |
| --- | --- | --- |
| [GET](../api/#tag/organizations/get/organizations/{id}/domains) | `/organizations/{id}/domains` | List the organization's claimed email domains (owner or admin). |
| [POST](../api/#tag/organizations/post/organizations/{id}/domains) | `/organizations/{id}/domains` | Claim an email domain (owner or admin); returns the DNS TXT record to publish. |
| [PATCH](../api/#tag/organizations/patch/organizations/{id}/domains/{domain}) | `/organizations/{id}/domains/{domain}` | Toggle auto-join or SSO enforcement on a domain (owner or admin). |
| [DELETE](../api/#tag/organizations/delete/organizations/{id}/domains/{domain}) | `/organizations/{id}/domains/{domain}` | Remove a claimed domain (owner or admin). |
| [POST](../api/#tag/organizations/post/organizations/{id}/domains/{domain}/verify) | `/organizations/{id}/domains/{domain}/verify` | Check DNS for the verification TXT record and mark the domain verified (owner or admin). |
<!-- /gen -->

Claiming a domain proves you control the addresses in it, which is what lets colleagues join without an individual invite.

1. `POST /organizations/{id}/domains` returns a TXT record to publish at `_nolgia.<domain>`.
2. Publish it in your DNS.
3. `POST /organizations/{id}/domains/{domain}/verify` reads DNS and marks the domain verified.

A missing or mismatched record answers `409`, and so does a domain another organization has already verified. Once verified, `PATCH /organizations/{id}/domains/{domain}` turns on auto-join, so a new account with an address in that domain lands in the organization, and SSO enforcement, which requires a verified domain and an enterprise organization.

## Organization API keys

<!-- gen:endpoints paths=/organizations/{id}/api-keys,/organizations/{id}/api-keys/{key_id} -->
| Method | Path | What it does |
| --- | --- | --- |
| [GET](../api/#tag/organizations/get/organizations/{id}/api-keys) | `/organizations/{id}/api-keys` | List the organization's API keys, no secrets (owner or admin). |
| [POST](../api/#tag/organizations/post/organizations/{id}/api-keys) | `/organizations/{id}/api-keys` | Create an organization API key (owner or admin). The plaintext token is returned ONCE. |
| [DELETE](../api/#tag/organizations/delete/organizations/{id}/api-keys/{key_id}) | `/organizations/{id}/api-keys/{key_id}` | Revoke an organization API key (owner or admin). |
<!-- /gen -->

An organization API key authenticates as the organization rather than as a person: it is bound to the organization it was created for and never follows anyone's active context. It carries its creator's current role, and it stops working when their membership ends.

The plaintext token is returned once, at creation. Store it where your application reads its secrets, and revoke it with `DELETE /organizations/{id}/api-keys/{key_id}` rather than rotating in place. [Get your API key](./authentication.html#organization-api-keys) has the token format and how it differs from a personal one.

## Bring your own storage

<!-- gen:endpoints prefix=/organizations/{id}/storage-connections -->
| Method | Path | What it does |
| --- | --- | --- |
| [GET](../api/#tag/organizations/get/organizations/{id}/storage-connections) | `/organizations/{id}/storage-connections` | List the organization's bring-your-own storage connections (owner or admin; Enterprise). |
| [POST](../api/#tag/organizations/post/organizations/{id}/storage-connections) | `/organizations/{id}/storage-connections` | Connect an S3-compatible bucket to the organization (owner or admin; Enterprise). |
| [PATCH](../api/#tag/organizations/patch/organizations/{id}/storage-connections/{connection_id}) | `/organizations/{id}/storage-connections/{connection_id}` | Update a storage connection (owner or admin; Enterprise). |
| [DELETE](../api/#tag/organizations/delete/organizations/{id}/storage-connections/{connection_id}) | `/organizations/{id}/storage-connections/{connection_id}` | Disconnect a storage connection (owner or admin; Enterprise). |
| [POST](../api/#tag/organizations/post/organizations/{id}/storage-connections/{connection_id}/test) | `/organizations/{id}/storage-connections/{connection_id}/test` | Probe a storage connection (owner or admin; Enterprise). |
| [POST](../api/#tag/organizations/post/organizations/{id}/storage-connections/{connection_id}/import) | `/organizations/{id}/storage-connections/{connection_id}/import` | Import objects from the connected bucket into the organization library (owner or admin; Enterprise). |
| [POST](../api/#tag/organizations/post/organizations/{id}/storage-connections/{connection_id}/backfill) | `/organizations/{id}/storage-connections/{connection_id}/backfill` | Queue every ready organization asset for mirroring to this connection (owner or admin; Enterprise). |
<!-- /gen -->

On an enterprise plan, an organization can keep its media in its own S3-compatible bucket. Create the connection, then `POST /organizations/{id}/storage-connections/{connection_id}/test` and read the status it returns before trusting it: a connection that cannot be probed is a configuration to fix, not something to discover at the first upload.

Two directions are available once it works. `import` brings objects that are already in the bucket into the organization's Library, and `backfill` queues every ready organization asset for mirroring into the bucket. With mirroring enabled, new assets are copied as they become ready.

## The audit trail

Every administrative action above is recorded. `GET /organizations/{id}/audit-events` lists them newest first, filtered by `action` or `actor`, and enterprise organizations can download the whole trail as CSV. See [Teams and organizations](./organizations.html#audit-events).

:::cards
- [Teams and organizations](./organizations.html) icon=spot-organizations: The active context, roles, shared credits and usage.
- [Get your API key](./authentication.html) icon=spot-keys: Personal tokens, organization keys and what each one may do.
- [Storage and retention](./storage.html) icon=spot-upload: Where files live, how long they last and how they are served.
:::
