File storage
Covers 3 API operations in the storage category.
| Method | Path | Description |
|---|---|---|
| GET | /v1/orgs/{orgSlug}/projects/{projectName}/storage | Object storage status (runlot storage usage) |
| POST | /v1/orgs/{orgSlug}/projects/{projectName}/storage | Grant storage (called by runlot deploy when it reads a \\"storage\\": true declaration) |
| DELETE | /v1/orgs/{orgSlug}/projects/{projectName}/storage | Unprovision storage usage (runlot storage delete) |
GET /v1/orgs/{orgSlug}/projects/{projectName}/storage
Whether enabled, prefix, quota, usage (docs/storage.md §7, §8). usedBytes is the last
observed value reported by the node, so it lags by the reporting interval — the
quota can be slightly exceeded in the meantime.
Object listings and signed URLs are not part of this API. Credentials live only on node-agent (§4.1), and not sending bytes to CP a second time is the decision from §5.
viewer or above.
operationId getStorage
| Status code | Description | Response body |
|---|---|---|
| 200 | Storage status | StorageStatus |
| 403 | — | — |
| 404 | — | — |
| 503 | no_core — no connection to cp-core | Error |
POST /v1/orgs/{orgSlug}/projects/{projectName}/storage
This is idempotent — calling it twice leaves the prefix unchanged. If a retry changed the prefix, every object already stored under that prefix would become invisible, and that loss would not surface immediately.
There is no request body. The prefix is the isolation boundary (docs/storage.md §4.4), and the quota is set by the plan (§4.5), so neither is a value the user sets.
Once enabled, the node connects env.storage to the worker on the next convergence. As
with env.db, no redeploy is needed.
member and above. Audited as storage.grant.
operationId grantStorage
| Status code | Description | Response body |
|---|---|---|
| 200 | Grant status (existing value if it was already there) | StorageStatus |
| 403 | — | — |
| 404 | — | — |
| 503 | no_core | Error |
DELETE /v1/orgs/{orgSlug}/projects/{projectName}/storage
Objects are not deleted. Deleting everything under the prefix must be a CP operation
idempotent by op_id (docs/storage.md §7, the same lane as database deletion), and that
lane does not exist yet — this fact is recorded in the audit log.
Disabling is also idempotent. It returns 204 even when storage was not enabled.
admin and above — billing stops, but the objects become orphaned, so this is not treated
at the same level as a deployment rollback. Audited as storage.revoke.
operationId revokeStorage
| Status code | Description | Response body |
|---|---|---|
| 204 | detached | — |
| 403 | — | — |
| 404 | — | — |
| 503 | no_core | Error |