Skip to main content

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​

CodeMeaning
200Success (GET, PATCH)
201Created (POST, PUT)
204No Content (DELETE)
304Not Modified: If-None-Match matched on a GET request
400Bad Request: invalid input or validation failure
401Unauthorized: missing or invalid API key
402Payment Required: the Pearl-derived wallet lacks WAL or SUI to fund the onchain action (see Cross-cutting error contracts)
404Not Found: resource doesn't exist or your account doesn't own it
409Conflict: resource already exists or limit reached
412Precondition Failed: If-Match or If-None-Match condition not met
413Payload Too Large: blob exceeds 1GB
500Internal Server Error
501Not Implemented: endpoint exists but isn't functional yet
503Service 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 a funding_required: { wal_frost, sui_mist } block (both decimal strings). Currently fires on PUT /buckets/{bucket}/blobs/{key} (see Store Blob) and DELETE /buckets/{bucket}/blobs/{key} (see Delete Blob). When the lookup itself fails, funding_required is null.

    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-account max_unencoded_bytes cap. Body carries a cap_exceeded block pointing at the admin endpoint that can raise the cap. Currently fires on PUT /buckets/{bucket}/blobs/{key} (see Store Blob). The cap is an upper bound by default; a per-account avg_blob_size turns 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's next_cursor
  • limit (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.