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

# Members & usage

> Who is in the organization, and how much of the plan is left before you spend it.

## Usage and limits

```
GET https://app.ruber.me/api/v1/usage
```

**Required permission:** Usage → Read.

```json theme={null}
{
  "plan": "personal",
  "mailboxes": { "used": 5, "limit": 5, "remaining": 0 },
  "domains":   { "used": 1, "limit": 1, "remaining": 0 },
  "storage":   { "used_bytes": 2147483648, "limit_bytes": 10737418240, "remaining_bytes": 8589934592 },
  "sending":   { "sent_today": 12, "limit_per_day": 100, "remaining_today": 88 }
}
```

This is the call to make **before** acting, not after being refused.

Sending is capped per day, and without this the only way to learn the cap is to
hit it — which for a batch means finding out halfway through that half the mail
went. `remaining` is reported next to every pair so the decision ("can I send
these 40?") is a comparison rather than a subtraction you have to get right.

<Note>
  **Advisory, not a reservation.**

  The limits are enforced by the database, not by this endpoint. Two callers
  asking at once both see the same room and only one gets it. Treat a `402
    quota_exceeded` as the authority and this as the thing that stops you provoking
  one.

  `remaining` never goes below zero, so an organization over its limit — which
  happens after a downgrade — reads `0` rather than a negative number.
</Note>

`sent_today` counts the **UTC** day, because that is the day the send path
counts. A local day would disagree with the number you are actually measured
against for several hours, every day.

## Members

```
GET https://app.ruber.me/api/v1/members
```

**Required permission:** Members → Read.

```json theme={null}
{
  "data": [
    {
      "id": "60dd5af3-f367-4bc9-bd2b-052ee3123c48",
      "email": "alice@yourdomain.com",
      "name": "Alice Chen",
      "role": "owner",
      "joined_at": "2026-08-01T09:12:44.008Z"
    }
  ]
}
```

Both `id` and `email` come back because a task's
[`assignee`](/api/tasks#assigning) accepts either, and you should not have to
know which one works.

<Note>
  **Read only, deliberately.**

  There is no invite, no remove and no role change. Adding somebody to an
  organization gives them a real person's access to real mail, and removing
  somebody takes it away — those belong behind a signed-in human who can be held
  to them, not behind a key that may be sitting in a repository. The dashboard
  does it.
</Note>

## Errors

| Code           | HTTP  | Cause                                         |
| -------------- | ----- | --------------------------------------------- |
| `unauthorized` | `401` | Missing, malformed, unknown or revoked key.   |
| `forbidden`    | `403` | The key lacks `usage:read` or `members:read`. |
| `rate_limited` | `429` | Over 600 requests in a minute.                |

See [Errors](/api/introduction#errors) for the full response shape.
