Documentation

HTTP API

Generated from internal/api/router.go. Every authenticated mutation requires both a session cookie and a X-CSRF-Token header that matches the stowage_csrf cookie.

Errors are JSON-shaped:

{ "error": { "code": "rate_limited", "message": "...", "detail": "" } }

For the full code list, see Error codes.

#Public endpoints

MethodPathPurpose
GET/healthzLiveness probe.
GET/readyzReadiness probe.
GET/metricsPrometheus scrape (no auth — gate at the proxy).

#Auth

MethodPathPurpose
POST/auth/login/localLocal username + password. Per-IP rate-limited.
GET/auth/login/oidcBegin the OIDC redirect dance.
GET/auth/callbackOIDC callback.
POST/auth/logoutClear the session.

#/api root

MethodPathAuthPurpose
GET/api/auth/confignoneLists enabled auth modes and OIDC start URL.
GET/api/mesessionCurrent user.
POST/api/me/passwordsession + CSRFChange own password.
GET/api/searchsessionCross-backend bucket+prefix search.

#Pinned buckets

MethodPathRolePurpose
GET/api/me/pinsanyList your pinned buckets.
POST/api/me/pinsuser/adminPin a (backend, bucket).
DELETE/api/me/pins/{bid}/{bucket}user/adminUnpin.

#Self-service S3 virtual credentials

Available when s3_proxy.enabled: true.

MethodPathRolePurpose
GET/api/me/s3-credentialsanyList your own virtual credentials.
POST/api/me/s3-credentialsuser/adminMint one.
PATCH/api/me/s3-credentials/{akid}user/adminUpdate description / scope / disable.
DELETE/api/me/s3-credentials/{akid}user/adminRevoke.

#Backends and bucket data

MethodPathRolePurpose
GET/api/backendsanyList configured backends + status.
GET/api/backends/{bid}anyOne backend's status.
GET/api/backends/{bid}/healthanyForce a probe and return the result.
GET/api/backends/{bid}/bucketsanyList buckets on a backend.
POST/api/backends/{bid}/bucketsadminCreate a bucket.
DELETE/api/backends/{bid}/buckets/{bucket}adminDelete a bucket.

#Bucket settings (admin-only)

MethodPathPurpose
GET / PUT/api/backends/{bid}/buckets/{bucket}/versioningGet / set versioning.
GET / PUT/api/backends/{bid}/buckets/{bucket}/corsGet / set CORS.
GET / PUT / DELETE/api/backends/{bid}/buckets/{bucket}/policyBucket policy.
GET / PUT/api/backends/{bid}/buckets/{bucket}/lifecycleLifecycle rules.
GET / PUT / DELETE/api/backends/{bid}/buckets/{bucket}/quotaQuota.
POST/api/backends/{bid}/buckets/{bucket}/quota/recomputeForce a quota scan.
PUT/api/backends/{bid}/buckets/{bucket}/size-trackingPer-bucket size-tracking toggle.

#Bucket size endpoints

MethodPathRolePurpose
GET/api/backends/{bid}/buckets/{bucket}/size-trackinganyRead current size-tracking state.
GET/api/backends/{bid}/buckets/{bucket}/prefix-sizeanySum bytes under a prefix.

#Object operations

All paths under /api/backends/{bid}/buckets/{bucket}/.

MethodPathRolePurpose
GET/objectsanyList objects.
POST/objects/deleteuser/adminBulk delete.
POST/objects/delete-prefixuser/adminRecursive delete.
POST/objects/folderuser/adminCreate a "folder" (zero-byte placeholder).
POST/objects/copy-prefixuser/adminRecursive copy (intra- or cross-backend).
GET/objects/zipanyStream a zip of selected keys.
GET / HEAD/objectanyGet / head one object.
GET/object/infoanyEquivalent to HEAD.
POST/objectuser/adminUpload (small file).
DELETE/objectuser/adminDelete.
POST/object/copyuser/adminSingle-object copy (intra- or cross-backend).
GET / PUT/object/tagsvariesGet / set tags.
PUT/object/metadatauser/adminUpdate user metadata in place.
GET/object/versionsanyList versions.

#Multipart

All under /api/backends/{bid}/buckets/{bucket}/multipart/.

MethodPathRolePurpose
GET/anyList in-progress uploads.
POST/user/adminInitiate.
DELETE/user/adminAbort.
POST/completeuser/adminComplete.
PUT/parts/{part}user/adminUpload one part.

#Shares

MethodPathRolePurpose
GET/api/sharesanyList shares (your own; admins can switch to "all").
POST/api/sharesuser/adminCreate.
DELETE/api/shares/{id}user/adminRevoke.

#Public share endpoints

Per-IP rate-limited (default 10 req/min).

MethodPathPurpose
GET/s/{code}/infoShare metadata.
POST/s/{code}/unlockSubmit password.
GET/s/{code}/rawStream the file.

The bare /s/{code} falls through to the SvelteKit SPA, which renders the recipient page.

#Admin: dashboard / backends / users

All under /api/admin/. Admin role required.

MethodPathPurpose
GET/dashboardThe admin dashboard data.
GET/backends/healthAll backends with probe history.
GET/auditAudit log query.
GET/audit.csvAudit log CSV export.
GET/usersList users.
POST/usersCreate user.
GET/users/{id}One user.
PATCH/users/{id}Update.
POST/users/{id}/reset-passwordAdmin password reset.
POST/users/{id}/unlockUnlock a locked-out account.
DELETE/users/{id}Delete.
GET/backendsList UI-managed endpoints.
POST/backendsCreate one.
POST/backends/testTest new credentials.
GET/backends/{bid}Detail.
PATCH/backends/{bid}Update.
DELETE/backends/{bid}Delete.

#Admin: S3 proxy management

Available when s3_proxy.enabled: true. All admin role.

MethodPathPurpose
GET/api/admin/s3-credentialsList virtual credentials.
POST/api/admin/s3-credentialsMint.
PATCH/api/admin/s3-credentials/{akid}Update.
DELETE/api/admin/s3-credentials/{akid}Revoke.
GET/api/admin/s3-anonymousList anonymous bindings.
POST/api/admin/s3-anonymousAdd or update.
DELETE/api/admin/s3-anonymous/{bid}/{bucket}Remove.
GET/api/admin/s3-proxy/credentialsRead-only merged view (SQLite + Kubernetes).
GET/api/admin/s3-proxy/anonymousRead-only merged anonymous view.

#CSRF & session details

See Self-host → Sessions.

#Status codes summary

CodeMeaning
200OK
204No content
400Validation failure (bad_request, invalid_*)
401No / invalid session (unauthorized)
403RBAC / CSRF / scope (forbidden, csrf_invalid, self_role_change)
404Object / bucket / user / backend not found
409Conflict (username_taken, id_taken, last_admin, yaml_managed)
410Share expired or revoked
429Rate-limited
500Internal error
503secret_key_unset or store_unavailable
507Bucket quota exceeded (quota_exceeded)