> ## Documentation Index
> Fetch the complete documentation index at: https://usenaive.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Teams

> GET /v1/teams and GET /v1/teams/{team}/tenants/{tenantUserId} — enumerate teams (refused today) and read the header the board prints above everything.

## List teams

```
GET /v1/teams
```

<Warning>
  **This operation answers `501 not_configured` in this build, and the reason is
  worth knowing before you design around it.**

  A declared team's name is stored in `agents.metadata` under a JSONB key spelled
  with a word the repository's vocabulary gate has retired, and every package that
  could host an accessor is already at its recorded ceiling for that word. Renaming
  the key with a migration is the fix; the API refuses rather than working around
  it, and says exactly this on the wire.

  Practical consequence: **you must already know your team name.** It comes from
  your `naive.config.ts`, not from this API. Every other operation on this surface
  takes `{team}` as a routing segment and works fine.
</Warning>

```json 501 theme={"theme":"css-variables"}
{
  "error": {
    "code": "not_configured",
    "message": "Team enumeration is not available in this build.",
    "details": {
      "surface": "durable-runtime",
      "missing": [
        "team storage: a declared team's name lives in `agents.metadata` under the retired spelling of `team`, and ci/vocabulary.test.ts rule 8 is at its recorded ceiling in every package that could host an accessor (packages/api 67, packages/db 6, platform/identity 4). Renaming that JSONB key to `config_team` with a migration is the fix; raising an allowance is not.",
        "durable runtime seam: no manifest, digest or fence storage exists, so `fence`, `digests` and `brain_partition` have nothing to report"
      ]
    }
  }
}
```

The request is still authorised before it is refused, so a bad credential gets
`401` and a good one gets `501`. The refusal is not an oracle for whether your
company exists.

***

## Get a team at a tenant

```
GET /v1/teams/{team}/tenants/{tenantUserId}
```

The header the board and the CLI print above everything: which runtime the tenant
is on, the six board counts, and spend over the tenant's own budget window.

<RequestExample>
  ```bash theme={"theme":"css-variables"}
  curl "https://api.usenaive.ai/v1/teams/support/tenants/8f1c…/" \
    -H "Authorization: Bearer nv_sk_live_..."
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={"theme":"css-variables"}
  {
    "team": "support",
    "tenant_user_id": "8f1c…",
    "runtime": "hermes",
    "provider": "hermes",
    "counts": {
      "open": 4,
      "claimed": 1,
      "awaiting_check": 0,
      "done": 12,
      "unverified": 1,
      "blocked": 2
    },
    "spend": {
      "spent_cents": 1840,
      "cap_cents": 5000,
      "class": "reserve",
      "enforced": true
    },
    "period": { "name": "month", "start": "2026-07-01T00:00:00.000Z" },
    "digests": null,
    "fence": null,
    "stop": null,
    "unavailable_because": {
      "digests": "no manifest or snapshot digest is stored in this build",
      "fence": "the apply fence requires an applied digest to compare against; none is stored",
      "stop": "a team-level stop is a durable-runtime state; the legacy runtime has no equivalent row"
    }
  }
  ```
</ResponseExample>

### Path parameters

| Name           | Description                                                                      |
| -------------- | -------------------------------------------------------------------------------- |
| `team`         | Your declared team name. Echoed back; not used as a storage key in this build.   |
| `tenantUserId` | A `tenant_users.id`. The same id the legacy `/v1/users/{user_id}/…` routes take. |

### Reading `spend`

`class` and `enforced` are the two fields that decide whether `cap_cents` is a
ceiling or an alert. Do not read `cap_cents` on its own.

| `class`   | `enforced` | what happens at the cap                                                                         |
| --------- | ---------- | ----------------------------------------------------------------------------------------------- |
| `reserve` | `true`     | the amount is reserved atomically **before** the action executes; over-cap actions are refused  |
| `meter`   | `false`    | the spend is recorded; nothing is refused. A soft cap escalates to approval, no cap meters only |

`period` is the tenant's **own budget window**, taken from its AccountKit — not a
calendar month. Reporting spend over a month while the cap resets weekly produces
a number that looks like a fraction of a cap and is not one. With no budget
declared, `period.name` is `month` because that is the conventional reporting
window, and `cap_cents` is `null`.

### `runtime` and `provider` are the same value

Both are emitted, and both carry `hermes` or `durable`. They are duplicated so a
client written against either name reads the true value.

<Note>
  **`counts` is derived from two legacy columns.** The six board columns are
  computed from `tasks_mirror.status` and `tasks_mirror.verification_status` by a
  single reader. There is no database constraint making those two columns agree, so
  a card whose legacy status the reader cannot classify is counted as `open` rather
  than dropped — an invisible card is how work is lost. See
  [Board](/docs/api-reference/runtime/board) for the full mapping.
</Note>
