Storage API
25 endpoints. Request and response schemas are described on the schemas page; the other tags are listed in the API index.
Endpoints
GET /api/v1/admin/recovery/status
Disaster-recovery journal status
State of the row journal behind openartifact rebuild: how many changed package rows still wait for their sidecar blob, how old the oldest is, the last failure and the progress of the backfill reconcile (admin only)
Responses
| Status | Description | Body |
|---|---|---|
200 | Journal status | application/json: RecoveryStatus |
403 | Admin access required | - |
GET /api/v1/admin/storage
List storage backends
List the storage backends stored in the database (items) and the primary store the server is configured with (primary, read-only; absent when none is wired). The primary store is not part of items or total. Its status comes from a health check cached for 10 seconds.
Responses
| Status | Description | Body |
|---|---|---|
200 | List of storage backends | application/json: object |
403 | Admin access required | - |
Fields of the 200 response (application/json):
| Field | Type | Required | Description |
|---|---|---|---|
items | array of StorageBackend | no | - |
primary | StoragePrimary | no | - |
total | integer | no | - |
POST /api/v1/admin/storage
Create storage backend
Create a new storage backend (admin only). The names "primary" and "replication" are reserved (they are static paths under /admin/storage): creating one answers 400
Request body (required)
application/json: object
| Field | Type | Required | Description |
|---|---|---|---|
config | object | no | - |
kind | string | yes | One of: filesystem, s3, gcs, azure. |
name | string | yes | - |
Responses
| Status | Description | Body |
|---|---|---|
201 | Storage backend created | application/json: StorageBackend |
400 | Invalid request | application/json: Error |
403 | Admin access required | - |
GET /api/v1/admin/storage/primary
Get the primary storage
The primary blob store the server is configured with (storage.* settings), with its non-secret location, live status and usage (admin only). The name "primary" is reserved: this static path takes precedence over /admin/storage/{name}.
Responses
| Status | Description | Body |
|---|---|---|
200 | The primary storage | application/json: StoragePrimary |
403 | Admin access required | - |
404 | No primary storage is wired | - |
PATCH /api/v1/admin/storage/primary
Update the primary storage (not allowed)
Always answers 405 read_only: the primary storage is set by the server configuration.
Responses
| Status | Description | Body |
|---|---|---|
403 | Admin access required | - |
405 | read_only | application/json: Error |
DELETE /api/v1/admin/storage/primary
Delete the primary storage (not allowed)
Always answers 405 read_only: the primary storage is set by the server configuration.
Responses
| Status | Description | Body |
|---|---|---|
403 | Admin access required | - |
405 | read_only | application/json: Error |
POST /api/v1/admin/storage/primary/test
Test the primary storage
Runs a live health check through the store that serves every request and refreshes the cached status (admin only).
Responses
| Status | Description | Body |
|---|---|---|
200 | Test result | application/json: object |
403 | Admin access required | - |
404 | No primary storage is wired | - |
Fields of the 200 response (application/json):
| Field | Type | Required | Description |
|---|---|---|---|
error | string | no | - |
message | string | no | - |
ok | boolean | no | - |
GET /api/v1/admin/storage/replication
Blob replication status
Backlog, lag, totals and the last verify pass of the replication to storage.replica (admin only). Reports enabled=false when no replica is configured. This static path takes precedence over /admin/storage/{name}.
Responses
| Status | Description | Body |
|---|---|---|
200 | Replication status | application/json: ReplicationStatus |
403 | Admin access required | - |
POST /api/v1/admin/storage/replication/verify
Verify the replica now
Requests a verify pass that compares the primary store with the replica and repairs differences in either direction; it runs in the background on the replica holding the verify lock (admin only)
Responses
| Status | Description | Body |
|---|---|---|
202 | Pass requested | application/json: object |
403 | Admin access required | - |
404 | Blob replication is not configured | - |
409 | A verify pass is already running or requested | - |
Fields of the 202 response (application/json):
| Field | Type | Required | Description |
|---|---|---|---|
requested | boolean | no | - |
GET /api/v1/admin/storage/{name}
Get storage backend
Get details of a specific storage backend (admin only)
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | yes | - |
Responses
| Status | Description | Body |
|---|---|---|
200 | Storage backend details | application/json: StorageBackend |
400 | Invalid request, including a NUL byte in the URL or the body | application/json: Error |
403 | Forbidden | application/json: Error |
404 | Storage backend not found | - |
PATCH /api/v1/admin/storage/{name}
Update storage backend
Update a storage backend (admin only). Renaming it to "primary" or "replication" answers 400. The name "primary" answers 405 read_only unless a record of that name still exists from before it was reserved, which this then renames. Changing kind or config is refused with 409 while the backend holds blobs, serves a tier or is named by a tier move
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | yes | - |
Request body (required)
application/json: object
| Field | Type | Required | Description |
|---|---|---|---|
config | object | no | - |
Responses
| Status | Description | Body |
|---|---|---|
200 | Storage backend updated | application/json: StorageBackend |
400 | Invalid request | application/json: Error |
403 | Forbidden | application/json: Error |
404 | Storage backend not found | - |
405 | The name is the reserved primary storage, which is set by the server configuration and read-only (error code read_only) | application/json: Error |
409 | The kind or config cannot change while the backend holds blobs, serves a tier or is named by a tier move | - |
DELETE /api/v1/admin/storage/{name}
Delete storage backend
Delete a storage backend (admin only)
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | yes | - |
Responses
| Status | Description | Body |
|---|---|---|
204 | Storage backend deleted | - |
400 | Invalid request | application/json: Error |
403 | Forbidden | application/json: Error |
404 | Storage backend not found | - |
405 | The name is the reserved primary storage, which is set by the server configuration and read-only (error code read_only) | application/json: Error |
POST /api/v1/admin/storage/{name}/test
Test storage backend
Test connection to a storage backend (admin only)
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | yes | - |
Responses
| Status | Description | Body |
|---|---|---|
200 | Test result | application/json: object |
400 | Invalid request, including a NUL byte in the URL or the body | application/json: Error |
404 | Storage backend not found | - |
Fields of the 200 response (application/json):
| Field | Type | Required | Description |
|---|---|---|---|
error | string | no | - |
message | string | no | - |
ok | boolean | no | - |
POST /api/v1/admin/tiering/dry-run
Simulate storage policies
Reports what a mover pass would move now (counts, bytes, per route and policy, and a sample) without changing anything. With policy set only that draft is simulated; otherwise every enabled policy and promote-on-read are (admin only)
Request body (required)
application/json: object
| Field | Type | Required | Description |
|---|---|---|---|
policy | StoragePolicyInput | no | - |
sample_limit | integer | no | Between 0 and 200; default 200. |
Responses
| Status | Description | Body |
|---|---|---|
200 | Simulation result | application/json: TierDryRun |
400 | Invalid request | - |
403 | Admin access required | - |
GET /api/v1/admin/tiering/policies
List storage policies
Lists lifecycle policies in evaluation order (admin only)
Responses
| Status | Description | Body |
|---|---|---|
200 | List of policies | application/json: object |
403 | Admin access required | - |
Fields of the 200 response (application/json):
| Field | Type | Required | Description |
|---|---|---|---|
items | array of StoragePolicy | no | - |
total | integer | no | - |
POST /api/v1/admin/tiering/policies
Create storage policy
Creates a lifecycle policy; the first enabled policy matching a blob decides its tier (admin only)
Request body (required)
application/json: StoragePolicyInput
Responses
| Status | Description | Body |
|---|---|---|
201 | Policy created | application/json: StoragePolicy |
400 | Invalid request | - |
403 | Admin access required | - |
409 | Name already used | - |
GET /api/v1/admin/tiering/policies/{id}
Get storage policy
Gets a lifecycle policy (admin only)
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (uuid) | yes | - |
Responses
| Status | Description | Body |
|---|---|---|
200 | Policy | application/json: StoragePolicy |
400 | Invalid request, including a NUL byte in the URL or the body | application/json: Error |
403 | Admin access required | - |
404 | Storage policy not found | - |
PUT /api/v1/admin/tiering/policies/{id}
Replace storage policy
Replaces every field of a lifecycle policy (admin only)
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (uuid) | yes | - |
Request body (required)
application/json: StoragePolicyInput
Responses
| Status | Description | Body |
|---|---|---|
200 | Policy updated | application/json: StoragePolicy |
400 | Invalid request | - |
403 | Admin access required | - |
404 | Storage policy not found | - |
409 | Name already used | - |
DELETE /api/v1/admin/tiering/policies/{id}
Delete storage policy
Deletes a lifecycle policy; blobs already moved stay where they are (admin only)
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (uuid) | yes | - |
Responses
| Status | Description | Body |
|---|---|---|
204 | Policy deleted | - |
400 | Invalid request, including a NUL byte in the URL or the body | application/json: Error |
403 | Admin access required | - |
404 | Storage policy not found | - |
POST /api/v1/admin/tiering/run
Run the tier mover now
Queues an immediate mover pass on the replica holding the mover lock (admin only)
Responses
| Status | Description | Body |
|---|---|---|
202 | Pass requested | application/json: object |
403 | Admin access required | - |
409 | The mover is disabled | - |
Fields of the 202 response (application/json):
| Field | Type | Required | Description |
|---|---|---|---|
started | boolean | no | False when a pass was already running. |
GET /api/v1/admin/tiering/status
Tier mover status
State of the background mover and the moves still in its crash-recovery journal (admin only)
Responses
| Status | Description | Body |
|---|---|---|
200 | Mover status | application/json: TierMoverStatus |
403 | Admin access required | - |
GET /api/v1/admin/tiering/tiers
List storage tiers
Lists the storage tiers (hottest first) with their placement: blob count and bytes per tier (admin only)
Responses
| Status | Description | Body |
|---|---|---|
200 | List of tiers | application/json: object |
403 | Admin access required | - |
Fields of the 200 response (application/json):
| Field | Type | Required | Description |
|---|---|---|---|
items | array of StorageTier | no | - |
total | integer | no | - |
POST /api/v1/admin/tiering/tiers
Create storage tier
Maps an existing storage backend to a named tier (admin only)
Request body (required)
application/json: object
| Field | Type | Required | Description |
|---|---|---|---|
backend | string | yes | Name of an existing storage backend. |
name | string | yes | - |
promote_on_read | boolean | no | - |
rank | integer | no | Position from hot (low) to cold (high); defaults to after the last tier. |
Responses
| Status | Description | Body |
|---|---|---|
201 | Tier created | application/json: StorageTier |
400 | Invalid request | - |
403 | Admin access required | - |
409 | Name or backend already used by a tier | - |
PATCH /api/v1/admin/tiering/tiers/{name}
Update storage tier
Renames a tier or changes its rank or promote-on-read flag (admin only)
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | yes | - |
Request body (required)
application/json: object
| Field | Type | Required | Description |
|---|---|---|---|
name | string | no | - |
promote_on_read | boolean | no | - |
rank | integer | no | - |
Responses
| Status | Description | Body |
|---|---|---|
200 | Tier updated | application/json: StorageTier |
400 | Invalid request | - |
403 | Admin access required | - |
404 | Storage tier not found | - |
409 | Name already used | - |
DELETE /api/v1/admin/tiering/tiers/{name}
Delete storage tier
Deletes a tier that holds no blobs and is not referenced by a policy; the primary tier cannot be deleted (admin only)
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | yes | - |
Responses
| Status | Description | Body |
|---|---|---|
204 | Tier deleted | - |
400 | The primary tier cannot be deleted | - |
403 | Admin access required | - |
404 | Storage tier not found | - |
409 | Tier still holds blobs, has moves in progress or is used by a policy | - |