Skip to content

Admin API

The JSON Admin API lives at /admin/api/v1/ on the admin listener (never the public S3 port). It is the control plane: tenants, service accounts, scoped access keys, quotas, usage, and audit.

It reuses the exact in-process domain services the HTML admin UI uses (tenant lifecycle, the metadata repo, the SigV4 secret cipher, the auditor), so it cannot bypass any authorization, audit, retention, or quota gate.

For most apps, reach this API through a first-party SDK rather than calling it directly: Go, Node, or Java. This page is the wire-level reference.

Authentication

Authentication is by an admin API bearer token: a high-entropy secret minted offline with lockwell admin-token create, stored only hashed (SHA-256), and distinct from S3 access keys. The wire form is prefixed lwadm_…. Send it as:

text
Authorization: Bearer lwadm_…
  • Token bootstrap is offline-only (lockwell admin-token create needs filesystem access, the same trust model as lockwell admin-create). There is no JSON route to mint the first token.
  • Bearer tokens are not sent automatically by browsers, so the API is for server-to-server use and carries no CSRF flow.
  • Anonymous, unauthenticated, revoked, and expired tokens are denied with 401.
  • Every request, success and denial, writes an audit row through the existing auditor. Tokens are rate-limited per token.

RBAC roles

Authorization composes the token's RBAC role with an optional single-tenant scope. A tenant-scoped token cannot cross to another tenant: a cross-tenant target is a 403, never a 404 existence leak.

RoleCan do
viewerread-only: list/get tenants, accounts, keys, quota, usage, audit
operatorthe above plus create tenants/accounts/keys, set/clear quota, rotate/revoke keys
ownerthe above plus the destructive tenant lifecycle: disable and delete

Routes

The server base is /admin/api/v1. GET /healthz and GET /openapi.json are unauthenticated; everything else requires a valid admin token.

Tenants

Method + pathRolePurpose
GET /tenantsviewerlist tenants (global token = all; scoped = its tenant)
POST /tenantsoperatorcreate a tenant
GET /tenants/{id}viewerget one tenant
POST /tenants/{id}/disableownerdisable a tenant; reason required
POST /tenants/{id}/deleteownerdelete a disabled tenant; reason + confirm required

disable revokes the tenant's active access keys. delete requires the tenant to be disabled first, requires confirm to equal the tenant id, and fails closed with a 412 when a retention window or legal hold gates the delete.

Accounts, keys, quota, usage

Method + pathRolePurpose
GET /tenants/{id}/accountsviewerlist service accounts
POST /tenants/{id}/accountsoperatorcreate a service account
GET /tenants/{id}/keysviewerlist access keys (secrets never returned)
POST /tenants/{id}/keysoperatorcreate an access key (secret returned once)
POST /tenants/{id}/keys/{keyId}/rotateoperatorrotate a key (new secret returned once)
POST /tenants/{id}/keys/{keyId}/revokeoperatorrevoke a key; reason required
GET|PUT|DELETE /tenants/{id}/quotaviewer / operatorget / set / clear the tenant quota
GET /tenants/{id}/usageviewerstorage usage report

The secret on a created or rotated key is shown exactly once and is never recoverable afterward; persist it immediately. listKeys returns only metadata.

The key request body accepts a scopes string (verb list read,write,delete,admin, or the resource form op=read,write,delete:bucket=reports:prefix=in/) and an optional expiresAt (RFC3339 or YYYY-MM-DD).

A created or rotated key returns its secret exactly once. Capture it from the response immediately; there is

no endpoint that reads it back. :::

Audit

Method + pathRolePurpose
GET /audit?tenant=&since=&limit=viewerquery the audit log

since is a Go duration string (e.g. 24h); limit is clamped to [1, 1000] (default 100). A tenant-scoped token is forced to its own tenant regardless of the tenant parameter; an explicit cross-tenant tenant from a scoped token is a 403.

reason / confirm and dry runs

Destructive operations are gated on the wire:

  • reason is required on disable, delete, and revoke (a 400 otherwise).
  • confirm must equal the tenant id on delete (a 400 otherwise).
  • ?dryRun=true on any mutation returns the plan the call would execute and applies nothing. For tenant disable/delete the plan enumerates the buckets, objects, versions, delete markers, legal-held and retained versions, access keys, and physical bytes that would be affected, so you can preview an offboarding before committing it.
text
POST /admin/api/v1/tenants/acme/delete?dryRun=true
Authorization: Bearer lwadm_…
Content-Type: application/json

{ "reason": "offboarding", "confirm": "acme" }

The SDKs surface this directly: every mutation takes a dryRun option (Go/Node) or has a …DryRun twin (Java). See tenancy and auth.

Error shape

Failures return an RFC-7807-style JSON problem with a stable code, message, status, and requestId (also echoed in X-Request-Id), so an operator can correlate a failure with its audit row:

json
{
  "code": "precondition_failed",
  "message": "tenant has legal-held object versions",
  "status": 412,
  "requestId": "req_01HXY…"
}

Status mapping:

StatusMeaning
400validation (missing reason, bad confirm, malformed body)
401missing/invalid/revoked/expired admin token
403RBAC role or cross-tenant scope denial
404target not found
412retention / legal-hold gated tenant delete (fail-closed)
429per-token rate limit exceeded

OpenAPI

The full machine-readable contract is an OpenAPI 3 document, available two ways:

  • Served live at GET /admin/api/v1/openapi.json (unauthenticated, since an operator needs the contract before holding a token; it leaks no tenant data).
  • Committed at internal/adminapi/openapi.json (the canonical source; a human-readable YAML twin lives alongside at internal/adminapi/openapi.yaml).

Each operation carries a unique operationId (listTenants, createTenantKey, queryAuditLog, …), so you can generate a client in any language with openapi-generator. Prefer the first-party Go/Node/Java admin clients; codegen is the path for every other language.

Not exposed here

This JSON API mirrors the tenant / account / key / quota / audit subset of the admin surface. Operational controls that live on the HTML admin UI (encryption-key rotation and rewrap, lifecycle, repair/scrub, placement, backup/restore) are not part of the JSON Admin API.

There is also no public-access, bucket-policy, or notification configuration surface here. Notifications are configured on the native data plane.

Interactive reference

Every admin operation below is generated from the OpenAPI document, so it always matches the shipped server. Expand an operation for its parameters, request and response schemas, and copy-paste samples. Send the admin token as Authorization: Bearer <token>. The example host is a placeholder; swap in your own admin endpoint.

Versioned, authenticated, RBAC'd, audited JSON Admin API for Lockwell. Mounted under /admin/api/v1/ on the admin/web listener only (never the public S3 data-plane port). Authentication is by admin API bearer token; tokens are minted offline with lockwell admin-token create, stored only hashed, scoped by RBAC role (owner/operator/viewer) and optional single-tenant scope. Every request, success and denial, writes an audit row. Server-to-server use only; bearer tokens are not sent automatically by browsers, so there is no CSRF flow.

Servers

https://admin.your-lockwell-host.com/admin/api/v1Your Lockwell deployment (replace with your own host)

system

Liveness and contract endpoints.


Liveness probe for the API (unauthenticated).

GET
/healthz

Responses

API process is up.

Playground

Samples


This OpenAPI document (unauthenticated).

GET
/openapi.json

Responses

OpenAPI 3 document.

Playground

Samples


List tenants (global token = all; tenant-scoped = its tenant).

GET
/tenants

Authorizations

adminToken

Admin API bearer token minted by lockwell admin-token create.

Type
HTTP (bearer)

Responses

Tenant list.

Playground

Authorization

Samples


Create a tenant (owner/operator).

POST
/tenants

Authorizations

adminToken

Admin API bearer token minted by lockwell admin-token create.

Type
HTTP (bearer)

Responses

Created tenant.

Playground

Authorization

Samples


Get one tenant.

GET
/tenants/{id}

Authorizations

adminToken

Admin API bearer token minted by lockwell admin-token create.

Type
HTTP (bearer)

Parameters

Path Parameters

id*
Type
string
Required

Responses

Tenant.

Playground

Authorization
Variables
Key
Value

Samples


Get a tenant's quota and usage.

GET
/tenants/{id}/quota

Authorizations

adminToken

Admin API bearer token minted by lockwell admin-token create.

Type
HTTP (bearer)

Parameters

Path Parameters

id*
Type
string
Required

Responses

Quota.

Playground

Authorization
Variables
Key
Value

Samples


Set a tenant's quota (owner/operator).

PUT
/tenants/{id}/quota

Authorizations

adminToken

Admin API bearer token minted by lockwell admin-token create.

Type
HTTP (bearer)

Parameters

Path Parameters

id*
Type
string
Required

Responses

Updated quota.

Playground

Authorization
Variables
Key
Value

Samples


Clear a tenant's quota (owner/operator).

DELETE
/tenants/{id}/quota

Authorizations

adminToken

Admin API bearer token minted by lockwell admin-token create.

Type
HTTP (bearer)

Parameters

Path Parameters

id*
Type
string
Required

Responses

Cleared quota.

Playground

Authorization
Variables
Key
Value

Samples


List service accounts in a tenant.

GET
/tenants/{id}/accounts

Authorizations

adminToken

Admin API bearer token minted by lockwell admin-token create.

Type
HTTP (bearer)

Parameters

Path Parameters

id*
Type
string
Required

Responses

Account list.

Playground

Authorization
Variables
Key
Value

Samples


Create a service account (owner/operator).

POST
/tenants/{id}/accounts

Authorizations

adminToken

Admin API bearer token minted by lockwell admin-token create.

Type
HTTP (bearer)

Parameters

Path Parameters

id*
Type
string
Required

Responses

Created account.

Playground

Authorization
Variables
Key
Value

Samples


List access keys in a tenant (secrets never returned).

GET
/tenants/{id}/keys

Authorizations

adminToken

Admin API bearer token minted by lockwell admin-token create.

Type
HTTP (bearer)

Parameters

Path Parameters

id*
Type
string
Required

Responses

Key list.

Playground

Authorization
Variables
Key
Value

Samples


Create an access key (owner/operator); secret returned once.

POST
/tenants/{id}/keys

Authorizations

adminToken

Admin API bearer token minted by lockwell admin-token create.

Type
HTTP (bearer)

Parameters

Path Parameters

id*
Type
string
Required

Responses

Created key with one-time secret.

Playground

Authorization
Variables
Key
Value

Samples


Rotate an access key (owner/operator); new secret returned once.

POST
/tenants/{id}/keys/{keyId}/rotate

Authorizations

adminToken

Admin API bearer token minted by lockwell admin-token create.

Type
HTTP (bearer)

Parameters

Path Parameters

id*
Type
string
Required
keyId*
Type
string
Required

Responses

Rotated key with one-time secret.

Playground

Authorization
Variables
Key
Value

Samples


Revoke an access key (owner/operator); reason required.

POST
/tenants/{id}/keys/{keyId}/revoke

Authorizations

adminToken

Admin API bearer token minted by lockwell admin-token create.

Type
HTTP (bearer)

Parameters

Path Parameters

id*
Type
string
Required
keyId*
Type
string
Required

Responses

Revoked key.

Playground

Authorization
Variables
Key
Value

Samples


Tenant storage usage report.

GET
/tenants/{id}/usage

Authorizations

adminToken

Admin API bearer token minted by lockwell admin-token create.

Type
HTTP (bearer)

Parameters

Path Parameters

id*
Type
string
Required

Responses

Usage report.

Playground

Authorization
Variables
Key
Value

Samples


Disable a tenant (owner only); reason required.

POST
/tenants/{id}/disable

Authorizations

adminToken

Admin API bearer token minted by lockwell admin-token create.

Type
HTTP (bearer)

Parameters

Path Parameters

id*
Type
string
Required

Responses

Disable plan applied.

Playground

Authorization
Variables
Key
Value

Samples


Delete a disabled tenant (owner only); reason + confirm required; retention/legal-hold gated.

POST
/tenants/{id}/delete

Authorizations

adminToken

Admin API bearer token minted by lockwell admin-token create.

Type
HTTP (bearer)

Parameters

Path Parameters

id*
Type
string
Required

Responses

Delete plan applied.

Playground

Authorization
Variables
Key
Value

Samples


audit

Audit log queries.

Operations


Query the audit log (tenant-scoped token forced to its tenant).

GET
/audit

Authorizations

adminToken

Admin API bearer token minted by lockwell admin-token create.

Type
HTTP (bearer)

Parameters

Query Parameters

tenant
Type
string
since

Go duration, e.g. 24h

Type
string
limit
Type
integer

Responses

Audit events.

Playground

Authorization
Variables
Key
Value

Samples


Powered by VitePress OpenAPI

Released under the Apache-2.0 License. License