JSON API Reference
Oyster serves the JSON API under /api/v1/. All requests and responses
use JSON (except blob content, which is raw binary). Authenticated endpoints
require a Bearer token in the Authorization header.
What is the base URL?
All API endpoints use the /api/v1 prefix:
$OYSTER_URL/api/v1/
Throughout this reference, $OYSTER_URL represents your Oyster
server address (for example, http://localhost:3000).
How to authenticate requests
Most endpoints require a Bearer token:
Authorization: Bearer <your-api-key>
Endpoints that do not require authentication:
- Reading blobs by key or blob ID
- Health, readiness, and metrics probes
- OpenAPI documentation
What do error responses look like?
All errors return a JSON body with a single error field:
{
"error": "human-readable error message"
}
Status codes
| Code | Meaning |
|---|---|
200 | Success (GET, PATCH) |
201 | Created (POST, PUT) |
204 | No Content (DELETE) |
304 | Not Modified: If-None-Match matched on a GET request |
400 | Bad Request: invalid input or validation failure |
401 | Unauthorized: missing or invalid API key |
402 | Payment Required: the Pearl-derived wallet lacks WAL or SUI to fund the onchain action (see Cross-cutting error contracts) |
404 | Not Found: resource doesn't exist or your account doesn't own it |
409 | Conflict: resource already exists or limit reached |
412 | Precondition Failed: If-Match or If-None-Match condition not met |
413 | Payload Too Large: blob exceeds 1GB |
500 | Internal Server Error |
501 | Not Implemented: endpoint exists but isn't functional yet |
503 | Service Unavailable: a dependent service is unreachable |
Only 3 account stubs currently return 501. The routes exist, but no
implementation backs them yet: PUT /account/billing, GET /account/report, and
POST /account/transfer. The per-endpoint reference intentionally omits them
until they are functional.
Cross-cutting error contracts
Multiple routes share a few error bodies, which carry a
structured block alongside the standard error string. They
appear once here, and per-route docs link back.
-
InsufficientBalance(402): the Pearl-derived wallet doesn't hold enough WAL or SUI to fund the onchain action. Body carries afunding_required: { wal_frost, sui_mist }block (both decimal strings). Currently fires onPUT /buckets/{bucket}/blobs/{key}(see Store Blob) andDELETE /buckets/{bucket}/blobs/{key}(see Delete Blob). When the lookup itself fails,funding_requiredisnull.The body has this shape:
{
"error": "human-readable error message",
"funding_required": {
"wal_frost": "decimal string",
"sui_mist": "decimal string"
}
} -
CapExceeded(400): the upload would push the account past its per-accountmax_unencoded_bytescap. Body carries acap_exceededblock pointing at the admin endpoint that can raise the cap. Currently fires onPUT /buckets/{bucket}/blobs/{key}(see Store Blob). The cap is an upper bound by default; a per-accountavg_blob_sizeturns it into a lower bound on storable capacity for blobs of that size.
The admin-side onchain shrink endpoint
(PUT /accounts/{account_id}/max-storage)
has its own 400 variants (would_orphan, shrink_aborted),
which the admin reference documents.
How to paginate list results
List endpoints use cursor-based pagination:
Query parameters:
cursor(optional): opaque string from a previous response'snext_cursorlimit(optional): number of items per page (default: 20, max: 100)
Response format:
{
"data": [ ... ],
"next_cursor": "opaque-cursor-string"
}
When next_cursor is null, there are no more results. To fetch the next
page, pass the next_cursor value as the cursor query parameter.
Example: paginating through buckets:
# First page
curl -s -H "Authorization: Bearer $API_KEY" \
"$OYSTER_URL/api/v1/buckets?limit=10" | jq
# Next page (using next_cursor from previous response)
curl -s -H "Authorization: Bearer $API_KEY" \
"$OYSTER_URL/api/v1/buckets?limit=10&cursor=eyJjcmVhdGVk..." | jq
Where is the interactive documentation?
Oyster serves an interactive OpenAPI UI at:
$OYSTER_URL/api/docs
Explore and test all endpoints directly from your browser.
How the server handles out-of-range limits
When you pass a limit greater than the maximum, the server clamps it to 100 items and does not return an error. A limit of 0 or less returns 400 with the error limit must be positive.
What is the Pearl-derived wallet?
Pearl is the custodial wallet service that derives each Oyster account's Sui wallet and signs the transactions Oyster submits. See What is Pearl? for how Pearl derives and protects the keys.