Skip to content

Fetch a team with its direct parents

GET
/teams/{id}
id
required
string format: uuid

The team

object
id
required
string format: uuid
slug
required

URL-friendly identifier, unique per origin server. Used in display and (eventually) federation actor URIs.

string
<= 80 characters
Example
aurora-rnd
name
required
string
<= 200 characters
Example
Aurora R&D
description
required
string
<= 500 characters
origin_server_id

Set on rows mirroring a federated team. NULL = locally owned.

string format: uuid
nullable
hero_asset_id

The team’s picture (#982) — fetch it from /assets/{hero_asset_id}/variants/col. NULL means the client falls back to the team’s initials tile.

THIS IS THE RENDER ANSWER, NOT THE STORED SETTING. The server re-derives it on every read, and it is absent whenever the chosen asset no longer qualifies: set to restricted, moved to another team, soft-deleted, or still missing its col rendition. The stored pointer survives all of those, so restoring the asset brings the picture back without an admin re-picking it — but until then the wire says “no hero” and the client paints initials.

One field rather than the setting/render pair Collection carries, because the two cannot disagree PER READER here. ADR 0088 gates a representative image per viewer; #982 narrows that for a team, because the followed-teams rail is a navigation strip and a strip that shows some teams’ pictures and not others depending on who is looking is noise rather than security. A team hero is admissible only if it is public AND owned by that team — visible to everyone or to no one — so a single field cannot be misread.

It does NOT federate: a local asset id names something that exists only on this server.

string format: uuid
nullable
parents

Direct parent teams (single hop). Empty for root teams. Closure-walked ancestors live behind the listTeams ancestor filter; this field is just the edges out of the current node.

Array<object>
object
parent_id
required
string format: uuid
parent_slug
string
parent_name
string
member_count

Direct memberships. Present on listTeams — the directory card shows it (#684) — and ABSENT from getTeam.

The asymmetry is deliberate and is about staleness, not taste. getTeam reads through an LRU that only the team-row and parent-edge endpoints invalidate; adding a membership does not, and never needed to, because nothing membership-shaped was cached. A count served from that entry would go stale the first time somebody joined. The list path is uncached, so it can carry the number honestly.

A team page that wants the count reads GET /teams/{id}/members, which it already fetches for the member strip.

integer format: int64
content_count

Live (non-soft-deleted) assets carrying this team_id — the directory card’s “how much is in here” hint (#684). Present on listTeams only, for the same caching reason as member_count.

NOT visibility-filtered, deliberately. It counts assets whose fields the caller may not read. That discloses nothing new: this operation needs teams.read, so the caller is signed in, and the authenticated asset predicate already hands them restricted rows as placeholders — the same number is reachable by paging /assets?team_id=X. Filtering it would make the card disagree with the page it links to.

integer format: int64
created_at
required
string format: date-time
updated_at
required
string format: date-time

Authentication required, missing, or invalid

object
error
required

Human-readable error summary

string
Example
the request could not be completed
Example
{
"error": "authentication required: sign in and retry with a valid session or API token"
}

Authenticated but missing required capabilities

object
error
required

Human-readable error summary

string
Example
the request could not be completed

Resource not found

object
error
required

Human-readable error summary

string
Example
the request could not be completed