Reference
Limits & quotas
Rate limits, storage caps, geometry constraints, and the size and encoding limits that apply to every request.
Rate limits
| Limit | Value | Scope |
|---|---|---|
| Sustained request rate | 30 per minute | Per credential |
| Burst | 3 per second | Per credential |
| Credential provisioning | 5 per hour | Per source address |
Exceeding a request limit returns 429 with Retry-After: 5:
HTTP/1.1 429 Too Many Requests
Retry-After: 5
{"error":"rate limited","retryAfter":5}
The rate limit is keyed on the credential query parameter, so separate credentials get separate
budgets. If you need more throughput for a single workload, that is a plan conversation rather than
something to engineer around by rotating credentials.
Thirty per minute is lower than it sounds — design for it
The API is a control plane, not a data path: object bytes never traverse it, so a well-built client makes very few calls. A 1 GiB upload is two calls plus the direct shard writes. A client that hits 30 per minute is usually making one call per small object rather than packing them into shared slabs — see Packing strategy.
Storage caps
Each credential carries caps recorded at provisioning:
| Cap | Enforced |
|---|---|
| Maximum stored bytes | Yes — 402 on prepare-write, slabs, and objects |
| Daily read bytes | Recorded, not currently enforced |
| Daily write bytes | Recorded, not currently enforced |
| Monthly spend | Recorded, not currently enforced |
Cap accounting is in whole 4 MiB sectors:
| Endpoint | Accounted as |
|---|---|
POST /prepare-write | totalShards × 4 MiB |
POST /slabs | sectors × 4 MiB per slab |
POST /objects | 4 KiB per object |
Small objects in their own slabs are expensive
A 100 KiB object written as its own 10-of-15 slab is accounted at 15 whole sectors — 60 MiB, a 600× overhead against its logical size. This is arithmetic, not a penalty: 15 providers each hold a sector, and a sector is the unit they deal in. Pack small objects into shared slabs and the overhead disappears.
Erasure coding constraints
| Constraint | Value |
|---|---|
Minimum redundancy (totalShards / minShards) | 1.5× |
| Maximum redundancy | 4.0× |
minShards | ≤ totalShards |
| Default geometry | 10 data + 5 parity = 15 |
encryptionKey length | exactly 32 bytes |
| Duplicate provider within a slab | rejected |
| Duplicate sector root within a slab | rejected |
| Sector size | 4 MiB |
Request constraints
| Constraint | Value |
|---|---|
| Object key | exactly 32 bytes, 64 hex characters, no / |
| Slab ID | exactly 32 bytes, 64 hex characters |
| Provider public key | ed25519: + 64 hex characters |
| Sector root | 64 hex characters |
credential / signature encoding | base64url with padding |
appKey encoding | base64url without padding |
| Byte-slice JSON fields | standard base64 with padding |
validUntil | unix seconds, decimal in the query, little-endian uint64 in the hash |
Pagination
| Endpoint | Mechanism | Default | Notes |
|---|---|---|---|
GET /slabs | limit + offset | 50 | Not a stable cursor; entries can be missed if the set changes between pages. |
GET /objects | limit + after timestamp | 50 | Preferred. Stable enough for synchronisation; make application idempotent for timestamp ties. |
For a complete enumeration, walk GET /objects and collect slab IDs from the records rather than
paging GET /slabs.
Signature expiry
validUntil is chosen entirely by you. There is no server-imposed maximum, which means the
discipline is yours:
- 60 seconds for interactive calls.
- Minutes, not days. A signed URL is a bearer capability until it expires; expiry is the only replay protection in the scheme.
- Never sign a
DELETEfar into the future. That signature is a deletion capability for as long as it remains valid, wherever the URL was logged.
No CORS
The API cannot be called from a browser
No Access-Control-Allow-Origin header is sent on any endpoint, so cross-origin browser requests are
blocked by the browser regardless of what you do client-side. Call the API from a server-side runtime,
or proxy it through your own backend — which is the better pattern anyway, since it keeps your
credential's private key off the client.
Availability expectations
| Endpoint | Behaviour |
|---|---|
prepare-write | May return 503 when provider availability dips. Always retry with backoff. |
| Manifest endpoints | Expected to be consistently available; 500 is a bug worth reporting. |
| Shard reads and writes | Depend on individual providers, which fail routinely. Your client should treat individual provider failure as normal and route around it. |
The base tiers are provided without a service level agreement. Contractual availability and support commitments are agreed on the Enterprise tier — see pricing.