Org

Org-wide visibility: a single usage rollup and the tamper-evident audit trail. Both routes are admin-gated. See Usage and audit for the CLI-rendered table views of these same responses.

GET /v1/org/usage — usage rollup

Auth: admin.

$ curl -s https://api.stagdb.com/v1/org/usage -H "Authorization: Bearer $TOKEN"

Response 200 OK

{
  "quota": {"max_per_user": 3, "max_per_org": 30, "active_in_org": 14},
  "users": [
    {"email": "[email protected]", "display_name": "Alex Park", "role": "admin", "status": "active", "active": 1, "total": 4},
    {"email": "[email protected]", "display_name": "Dana Lin", "role": "user", "status": "active", "active": 2, "total": 9}
  ],
  "goldens": [
    {"name": "prod-pg16", "latest_version": 3, "shared": true, "active": 11, "total": 40}
  ],
  "clusters": [
    {"name": "prod", "health": "connected", "last_seen": "2026-07-19T08:12:41Z", "active_instances": 14}
  ],
  "pools": [
    {"golden": "prod-pg16", "warm": 5, "target": 5}
  ],
  "imports": {
    "total": 3,
    "succeeded": 3,
    "failed": 0,
    "last_finished_at": "2026-07-18T22:10:04Z"
  }
}

One call, six sections — quota, users, goldens, clusters, pools, imports. This is the same data available piecemeal from GET /v1/org/quota, GET /v1/users, GET /v1/snapshots, GET /v1/clusters, GET /v1/pools, and GET /v1/imports, joined into one document — useful for a dashboard or a single scripted health check instead of five separate calls. pools is [] (empty array) if the org has none.

Status When
403 Caller is not an admin.

GET /v1/org/audit — audit trail

Auth: admin.

Query parameters

Param Type Notes
limit integer Page size. Clamped server-side to (0, 500]; an out-of-range or omitted value falls back to 100. Must parse as an integer if present (?limit=abc is a 400, not a silent fallback).
before RFC3339 timestamp Pagination cursor — restricts the page to events strictly older than this timestamp. Compares at full precision, so pass back the exact ts of the last event on a page (RFC3339Nano) to page further without skipping same-second events.
verify 1 When set to exactly "1", adds a chain-verification pass to the response (see below). Any other value is ignored (verification is skipped, not errored).
$ curl -s "https://api.stagdb.com/v1/org/audit?limit=3" -H "Authorization: Bearer $TOKEN"

Response 200 OK

{
  "events": [
    {
      "seq": 102,
      "actor": "[email protected]",
      "action": "import.start",
      "resource": "5b9d7c31-2e4f-4a6b-8c0d-1e2f3a4b5c6d",
      "ts": "2026-07-18T22:10:04.812345Z",
      "payload": {}
    },
    {
      "seq": 101,
      "actor": "[email protected]",
      "action": "instance.launch",
      "resource": "7a1e9c3d-5b2f-4c8a-9d0e-2f3a4b5c6d7e",
      "ts": "2026-07-18T21:02:11.204819Z",
      "payload": {}
    },
    {
      "seq": 100,
      "actor": "[email protected]",
      "action": "invite.create",
      "resource": "1f2e3d4c-5b6a-4978-8c9d-0e1f2a3b4c5d",
      "ts": "2026-07-18T20:58:40.573062Z",
      "payload": {}
    }
  ]
}

Every state-changing action in the org is recorded: logins, invites, instance launches/destroys, snapshot registration/share/delete, quota changes, cluster registration, and more — as a sequenced (seq, strictly increasing), hash-chained event. action is a dotted verb (instance.launch, snapshot.share, invite.create, cluster.register, …); resource is the affected object's UUID as a string. ts is RFC3339Nano, not plain RFC3339 like every other timestamp in this API — full sub-second precision is load-bearing for the before cursor (see above). payload is {} when the event carries no extra structured detail.

With ?verify=1 — tamper-evident chain check

$ curl -s "https://api.stagdb.com/v1/org/audit?verify=1" -H "Authorization: Bearer $TOKEN"
{
  "events": [ /* ... */ ],
  "chain_ok": true,
  "events_checked": 102
}

Each event is hash-chained to the one before it. verify=1 re-derives the chain from the stored events and reports whether it's intact — chain_ok: true/false plus events_checked. If verification fails, a verify_error field is added with the specific reason:

{"events": [ /* ... */ ], "chain_ok": false, "events_checked": 102, "verify_error": "hash mismatch at seq 57"}

Note that chain_ok: false does not change the HTTP status — this response is still 200 OK even when the chain is broken, since the read succeeded; the caller (the CLI) is what turns chain_ok: false into a non-zero exit.

Exporting

There's no separate export endpoint — page through with limit/before and concatenate. This is exactly what adj org audit --limit 500 -o json > audit-export.json does under the hood.

Status When
400 limit present but not a valid integer ("limit must be an integer"); or before present but not a valid RFC3339 timestamp ("before must be an RFC3339 timestamp").
403 Caller is not an admin.

Next