Getting Started

Follow these steps to complete your first interactions with Oyster. By the end, you have created a bucket, uploaded a blob, and downloaded it back.

Prerequisites

  • curl: for making HTTP requests to the JSON API
  • AWS CLI (optional): for using the S3-compatible API (install guide)

Obtaining Credentials

Oyster uses a two-tier auth model: operators manage accounts with long-lived per-app admin keys, and end users authenticate data operations with API keys. Both tiers use Authorization: Bearer <hex>; the route prefix selects which credential table is consulted.

For Operators

The server operator creates an app, gets back a first admin key, and provisions accounts. See the Admin API docs for full details.

# 1. Create an app (server operator runs this once). `app new` auto-issues
#    a first admin key by default; pass --no-key to opt out.
oysterd app new --name my-app --contact_email admin@example.com
# Prints: 550e8400-e29b-41d4-a716-446655440000   <- app id
# Prints: <64-char hex admin key>                 <- save this

export ADMIN_KEY="<64-char hex admin key from above>"

# 2. Create an account using the admin key
export OYSTER_URL="http://localhost:3000"
curl -s -X POST \
  -H "Authorization: Bearer $ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "my-app-user"}' \
  "$OYSTER_URL/api/v1/accounts" | jq

The response includes the account ID and an initial API key:

{
  "account_id": "550e8400-e29b-41d4-a716-446655440000",
  "api_key": {
    "id": "b2c3d4e5-f6a7-4b8c-9d0e-1f2a3b4c5d6e",
    "prefix": "a1b2c3d4",
    "bearer_token": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
    "created_at": "2025-01-15T10:30:00Z"
  }
}

Save the account_id and bearer_token. The token is only shown once.

export ACCOUNT_ID="550e8400-e29b-41d4-a716-446655440000"
export API_KEY="a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2"

For End Users

Your operator provides you with an API key. Store it in an environment variable for the rest of this guide:

export OYSTER_URL="http://localhost:3000"
export API_KEY="your-api-key-here"

Create Your First Bucket

Buckets are named containers for your blobs. Create one called my-bucket:

curl -s -X POST \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "my-bucket"}' \
  "$OYSTER_URL/api/v1/buckets" | jq

Response:

{
  "name": "my-bucket",
  "account_id": "550e8400-e29b-41d4-a716-446655440000",
  "created_at": "2025-01-15T10:30:00Z"
}

Upload a Blob

Upload a text file to your bucket with the key hello.txt:

curl -s -X PUT \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: text/plain" \
  --data-binary "Hello, Oyster!" \
  "$OYSTER_URL/api/v1/buckets/my-bucket/blobs/hello.txt" | jq

Response:

{
  "key": "hello.txt",
  "blob_id": "2cf24dba5fb0a30e...",
  "size": 14,
  "md5": "9a0364b9e99bb480...",
  "sui_object_id": null,
  "created_at": "2025-01-15T10:31:00Z"
}

You can also upload a file from disk:

curl -s -X PUT \
  -H "Authorization: Bearer $API_KEY" \
  --data-binary @photo.png \
  "$OYSTER_URL/api/v1/buckets/my-bucket/blobs/images/photo.png" | jq

Download a Blob

Blob reads are public (no authentication needed):

curl -s "$OYSTER_URL/api/v1/buckets/my-bucket/blobs/hello.txt"

Output:

Hello, Oyster!

List Blobs in a Bucket

curl -s -H "Authorization: Bearer $API_KEY" \
  "$OYSTER_URL/api/v1/buckets/my-bucket/blobs" | jq

Response:

{
  "data": [
    {
      "key": "hello.txt",
      "blob_id": "2cf24dba5fb0a30e...",
      "bucket_name": "my-bucket",
      "content_type": "text/plain",
      "size": 14,
      "md5": "9a0364b9e99bb480...",
      "created_at": "2025-01-15T10:31:00Z"
    }
  ],
  "next_cursor": null
}

Delete a Blob

curl -s -X DELETE \
  -H "Authorization: Bearer $API_KEY" \
  "$OYSTER_URL/api/v1/buckets/my-bucket/blobs/hello.txt"

Returns HTTP 204 (no content) on success.

Create Additional API Keys (Operator)

Additional API keys are created by the operator through the Admin API using admin-key authentication. This requires the $ADMIN_KEY and $ACCOUNT_ID variables from the Obtaining Credentials section.

curl -s -X POST \
  -H "Authorization: Bearer $ADMIN_KEY" \
  "$OYSTER_URL/api/v1/accounts/$ACCOUNT_ID/api-keys" | jq

Response:

{
  "id": "b2c3d4e5-f6a7-4b8c-9d0e-1f2a3b4c5d6e",
  "prefix": "a1b2c3d4",
  "bearer_token": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
  "created_at": "2025-01-15T10:32:00Z"
}

Important: The bearer_token field is only shown once. Save it immediately.

See the Admin API docs for full details including error handling and key revocation.

Set Up S3 Access Keys (Operator)

To use the AWS CLI or any S3-compatible SDK, the operator creates S3 access keys through the Admin API. This requires the $ADMIN_KEY and $ACCOUNT_ID variables from the Obtaining Credentials section.

curl -s -X POST \
  -H "Authorization: Bearer $ADMIN_KEY" \
  "$OYSTER_URL/api/v1/accounts/$ACCOUNT_ID/access-keys" | jq

Response:

{
  "access_key_id": "OYAK1234567890ABCDEF",
  "secret_access_key": "abcdef1234567890abcdef1234567890abcdef12",
  "created_at": "2025-01-15T10:33:00Z"
}

Important: The secret_access_key is only shown once. Save it immediately. You can have up to 3 active S3 access keys per account.

Then configure the AWS CLI:

aws configure set aws_access_key_id "OYAK1234567890ABCDEF" --profile oyster
aws configure set aws_secret_access_key "abcdef1234567890..." --profile oyster
aws configure set region "us-east-1" --profile oyster
aws configure set endpoint_url "$OYSTER_URL" --profile oyster

Now you can use standard S3 commands:

# Create a bucket
aws --profile oyster s3api create-bucket --bucket my-s3-bucket

# Upload a file
aws --profile oyster s3api put-object \
  --bucket my-s3-bucket --key hello.txt --body hello.txt

# Download a file
aws --profile oyster s3api get-object \
  --bucket my-s3-bucket --key hello.txt downloaded.txt

For the full S3 API reference, see S3 API Reference.

What's Next