---
title: "Super-admin"
description: "The super-admin tier — raise a tenant's ceilings, and read the operational activity, metrics, and diagnostics behind the X-Admin-Key."
---

> Documentation Index
> Fetch the complete documentation index at: https://tee.hypetrade.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Super-admin

The super-admin tier sits above every tenant. It authenticates with a single
`X-Admin-Key` header and does two kinds of thing: raise a tenant's ceilings, and
expose read-only operational state — recent activity, a performance series, and
instantaneous gauges — so an incident can be diagnosed from an HTTP client
rather than a host sign-in. None of it appears on the public health probe.

Every route below shares the same auth. A missing or invalid key is `401`
`admin_denied`; the tier is rate limited as a whole (`429` `admin_rate_limited`).

## `POST /v1/admin/tenants/{id}/limits`

Lift a tenant's limits. **Auth: `X-Admin-Key`.** Returns `201`.

`{id}` is the tenant id.

### Request

```json
{
  "maxWorkspaces": 50,
  "maxWallets": 2000
}
```

| Field | Type | Required | Notes |
|---|---|---|---|
| `maxWorkspaces` | integer | no | New workspace ceiling. Non-negative |
| `maxWallets` | integer | no | New wallet ceiling. Non-negative |

At least one field is required; an empty body is `400`. Only these two ceilings
are liftable — `maxUnlockedWorkspaces` is deliberately out of reach. The raise is
**one-directional**: a value below the current ceiling is refused with `409`
`limit_not_raised`, never silently applied.

The change is persisted in `state.json`, so it survives a restart even though
`tenants.json` is mounted read-only.

### Response

```json
{
  "tenant": "acme",
  "limits": { "maxWorkspaces": 50, "maxWallets": 2000 },
  "changed": ["maxWorkspaces"]
}
```

`limits` is the effective ceiling after the call; `changed` lists only the
fields that actually moved, so a no-op raise returns an empty array.

### Errors

| Status | Code |
|---|---|
| 400 | `invalid_body`, `invalid_slug` |
| 401 | `admin_denied` — a missing or invalid `X-Admin-Key` |
| 404 | `tenant_not_found` |
| 409 | `limit_not_raised` — the value is below the current ceiling (a value equal to it is accepted, changing nothing) |
| 429 | `admin_rate_limited` |

## `GET /v1/admin/diagnostics`

An instantaneous operational snapshot. **Auth: `X-Admin-Key`.** Returns `200`.

Cheap in-process gauges — no locks, no tenant work. Uptime and core version;
process memory, open file descriptors, and cumulative event-loop lag; live
session and lease counts; and an `activity` block reporting the fill and drop
counters of the activity log below.

```json
{
  "uptimeSec": 37,
  "coreVersion": "<wative-core version>",
  "process": {
"rssBytes": 118321152,
"heapUsedBytes": 40286992,
"heapTotalBytes": 43204608,
"externalBytes": 3893242,
"openFds": 23,
"openFdLimit": 524288,
"eventLoopLagMeanMs": 20.3,
"eventLoopLagMaxMs": 196.35
  },
  "sessions": { "sessions": 0, "unlockedWorkspaces": 0, "unlockedWorkspacesCap": 32, "liveLeases": 0, "durableLeases": 0, "leasesPerWorkspaceCap": 64 },
  "activity": { "enabled": true, "eventsCaptured": 3, "eventsDropped": 0, "eventsHeld": 3, "eventCap": 2000, "perfSamplesHeld": 0, "perfCap": 900, "lastSeq": 3, "lastCrashHeld": 0 },
  "buffer": { "enabled": true, "batchSize": 50, "lowWatermark": 25 }
}
```

The event-loop figures here are cumulative over the process lifetime, so they
cannot place a stall in time. Use `GET /v1/admin/metrics` for a timestamped
series. The `buffer` block reports whether wallet buffer mode is on (`BUFFER_SIZE
> 0`) and its dials, so the mode is confirmable without host access.

### Errors

| Status | Code |
|---|---|
| 401 | `admin_denied` |
| 429 | `admin_rate_limited` |

## `GET /v1/admin/activity`

The recent-activity ring — a bounded, in-memory log of what the service has been
doing. **Auth: `X-Admin-Key`.** Returns `200`, `cache-control: no-store`.

One entry per HTTP request (method, route template, status, latency, request id,
tenant, and any account or wallet binding), session open/close/evict events, and
— for every error — the internal `reason` the response body and the warning log
deliberately omit. That last field is what lets a failure be diagnosed by its
request id alone.

### Query

| Field | Type | Notes |
|---|---|---|
| `limit` | integer | Max events returned, newest kept. Optional |
| `kind` | string | Filter by kind — one of `request`, `error`, `session`, `mint`, `lease`, `ratelimit`, `provision`, `lifecycle`, `fatal`; any other value is `400 invalid_body`. Optional |
| `sinceSeq` | integer | Only events with a higher `seq` — feed the previous response's `lastSeq` back for a gap-free incremental tail. Optional |
| `scope` | string | `current` (default) reads the live ring; `lastcrash` reads the previous run's reloaded dump |

### Response

```json
{
  "events": [
{
  "seq": 42,
  "ts": 1789715615345,
  "kind": "request",
  "method": "POST",
  "route": "/v1/auth/token",
  "status": 401,
  "latencyMs": 6,
  "requestId": "53e33bc8-c052-4760-a617-47926dcca0db",
  "tenant": "acme"
},
{
  "seq": 43,
  "ts": 1789715615346,
  "kind": "error",
  "code": "session_expired",
  "status": 401,
  "reason": "no token lifetime remains",
  "requestId": "53e33bc8-c052-4760-a617-47926dcca0db"
}
  ],
  "lastSeq": 43
}
```

Fields are redacted as they enter the ring: bearer tokens, JWTs, API keys, and
32-byte hex secrets never reach it, and overlong values are capped. Wallet addresses and workspace/account slugs **are** recorded
— they are admin-tier diagnostic aids, not secrets. Passwords and key material
are never captured.

The ring is in memory and clears on restart, except that its tail is written to
`state/activity-crash.json` on shutdown and from the fatal handler, then reloaded
at boot and served under `scope=lastcrash` — so the events leading to a crash
survive the restart.

### Errors

| Status | Code |
|---|---|
| 400 | `invalid_body` — an unknown or malformed query parameter |
| 401 | `admin_denied` |
| 429 | `admin_rate_limited` |

## `GET /v1/admin/metrics`

The performance series. **Auth: `X-Admin-Key`.** Returns `200`, `cache-control: no-store`.

A short, bounded time-series sampled on an interval: event-loop lag (mean and max
**per interval**, so a stall lands on a timestamp), process memory, and file
descriptor count.

### Query

| Field | Type | Notes |
|---|---|---|
| `limit` | integer | Max samples returned, newest kept. Optional |

### Response

```json
{
  "samples": [
{
  "ts": 1789715630419,
  "loopLagMeanMs": 20.16,
  "loopLagMaxMs": 21.2,
  "rssBytes": 118321152,
  "heapUsedBytes": 40410712,
  "externalBytes": 3893242,
  "openFds": 22
}
  ]
}
```

### Errors

| Status | Code |
|---|---|
| 400 | `invalid_body` |
| 401 | `admin_denied` |
| 429 | `admin_rate_limited` |

## Related

- [Workspaces](/api/workspaces/) — where those ceilings are spent
- [Quota](/api/workspaces/#get-v1quota) — a tenant reading its own usage against these limits

Source: https://tee.hypetrade.xyz/api/admin/index.mdx
