# Team
Source: https://docs.aden.space/docs/developers/concepts/team

The shared workspace that owns tracks, albums, sessions, and chat, plus members, invites, plans, and socials.
A **team** is the tenancy boundary in Aden. Every resource: tracks, albums,
sessions, chat, calendar events, contacts. Belongs to exactly one team.
Users belong to many teams and switch between them in the app.

If you're integrating against Aden, the team ID is the most important
parameter you'll pass.

## What a team represents [#what-a-team-represents]

A team can be a single artist, a band, a label imprint, or a production
studio. It carries:

* **Members**: users with a role on the team.
* **Plan**: the subscription tier that controls features and rate limits.
* **Identity**: name, avatar, socials, links shown on the public team page.
* **Media**: uploads attached to the team itself (press kit, brand assets).

## Data model [#data-model]

| Field        | Type             | Notes                                      |
| ------------ | ---------------- | ------------------------------------------ |
| `id`         | `number`         | Stable numeric ID.                         |
| `name`       | `string`         | Display name.                              |
| `slug`       | `string`         | URL-safe handle, used for the public page. |
| `avatar_url` | `string \| null` | Team avatar / logo.                        |
| `plan`       | `Plan`           | `free`, `air`, `pro`, `ultra`, `max`.      |
| `created_at` | `string`         | ISO 8601.                                  |
| `updated_at` | `string`         | ISO 8601.                                  |

Sub-resources:

* **Members**: the roster.
* **Invites**: pending email invites.
* **Socials**: Spotify, Instagram, TikTok, etc.
* **Media**: files attached to the team.
* **Plan**: current subscription state.

## Membership and roles [#membership-and-roles]

Members live in the `user_teams` table and carry a role. Roles are coarse
they gate which actions a user can take inside the team. Granular permissions
(like access to a specific track) layer on top via track-level
collaborators.

Endpoints:

* `GET /teams/{id}/members`: list members and roles.
* `PATCH /teams/{id}/members`: change a member's role.
* `DELETE /teams/{id}/members`: remove a member.

### Invites [#invites]

Invites are email-addressed and expire. The invitee accepts in the app and
becomes a member.

* `GET /teams/{id}/invites`: list pending invites.
* `POST /teams/{id}/invites`: send one.
* `DELETE /teams/{id}/invites`: revoke.

## Plans [#plans]

A team's plan controls which features are available and the per-action rate
limits. The plan hierarchy is:

```
free < air < pro < ultra < max
```

Read the current plan via `GET /teams/{id}/plan`. Plan changes are driven by
Polar webhooks: your integration never writes a plan directly. To gate a
feature in your own UI, check the team plan against
`packages/shared/src/plans/feature-plan-requirements.ts`.

## Socials and links [#socials-and-links]

Socials are surfaced on the team's public page and pulled into the calendar
for things like "release day post."

* `GET /teams/socials`: list across the user's teams.
* `POST /teams/socials`, `PATCH /teams/socials`, `DELETE /teams/socials`.

## Media [#media]

Team media is for assets attached to the workspace itself rather than a track
or album: press shots, EPKs, brand kits.

* `GET /teams/{id}/media`
* `POST /teams/{id}/media`
* `DELETE /teams/{id}/media/{mediaId}`

## Auth notes [#auth-notes]

A few endpoints in this section are **session-only**: they require a
Supabase user session, not an API key. Anything that mutates membership
(`/members`, `/invites`) and `/plan` is in this group, so a user is always
attached to the action.

API keys can read team data and operate on tracks/albums/sessions. See
[Authentication](/docs/developers/api/authentication) for the full split.

## Recipes [#recipes]

### Bootstrap a new team integration [#bootstrap-a-new-team-integration]

```ts
const { data: team } = await aden.api.v1.teams({ id: teamId }).get()
const { data: members } = await aden.api.v1.teams({ id: teamId }).members.get()
const { data: plan } = await aden.api.v1.teams({ id: teamId }).plan.get()

console.log(`${team.name} (${plan.tier}), ${members.length} members`)
```

### Invite a collaborator [#invite-a-collaborator]

```ts
await aden.api.v1.teams({ id: teamId }).invites.post({
    email: 'producer@example.com',
    role: 'editor',
})
```

### Mirror team socials into your CMS [#mirror-team-socials-into-your-cms]

```ts
const { data: socials } = await aden.api.v1.teams.socials.get()

for (const social of socials ?? []) {
    await cms.upsert('socials', { id: social.id, ...social })
}
```

## Related [#related]

* [Tracks](/docs/developers/concepts/tracks) and [Albums](/docs/developers/concepts/albums): what
  a team owns.
* [Authentication](/docs/developers/api/authentication): API keys vs. session tokens.
* [Rate limits](/docs/developers/api/rate-limits): per-plan ceilings.