> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.runledger.co/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.runledger.co/_mcp/server.

# Members, teams and agents

A customer is usually an organization. Inside it are people, teams and the agents that act for them. Runledger attributes usage to them with three labels you send, and doesn't model them as objects.

## Before you start

* You call [`check()` and `track()`](/concepts/checks-and-holds) for each piece of work.

| Field       | Is                                       | Where you send it               |
| ----------- | ---------------------------------------- | ------------------------------- |
| `agent_id`  | Your ID for the agent doing the work     | `check()`, `track()`, `trace()` |
| `member_id` | Your ID for a person inside the customer | `check()`, `track()`, `trace()` |
| `team_id`   | Your ID for a team inside the customer   | `check()`, `track()`, `trace()` |

All three are strings up to 128 characters. Send them on every call for the same work, and they are recorded on the hold, the event, the cost and the ledger entries. The ledger can be filtered by `member_id` and `team_id`, and the usage summary takes `member_id`.

**`POST /v1/check`**

```json title="POST /v1/check"
{
  "external_customer_id": "org_123",
  "event_name": "agent.task",
  "quantity": "1",
  "hold": true,
  "agent_id": "agent_billing_bot",
  "member_id": "user_2231",
  "team_id": "team_growth",
  "run_id": "run_01JD7Q2W"
}
```

Runledger keeps no list of members or teams. A `member_id` exists once you send one. Your own system decides who belongs where and what to call them, and Runledger never needs to look anyone up.

## Caps for a person, a team or an agent

[Spend limits](/guides/spend-limits) take `member_id`, `team_id` and `agent_id` in `applies_to`. Use them for budgets such as "each member may spend $50 a month on paid credits", "the growth team has $2,000", or "this agent may spend \$100 a day".

**`POST /v1/spend_limits`**

```json title="POST /v1/spend_limits"
{
  "key": "agent_daily",
  "applies_to": { "plan": "pro_monthly", "agent_id": "agent_billing_bot" },
  "period": { "duration": "P1D", "anchor": "calendar" },
  "amount": { "amount": 10000, "currency": "usd" },
  "action": "block"
}
```

Every group of limits that applies must have room, so a member can be inside their own cap and still be stopped by their team's. From the [customer view](/guides/customer-view) a customer sets one limit for themselves as a whole, which blocks, and can only tighten the one you set; limits on members and teams are yours to set.

## Allowances for each member

An allowance with `scope: per_member` counts for each `member_id` separately, and a refill grants `amount` for each member at the member's first `check()` or `track()` of a window, so a seat's first call of the week can draw on it. On a [seat-based plan](/guides/recipes#per-seat-plus-pooled-credits) that adds a week's credits for every active seat. The refills land in the allowance's pool, which every member draws on: a member's window shows what that member used against `amount`, and a member can use more while the pool has credits, drawing on other members' refills. To hold each member to `amount`, add a `per_member` cap on the same window. Without a `member_id` on the call, a `per_member` allowance doesn't apply. What the refills leave expires with their window.

## Read usage by member

`GET /v1/customers/{id}/usage_summary?member_id=user_2231` returns the windows kept for that member, and `GET /v1/ledger_entries` filters by `member_id` and `team_id`. [Runs and margin](/guides/cost-attribution-and-margin) group by `run_id` and by customer. `agent_id` is kept on events and costs, and a spend limit can name it, but no report groups by it yet.

## Not modeled

Runledger doesn't have team hierarchies or parent and child customers. A `team_id` is a flat label. To see the usage of several teams under one customer, send `team_id`.

## When it fails

`agent_id`, `member_id` and `team_id` are free labels, so Runledger never rejects an event for an unknown one. It rejects a value longer than 128 characters with `400` and `parameter_invalid`.

[Idempotency and errors](/reference/idempotency-and-errors) lists every code.

## Next steps

* [Spend limits](/guides/spend-limits) cap each member, team or agent.
* [Usage meters](/guides/usage-summary) read usage for one member.
* [Recipes](/guides/recipes#teams-with-budgets) shows a team budget in a complete plan.