Platform
ScaiWave ScaiGrid ScaiCore ScaiBot ScaiDrive ScaiKey Modellen Tools & Services
Oplossingen
Organisaties Ontwikkelaars Internet Service Providers Managed Service Providers AI-in-a-Box
Kenniscentrum
Ondersteuning Documentation Blog Downloads
Bedrijf
Over ons Onderzoek Vacatures Investeren Contact
Inloggen

Management API

The management API handles everything that is not object data: buckets, access keys, grants, usage, and audit. It is separate from the S3 endpoint and is never co-hosted with it.

  • Base: https://storey.scailabs.ai/api/v1
  • JSON in, JSON out, snake_case fields, RFC 3339 UTC timestamps.
  • Every response carries X-Request-Id. Quote it when reporting a problem.

Authentication#

The console authenticates with your ScaiLabs account through a server-side session — no access token is ever stored in your browser. Requests from the console carry a session cookie plus a CSRF header.

Pagination#

Listings are cursor-based: pass ?limit= (default 50, max 200) and follow next_cursor until it is null. There is no offset pagination — bucket and object listings are unbounded, and offsets over an unbounded set produce duplicates and gaps under concurrent writes.

Errors#

Every error uses one shape:

json
1
2
3
4
5
6
7
8
{
  "error": {
    "code": "BucketNotEmpty",
    "message": "This bucket still contains objects. Delete them first, then delete the bucket.",
    "request_id": "3f2b…",
    "details": null
  }
}

The code is the contract — match on it, not on the message. Messages state what to do next and may be reworded.

Code Status Meaning
Unauthenticated 401 No valid session
Forbidden 403 Your role does not allow this
NotFound 404 No such resource in your tenant
NameConflict 409 That name is already used
BucketNotEmpty 409 Delete the objects first
PlacementUnavailable 409 No cluster serves that region and tier
EntitlementExceeded 409 You are at a limit on your plan
KeyClusterMismatch 409 The key belongs to a different region
OperationInProgress 409 Still provisioning; retry shortly
ValidationError 422 The request was malformed
RateLimited 429 Slow down
ClusterUnavailable 503 Temporary; retry

A resource belonging to another tenant returns NotFound, never Forbidden — a 403 would confirm the id exists somewhere.

Idempotency#

Mutating requests accept an Idempotency-Key header. Replaying a request with the same key returns the original result instead of acting twice. Bucket and key creation are long-running: the response carries an operation_id you can poll at GET /v1/operations/{id}.

Endpoint groups#

Group Purpose
/v1/regions, /tiers, /placements What you can order
/v1/tenant, /tenant/entitlements, /tenant/usage Your account
/v1/buckets Bucket lifecycle, stats, usage
/v1/buckets/{id}/objects Listing, metadata, presigned URLs, delete, copy
/v1/buckets/{id}/share Time-boxed public links
/v1/keys, /v1/buckets/{id}/grants Access keys and their grants
/v1/operations, /v1/audit, /v1/events Progress, history, live updates

Objects: bytes never pass through this API#

Object listing and metadata come from the management API, but the bytes do not. Uploads and downloads use presigned URLs that your client sends directly to the S3 endpoint:

bash
1
2
3
curl -X POST https://storey.scailabs.ai/api/v1/buckets/$BUCKET/objects/presign \
  -H "Content-Type: application/json" \
  -d '{"key": "reports/q2.pdf", "method": "GET", "ttl_seconds": 900}'

That keeps a large transfer off the control plane and means a presigned request is metered exactly like any other S3 request — there is no cheaper path.

Presigned URLs are credentials. Their lifetime is capped by your role, every one is recorded in the audit log, and a share link can be revoked.

Updated 2026-08-09 18:10:55 View source (.md) rev 1