Aden
Features

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

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

FieldTypeNotes
idnumberStable numeric ID.
namestringDisplay name.
slugstringURL-safe handle, used for the public page.
avatar_urlstring | nullTeam avatar / logo.
planPlanfree, air, pro, ultra, max.
created_atstringISO 8601.
updated_atstringISO 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

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 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

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 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

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

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 for the full split.

Recipes

Bootstrap a new team integration

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

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

Mirror team socials into your CMS

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

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

On this page