Basalt docs
basaltapp.io

Instanzverwaltung

Das Backoffice des Betreibers: jeder Workspace dieser Instanz mit Metadaten und Tarif, die Tarifzuweisung, die fortschreibende Spur der Betreiberaktionen und der Posteingang der eingesendeten Meldungen (siehe Feedback). Bis auf diese eine Ausnahme ausschließlich Metadaten — der Betreiber einer gehosteten Instanz ist Auftragsverarbeiter, und diese Routen können weder Seitentitel noch Seiteninhalte noch Kommentare zurückgeben; eine Meldung ist hier nur deshalb lesbar, weil jemand sie geschrieben und an den Betreiber gesendet hat. Nur mit Sitzung, und beschränkt auf die in OPERATORS genannten Personen.

6 Operationen. Jeder Pfad ist relativ zum Ursprung der Instanz; jeder Antwortkörper ist JSON, sofern nicht anders vermerkt. Die Endpunktbeschreibungen unten stammen unverändert aus der Routentabelle des Servers und bleiben englisch. Authentifizierung, Fehler und seitenweise Abfrage stehen unter API.

GET /api/v1/admin/workspaces

Every workspace on this instance with its billing-relevant METADATA: name, slug, creation date, member count, live page count, stored bytes, plan and last activity. Newest first, keyset-paginated, optionally narrowed by name/slug or plan. Carries no page titles, no bodies and no comments — the operator is a processor, not a reader (GDPR Art. 28). Instance operator only (OPERATORS); everybody else gets 403, a workspace owner included. Session-only twice over: the route sits outside /workspaces/{workspaceId}, which tokens/scopes.ts classifies session-only, and the operator guard refuses a token-authenticated request outright.

listAdminWorkspaces · token scope: session only

Query parameters

  • cursor · string — length 1–∞
  • limit · integer — 1–100
  • q · string — length 1–200
  • plan · "free" | "pro" | "business" | "enterprise" | "self_hosted" | "team" Show only workspaces on this plan. Deprecated spellings are accepted for compatibility and resolved before anything is stored or answered: team means pro, and self_hosted means enterprise — the deployment mode that id named was withdrawn (ADR-0024) and the id retired (ADR-0029 D1). Responses only ever spell the four live ids.

Response 200 — application/json

  • items · object[] — required
    • id · string (uuid) — required
    • slug · string — required, length 1–100
    • name · string — required
    • createdAt · string (date-time) — required
    • memberCount · integer — required, 0–9007199254740991
    • pageCount · integer — required, 0–9007199254740991
    • storageBytes · integer — required, 0–9007199254740991
    • plan · "free" | "pro" | "business" | "enterprise" — required
    • planSince · string (date-time) | null — required
    • lastActivityAt · string (date-time) | null — required
  • nextCursor · string | null — required

Response default — application/json

  • error · object — required
    • code · "bad_request" | "validation_failed" | "unauthorized" | "forbidden" | "not_found" | "conflict" | "rate_limited" | "internal" — required
    • message · string — required
    • reason · string — length 1–64

GET /api/v1/admin/workspaces/{targetWorkspaceId}

One workspace in detail: the list row plus memberships per role, the owners (the billing counterparties — owners only, never the whole roster), the attachment count, and the plan limits with whichever of them it currently exceeds. Metadata only. Instance operator only (OPERATORS); everybody else gets 403, a workspace owner included. Session-only twice over: the route sits outside /workspaces/{workspaceId}, which tokens/scopes.ts classifies session-only, and the operator guard refuses a token-authenticated request outright.

getAdminWorkspace · token scope: session only

Path parameters

  • targetWorkspaceId · string (uuid) — required

Response 200 — application/json

  • id · string (uuid) — required
  • slug · string — required, length 1–100
  • name · string — required
  • createdAt · string (date-time) — required
  • memberCount · integer — required, 0–9007199254740991
  • pageCount · integer — required, 0–9007199254740991
  • storageBytes · integer — required, 0–9007199254740991
  • plan · "free" | "pro" | "business" | "enterprise" — required
  • planSince · string (date-time) | null — required
  • lastActivityAt · string (date-time) | null — required
  • membersByRole · object — required
    • owner · integer — required, 0–9007199254740991
    • admin · integer — required, 0–9007199254740991
    • member · integer — required, 0–9007199254740991
    • guest · integer — required, 0–9007199254740991
  • owners · object[] — required
    • userId · string (uuid) — required
    • name · string — required
    • email · string (email) — required
    • joinedAt · string (date-time) — required
  • attachmentCount · integer — required, 0–9007199254740991
  • limits · object — required
    • storageBytes · integer | null — required
    • fileSizeBytes · integer | null — required
    • members · integer | null — required
    • guests · integer | null — required
    • versionHistoryDays · integer | null — required
  • over · "storageBytes" | "fileSizeBytes" | "members" | "guests" | "versionHistoryDays"[] — required

Response default — application/json

  • error · object — required
    • code · "bad_request" | "validation_failed" | "unauthorized" | "forbidden" | "not_found" | "conflict" | "rate_limited" | "internal" — required
    • message · string — required
    • reason · string — length 1–64

PUT /api/v1/admin/workspaces/{targetWorkspaceId}/plan

Assign a workspace's plan — the write that makes the billing work usable before payments are wired. Idempotent: re-assigning the plan a workspace already has changes nothing and records nothing. Every real change writes an append-only workspace.plan.set entry to the operator audit trail IN THE SAME TRANSACTION, so a plan change with no record of who made it cannot exist. A downgrade never removes, hides or locks anything — it only narrows what the next write may add. Instance operator only (OPERATORS); everybody else gets 403, a workspace owner included. Session-only twice over: the route sits outside /workspaces/{workspaceId}, which tokens/scopes.ts classifies session-only, and the operator guard refuses a token-authenticated request outright.

setAdminWorkspacePlan · token scope: session only

Path parameters

  • targetWorkspaceId · string (uuid) — required

Request body — application/json, required

  • plan · "free" | "pro" | "business" | "enterprise" | "self_hosted" | "team" — required The plan to assign. Deprecated spellings are accepted for compatibility and resolved before anything is stored or answered: team means pro, and self_hosted means enterprise — the deployment mode that id named was withdrawn (ADR-0024) and the id retired (ADR-0029 D1). Responses only ever spell the four live ids.
  • note · string — length 0–500

Response 200 — application/json

  • id · string (uuid) — required
  • slug · string — required, length 1–100
  • name · string — required
  • createdAt · string (date-time) — required
  • memberCount · integer — required, 0–9007199254740991
  • pageCount · integer — required, 0–9007199254740991
  • storageBytes · integer — required, 0–9007199254740991
  • plan · "free" | "pro" | "business" | "enterprise" — required
  • planSince · string (date-time) | null — required
  • lastActivityAt · string (date-time) | null — required
  • membersByRole · object — required
    • owner · integer — required, 0–9007199254740991
    • admin · integer — required, 0–9007199254740991
    • member · integer — required, 0–9007199254740991
    • guest · integer — required, 0–9007199254740991
  • owners · object[] — required
    • userId · string (uuid) — required
    • name · string — required
    • email · string (email) — required
    • joinedAt · string (date-time) — required
  • attachmentCount · integer — required, 0–9007199254740991
  • limits · object — required
    • storageBytes · integer | null — required
    • fileSizeBytes · integer | null — required
    • members · integer | null — required
    • guests · integer | null — required
    • versionHistoryDays · integer | null — required
  • over · "storageBytes" | "fileSizeBytes" | "members" | "guests" | "versionHistoryDays"[] — required

Response default — application/json

  • error · object — required
    • code · "bad_request" | "validation_failed" | "unauthorized" | "forbidden" | "not_found" | "conflict" | "rate_limited" | "internal" — required
    • message · string — required
    • reason · string — length 1–64

GET /api/v1/admin/audit

The operator audit trail, newest first, optionally narrowed to one workspace. Append-only: a database trigger refuses UPDATE, DELETE and TRUNCATE, so an entry can be neither edited nor deleted by any code path, this one included. Instance operator only (OPERATORS); everybody else gets 403, a workspace owner included. Session-only twice over: the route sits outside /workspaces/{workspaceId}, which tokens/scopes.ts classifies session-only, and the operator guard refuses a token-authenticated request outright.

listAdminAudit · token scope: session only

Query parameters

  • cursor · string — length 1–∞
  • limit · integer — 1–100
  • workspaceId · string (uuid)

Response 200 — application/json

  • items · object[] — required
    • id · string (uuid) — required
    • at · string (date-time) — required
    • action · "workspace.plan.set" — required
    • operatorUserId · string (uuid) — required
    • operatorEmail · string (email) — required
    • workspaceId · string (uuid) | null — required
    • workspaceSlug · string | null — required
    • detail · object — required
  • nextCursor · string | null — required

Response default — application/json

  • error · object — required
    • code · "bad_request" | "validation_failed" | "unauthorized" | "forbidden" | "not_found" | "conflict" | "rate_limited" | "internal" — required
    • message · string — required
    • reason · string — length 1–64

GET /api/v1/admin/feedback

The feedback inbox, newest first, optionally narrowed by status, kind or product. The one operator surface that holds user-written text, and it is not an exception to the metadata-only rule: a report is a message somebody composed and sent to the operator, having seen everything attached to it. Joins no workspace content and links nowhere into one. Instance operator only (OPERATORS); everybody else gets 403, a workspace owner included. Session-only twice over: the route sits outside /workspaces/{workspaceId}, which tokens/scopes.ts classifies session-only, and the operator guard refuses a token-authenticated request outright.

listAdminFeedback · token scope: session only

Query parameters

  • cursor · string — length 1–∞
  • limit · integer — 1–100
  • status · "open" | "closed"
  • kind · "bug" | "idea"
  • product · "basalt" | "lithic" | "tecto"

Response 200 — application/json

  • items · object[] — required
    • id · string (uuid) — required
    • at · string (date-time) — required
    • kind · "bug" | "idea" — required
    • status · "open" | "closed" — required
    • message · string — required
    • product · "basalt" | "lithic" | "tecto" | null — required
    • reporter · object — required
      • userId · string (uuid) — required
      • name · string — required
      • email · string (email) — required
    • workspace · object | null — required
      • id · string (uuid) — required
      • name · string — required
    • context · object — required
      • route · string | null — required
      • appVersion · string | null — required
      • viewport · object | null — required
        • width · integer — required, 0–100000
        • height · integer — required, 0–100000
      • pointer · "coarse" | "fine" | null — required
      • trace · string | null — required
    • note · string | null — required
    • closedAt · string (date-time) | null — required
  • nextCursor · string | null — required

Response default — application/json

  • error · object — required
    • code · "bad_request" | "validation_failed" | "unauthorized" | "forbidden" | "not_found" | "conflict" | "rate_limited" | "internal" — required
    • message · string — required
    • reason · string — length 1–64

PATCH /api/v1/admin/feedback/{reportId}

Close or reopen a report, and/or set the operator's own note about it. The note is never shown to the sender. Instance operator only (OPERATORS); everybody else gets 403, a workspace owner included. Session-only twice over: the route sits outside /workspaces/{workspaceId}, which tokens/scopes.ts classifies session-only, and the operator guard refuses a token-authenticated request outright.

updateAdminFeedback · token scope: session only

Path parameters

  • reportId · string (uuid) — required

Request body — application/json, required

  • status · "open" | "closed"
  • note · string | null

Response 200 — application/json

  • id · string (uuid) — required
  • at · string (date-time) — required
  • kind · "bug" | "idea" — required
  • status · "open" | "closed" — required
  • message · string — required
  • product · "basalt" | "lithic" | "tecto" | null — required
  • reporter · object — required
    • userId · string (uuid) — required
    • name · string — required
    • email · string (email) — required
  • workspace · object | null — required
    • id · string (uuid) — required
    • name · string — required
  • context · object — required
    • route · string | null — required
    • appVersion · string | null — required
    • viewport · object | null — required
      • width · integer — required, 0–100000
      • height · integer — required, 0–100000
    • pointer · "coarse" | "fine" | null — required
    • trace · string | null — required
  • note · string | null — required
  • closedAt · string (date-time) | null — required

Response default — application/json

  • error · object — required
    • code · "bad_request" | "validation_failed" | "unauthorized" | "forbidden" | "not_found" | "conflict" | "rate_limited" | "internal" — required
    • message · string — required
    • reason · string — length 1–64