Bucket0 Developer Docs
Two ways to integrate: AgentBucket API for AI agents, and an S3-compatible API for standard tooling.
AgentBucket API
Bearer token auth for AI agents to upload, download, list, delete files, and create folders
S3-Compatible API
AWS Signature V4 auth — works with AWS CLI, SDKs, Cyberduck, rclone, and more
Introduction
What you can build with Bucket0
Bucket0 exposes two developer APIs for programmatic access to your storage:
AgentBucket API
Designed for AI agents. Create API keys from your dashboard, then use Bearer token auth to upload, download, list, delete files, and create folders. Keys are prefixed with b0ak_.
S3-Compatible API
A standard S3 endpoint with AWS Signature V4 authentication. Create access keys from your dashboard, then use any S3 client — AWS CLI, boto3, aws-sdk, Cyberduck, rclone, etc. Access key format: B0IAXXXXXXXXXXXXXXXX.
Authentication
How to get credentials from the dashboard
AgentBucket — Bearer Token
1. Go to Dashboard > AgentBucket > API Keys > New Key
2. Name your key (e.g., "my-coding-agent")
3. Choose destination: AgentBucket (files go to review tab) or My Drive (files go directly to your drive, optionally into a folder)
4. Copy the key — it's shown only once
5. Copy the API Guide (available in the same tab) and give it to your agent as a reference file — it includes endpoints, examples, error handling, and best practices for instant setup
Authorization: Bearer b0ak_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxS3 API — AWS Signature V4
1. Go to Dashboard > S3 API > Access Keys > Create Key
2. Name your key (e.g., "CLI Access")
3. Copy both the Access Key ID (B0IAXXXXXXXXXXXXXXXX) and Secret Access Key — shown only once
4. Copy the S3 API Integration Guide (available in the same tab) and give it to your agent — it covers all S3 operations, error handling, and best practices
aws configure --profile bucket0
AWS Access Key ID: B0IAXXXXXXXXXXXXXXXX
AWS Secret Access Key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Default region name: autoEndpoint: https://s3.bucket0.com
Important: Both API keys and S3 credentials are shown only once at creation. Store them securely. You can deactivate or delete keys anytime from the dashboard.
AgentBucket API
File storage for AI agents
AgentBucket lets AI agents save files directly to your storage using API keys. Files land in your Agent Storage tab by default (for review before moving to drive), or directly in your Drive if the key is configured with "My Drive" destination.
Endpoints
POST /api/agent-bucket/files/uploadUpload a file (multipart/form-data)
GET /api/agent-bucket/filesList files (paginated)
GET /api/agent-bucket/files/downloadDownload a file by key
DELETE /api/agent-bucket/filesDelete a file by key
POST /api/agent-bucket/files/folderCreate a folder
Upload a File
Send multipart/form-data with a file field and optional filename (defaults to file name). Files are encrypted with AES-128-GCM automatically.
const apiKey = 'b0ak_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
const formData = new FormData();
formData.append('file', fileBuffer);
formData.append('filename', 'research/results.json');
const response = await fetch('https://bucket0.com/api/agent-bucket/files/upload', {
method: 'POST',
headers: { 'Authorization': `Bearer ${apiKey}` },
body: formData,
});
const data = await response.json();
// { success: true, key: "research/results.json", fileName: "results.json", size: 2048, destination: "agent" }Response includes: success, key, fileName, size, destination("agent" or "drive").
List Files
const apiKey = 'b0ak_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
const response = await fetch('https://bucket0.com/api/agent-bucket/files?page=1&pageSize=50', {
headers: { 'Authorization': `Bearer ${apiKey}` },
});
const { files, pagination } = await response.json();
// pagination: { total: 25, page: 1, pageSize: 50, hasMore: false }
files.forEach(file => {
console.log(`${file.fileName} - ${file.size} bytes (via ${file.uploadedVia})`);
});Params: page (default 1), pageSize (default 50, max 100). Each file includes: key, fileName, size, mimeType, isStarred, uploadedVia, createdAt, updatedAt.
Download a File
Returns the binary file stream. Files are automatically decrypted. Response headers include Content-Type, Content-Disposition, and Content-Length.
const apiKey = 'b0ak_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
const key = 'research/results.json';
const response = await fetch(
`https://bucket0.com/api/agent-bucket/files/download?key=${encodeURIComponent(key)}`,
{ headers: { 'Authorization': `Bearer ${apiKey}` } }
);
// Response is binary with headers:
// Content-Type, Content-Disposition, Content-Length
const blob = await response.blob();Delete a File
Deletes the file and automatically releases storage quota.
DELETE /api/agent-bucket/files?key=research/results.json
Authorization: Bearer b0ak_xxx...
→ { "success": true }Create a Folder
Creates a folder marker. Path cannot contain .. or //.
POST /api/agent-bucket/files/folder
Authorization: Bearer b0ak_xxx...
Content-Type: application/json
{ "path": "reports/daily" }
→ { "success": true, "path": "reports/daily/" }Error Codes
400Missing file, filename, or invalid path
401Missing, invalid, or expired API key
402Plan limit, storage quota, or file size exceeded
404File not found
429Rate limit exceeded (100/min)
S3-Compatible API
Use AWS SDKs, CLI, and S3 tools
Full S3-compatible API with AWS Signature V4. Use AWS CLI, SDKs, Cyberduck, WinSCP, rclone, and any other S3 client.
Endpoint
https://s3.bucket0.comSupported Operations
GET /ListBuckets
GET /{bucket}ListObjectsV2
HEAD /{bucket}HeadBucket
PUT /{bucket}CreateBucket
DELETE /{bucket}DeleteBucket (must be empty)
GET /{bucket}/{key}GetObject (Range supported)
HEAD /{bucket}/{key}HeadObject
PUT /{bucket}/{key}PutObject (auto-creates bucket)
DELETE /{bucket}/{key}DeleteObject (idempotent)
Behavior
- Buckets auto-create on first PutObject — no need to CreateBucket first
- DeleteObject returns 204 even if the object doesn't exist (idempotent)
- GetObject supports Range requests (returns 206 Partial Content)
- PutObject enforces plan storage and file size limits with atomic quota reservation
- DeleteBucket requires the bucket to be empty first
- ListObjectsV2 supports prefix, delimiter, max-keys, and continuation-token
List Buckets
import { S3Client, ListBucketsCommand } from '@aws-sdk/client-s3';
const client = new S3Client({
endpoint: 'https://s3.bucket0.com',
region: 'auto',
credentials: {
accessKeyId: 'YOUR_ACCESS_KEY_ID',
secretAccessKey: 'YOUR_SECRET_ACCESS_KEY',
},
});
const { Buckets } = await client.send(new ListBucketsCommand({}));
Buckets?.forEach(b => console.log(b.Name, b.CreationDate));Upload a File
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
const client = new S3Client({
endpoint: 'https://s3.bucket0.com',
region: 'auto',
credentials: {
accessKeyId: 'YOUR_ACCESS_KEY_ID',
secretAccessKey: 'YOUR_SECRET_ACCESS_KEY',
},
});
await client.send(new PutObjectCommand({
Bucket: 'my-bucket',
Key: 'documents/report.pdf',
Body: fileBuffer,
ContentType: 'application/pdf',
}));
// Returns ETag header on successDownload a File
Response includes standard S3 headers: Content-Type, Content-Length, ETag, Last-Modified, Accept-Ranges.
import { S3Client, GetObjectCommand } from '@aws-sdk/client-s3';
const client = new S3Client({
endpoint: 'https://s3.bucket0.com',
region: 'auto',
credentials: {
accessKeyId: 'YOUR_ACCESS_KEY_ID',
secretAccessKey: 'YOUR_SECRET_ACCESS_KEY',
},
});
const response = await client.send(new GetObjectCommand({
Bucket: 'my-bucket',
Key: 'documents/report.pdf',
}));
// response includes: ContentType, ContentLength, ETag, LastModified
const chunks = [];
for await (const chunk of response.Body) {
chunks.push(chunk);
}
const buffer = Buffer.concat(chunks);AWS CLI
# Configure
aws configure --profile bucket0
AWS Access Key ID: B0IAXXXXXXXXXXXXXXXX
AWS Secret Access Key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Default region name: auto
Default output format: json
# List buckets
aws s3 ls --endpoint-url https://s3.bucket0.com --profile bucket0
# Upload file
aws s3 cp report.pdf s3://my-bucket/documents/report.pdf \
--endpoint-url https://s3.bucket0.com --profile bucket0
# Download file
aws s3 cp s3://my-bucket/documents/report.pdf ./report.pdf \
--endpoint-url https://s3.bucket0.com --profile bucket0S3 Error Codes
AccessDeniedInvalid signature or expired credentials
NoSuchBucketBucket does not exist
NoSuchKeyObject does not exist
BucketNotEmptyCannot delete non-empty bucket
QuotaExceededStorage limit reached
EntityTooLargeFile exceeds plan size limit
SDK Examples
Code examples in JavaScript, Python, Go, and Rust
AgentBucket
Upload File
const apiKey = 'b0ak_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
const formData = new FormData();
formData.append('file', fileBuffer);
formData.append('filename', 'research/results.json');
const response = await fetch('https://bucket0.com/api/agent-bucket/files/upload', {
method: 'POST',
headers: { 'Authorization': `Bearer ${apiKey}` },
body: formData,
});
const data = await response.json();
// { success: true, key: "research/results.json", fileName: "results.json", size: 2048, destination: "agent" }List Files
const apiKey = 'b0ak_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
const response = await fetch('https://bucket0.com/api/agent-bucket/files?page=1&pageSize=50', {
headers: { 'Authorization': `Bearer ${apiKey}` },
});
const { files, pagination } = await response.json();
// pagination: { total: 25, page: 1, pageSize: 50, hasMore: false }
files.forEach(file => {
console.log(`${file.fileName} - ${file.size} bytes (via ${file.uploadedVia})`);
});Download File
const apiKey = 'b0ak_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
const key = 'research/results.json';
const response = await fetch(
`https://bucket0.com/api/agent-bucket/files/download?key=${encodeURIComponent(key)}`,
{ headers: { 'Authorization': `Bearer ${apiKey}` } }
);
// Response is binary with headers:
// Content-Type, Content-Disposition, Content-Length
const blob = await response.blob();S3-Compatible API
List Buckets
import { S3Client, ListBucketsCommand } from '@aws-sdk/client-s3';
const client = new S3Client({
endpoint: 'https://s3.bucket0.com',
region: 'auto',
credentials: {
accessKeyId: 'YOUR_ACCESS_KEY_ID',
secretAccessKey: 'YOUR_SECRET_ACCESS_KEY',
},
});
const { Buckets } = await client.send(new ListBucketsCommand({}));
Buckets?.forEach(b => console.log(b.Name, b.CreationDate));Upload
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
const client = new S3Client({
endpoint: 'https://s3.bucket0.com',
region: 'auto',
credentials: {
accessKeyId: 'YOUR_ACCESS_KEY_ID',
secretAccessKey: 'YOUR_SECRET_ACCESS_KEY',
},
});
await client.send(new PutObjectCommand({
Bucket: 'my-bucket',
Key: 'documents/report.pdf',
Body: fileBuffer,
ContentType: 'application/pdf',
}));
// Returns ETag header on successDownload
import { S3Client, GetObjectCommand } from '@aws-sdk/client-s3';
const client = new S3Client({
endpoint: 'https://s3.bucket0.com',
region: 'auto',
credentials: {
accessKeyId: 'YOUR_ACCESS_KEY_ID',
secretAccessKey: 'YOUR_SECRET_ACCESS_KEY',
},
});
const response = await client.send(new GetObjectCommand({
Bucket: 'my-bucket',
Key: 'documents/report.pdf',
}));
// response includes: ContentType, ContentLength, ETag, LastModified
const chunks = [];
for await (const chunk of response.Body) {
chunks.push(chunk);
}
const buffer = Buffer.concat(chunks);Rate Limits
API request limits per user
Request Limits
| Operation | Limit | Window |
|---|---|---|
| File Upload | 100 | per minute |
| General API | 200 | per minute |
| Share Links | 100 | per hour |
| S3 Connection Test | 15 | per minute |
Handling 429 Responses
When rate limited, the response includes headers to help you retry:
X-RateLimit-Limit: 100 # max requests allowed
X-RateLimit-Remaining: 0 # requests remaining
X-RateLimit-Reset: 1713024060 # Unix timestamp when limit resets- Implement exponential backoff — wait for the reset timestamp before retrying
- Cache file listings to reduce API calls
- Store API keys server-side — never expose them in client code