API Reference
v1The Beezifi Storage API is a RESTful HTTP API. All request and response bodies are JSON unless you are uploading or downloading file content. Authentication uses API keys sent as request headers.
Authentication
The API supports two authentication methods: API Keys (recommended for server-to-server) and JWT Bearer tokens (used by the dashboard).
API Key Authentication
Generate an API key from your dashboard under API Keys. Each key has an Access Key (prefix obj_) and a Secret Key shown only once at creation.
Send both on every request:
X-Api-Key: obj_a1b2c3d4 X-Api-Secret: your-secret-key-here
Bearer Token
Log in via POST /api/auth/login to receive a short-lived JWT (12 h). Include it in the Authorization header:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6Ikp...
Quick Start
Node.js / JavaScript
Install via npm: npm i node-fetch form-data or use the native fetch in Node 18+.
Python
Install via pip: pip install requests
HTTP / cURL
Any HTTP client works. Examples below use curl.
S3-Compatible
Coming soon — drop-in S3 SDK support with a compatibility layer.
Upload your first file
import { FormData } from 'node:stream'; import { readFileSync } from 'node:fs'; const BASE = 'https://storage.beezifi.com/api'; const HEADERS = { 'X-Api-Key': 'obj_your_access_key', 'X-Api-Secret': 'your_secret_key', }; // 1. Create a bucket const bucket = await fetch(`${BASE}/buckets`, { method: 'POST', headers: { ...HEADERS, 'Content-Type': 'application/json' }, body: JSON.stringify({ name: 'my-bucket' }), }).then(r => r.json()); // 2. Upload a file const form = new FormData(); form.append('file', new Blob([readFileSync('./photo.jpg')]), 'photo.jpg'); form.append('key', 'photos/photo.jpg'); const obj = await fetch(`${BASE}/buckets/${bucket.id}/objects/upload`, { method: 'POST', headers: HEADERS, body: form, }).then(r => r.json()); console.log('Uploaded:', obj.objectKey);
import requests BASE = 'https://storage.beezifi.com/api' HEADERS = { 'X-Api-Key': 'obj_your_access_key', 'X-Api-Secret': 'your_secret_key', } # 1. Create a bucket bucket = requests.post( f'{BASE}/buckets', headers=HEADERS, json={'name': 'my-bucket'}, ).json() # 2. Upload a file with open('photo.jpg', 'rb') as f: obj = requests.post( f'{BASE}/buckets/{bucket["id"]}/objects/upload', headers=HEADERS, data={'key': 'photos/photo.jpg'}, files={'file': f}, ).json() print('Uploaded:', obj['objectKey'])
# 1. Create a bucket curl -s -X POST https://storage.beezifi.com/api/buckets \ -H "X-Api-Key: obj_your_access_key" \ -H "X-Api-Secret: your_secret_key" \ -H "Content-Type: application/json" \ -d '{"name":"my-bucket"}' # 2. Upload a file curl -s -X POST https://storage.beezifi.com/api/buckets/BUCKET_ID/objects/upload \ -H "X-Api-Key: obj_your_access_key" \ -H "X-Api-Secret: your_secret_key" \ -F "file=@photo.jpg" \ -F "key=photos/photo.jpg"
Buckets
Returns all buckets belonging to your organization, sorted by creation date descending.
curl https://storage.beezifi.com/api/buckets \ -H "X-Api-Key: obj_your_access_key" \ -H "X-Api-Secret: your_secret_key"
const res = await fetch(`${BASE}/buckets`, { headers: HEADERS }); const buckets = await res.json();
200Array of bucket objects
[{ "id": "a1b2c3d4-...", "name": "my-bucket", "visibility": "private", "storageUsedBytes": 1048576, "createdAt": "2026-01-15T10:00:00.000Z" }]
| Body | Type | Required | Description |
|---|---|---|---|
| name | string | required | Unique bucket name within your org. Lowercase letters, numbers, hyphens. |
| visibility | string | optional | private (default) or public. Public buckets allow unauthenticated downloads. |
curl -X POST https://storage.beezifi.com/api/buckets \ -H "X-Api-Key: obj_your_access_key" \ -H "X-Api-Secret: your_secret_key" \ -H "Content-Type: application/json" \ -d '{"name":"my-bucket","visibility":"private"}'
const bucket = await fetch(`${BASE}/buckets`, { method: 'POST', headers: { ...HEADERS, 'Content-Type': 'application/json' }, body: JSON.stringify({ name: 'my-bucket' }), }).then(r => r.json());
201Bucket object
| Body | Type | Required | Description |
|---|---|---|---|
| visibility | string | required | private or public |
curl -X PUT https://storage.beezifi.com/api/buckets/BUCKET_ID/policy \ -H "X-Api-Key: obj_your_access_key" \ -H "X-Api-Secret: your_secret_key" \ -H "Content-Type: application/json" \ -d '{"visibility":"public"}'
Objects
| Query | Type | Required | Description |
|---|---|---|---|
| prefix | string | optional | Filter objects by key prefix, e.g. images/ |
| limit | integer | optional | Max results (default 100, max 1000) |
| offset | integer | optional | Pagination offset |
| includeDeleted | boolean | optional | Include soft-deleted objects |
curl "https://storage.beezifi.com/api/buckets/BUCKET_ID/objects?prefix=images/" \ -H "X-Api-Key: obj_your_access_key" \ -H "X-Api-Secret: your_secret_key"
200Paginated object list
{ "total": 42, "objects": [{ "id": "...", "objectKey": "images/photo.jpg", "sizeBytes": 204800, "contentType":"image/jpeg", "etag": "d41d8cd9...", "createdAt": "2026-01-15T10:00:00.000Z" }] }
Upload a file using multipart/form-data. Maximum size is configurable (default 1 GB).
| Form Field | Type | Required | Description |
|---|---|---|---|
| file | file | required | The file binary |
| key | string | required | Object key (path), e.g. images/photo.jpg. Use / as a folder separator. |
| metadata | JSON string | optional | Custom key/value metadata as a JSON string |
curl -X POST https://storage.beezifi.com/api/buckets/BUCKET_ID/objects/upload \ -H "X-Api-Key: obj_your_access_key" \ -H "X-Api-Secret: your_secret_key" \ -F "file=@/path/to/photo.jpg" \ -F "key=images/photo.jpg"
const form = new FormData(); form.append('file', fileBlob, 'photo.jpg'); form.append('key', 'images/photo.jpg'); const obj = await fetch(`${BASE}/buckets/${bucketId}/objects/upload`, { method: 'POST', headers: HEADERS, // do NOT set Content-Type — let fetch set it with boundary body: form, }).then(r => r.json());
import requests with open('photo.jpg', 'rb') as f: obj = requests.post( f'{BASE}/buckets/{bucket_id}/objects/upload', headers=HEADERS, data={'key': 'images/photo.jpg'}, files={'file': ('photo.jpg', f, 'image/jpeg')}, ).json()
201Uploaded object metadata
{ "id": "...", "objectKey": "images/photo.jpg", "sizeBytes": 204800, "contentType":"image/jpeg", "etag": "d41d8cd9..." }
Streams the file content. The response Content-Type matches the uploaded file type. objectKey supports nested paths, e.g. images/folder/photo.jpg.
curl -O https://storage.beezifi.com/api/buckets/BUCKET_ID/objects/images/photo.jpg \ -H "X-Api-Key: obj_your_access_key" \ -H "X-Api-Secret: your_secret_key"
200File binary stream
Soft-deletes the object. It can be recovered within your retention window using the /recover endpoint.
curl -X DELETE https://storage.beezifi.com/api/buckets/BUCKET_ID/objects/images/photo.jpg \ -H "X-Api-Key: obj_your_access_key" \ -H "X-Api-Secret: your_secret_key"
200{ "deleted": true }
Download an object without authentication. The bucket must have visibility: "public". Use this URL directly in <img>, <video>, or <a> tags.
# No headers needed — share this URL directly
https://storage.beezifi.com/api/public/objects/BUCKET_ID/images/photo.jpg
Generate a time-limited URL that grants temporary access to a private object — useful for sharing downloads without exposing your API key.
| Body | Type | Required | Description |
|---|---|---|---|
| objectKey | string | required | Key of the object to sign |
| expiresIn | integer | optional | Seconds until expiry (default 3600, max 604800) |
curl -X POST https://storage.beezifi.com/api/buckets/BUCKET_ID/signed-url \ -H "X-Api-Key: obj_your_access_key" \ -H "X-Api-Secret: your_secret_key" \ -H "Content-Type: application/json" \ -d '{"objectKey":"images/photo.jpg","expiresIn":3600}'
200{ "url": "https://storage.beezifi.com/..." }
API Keys
curl https://storage.beezifi.com/api/auth/api-keys \ -H "X-Api-Key: obj_your_access_key" \ -H "X-Api-Secret: your_secret_key"
secretKey is only returned once. Store it securely — it cannot be retrieved again.
| Body | Type | Required | Description |
|---|---|---|---|
| label | string | required | Human-readable label for this key, e.g. "Production server" |
curl -X POST https://storage.beezifi.com/api/auth/api-keys \ -H "X-Api-Key: obj_your_access_key" \ -H "X-Api-Secret: your_secret_key" \ -H "Content-Type: application/json" \ -d '{"label":"Production server"}'
201New API key (secret shown once)
{ "id": "...", "accessKey": "obj_a1b2c3d4", "secretKey": "sk_live_...", // save this — shown only once "label": "Production server" }
Usage
curl https://storage.beezifi.com/api/usage/summary \ -H "X-Api-Key: obj_your_access_key" \ -H "X-Api-Secret: your_secret_key"
200
{ "storageUsedBytes": 1073741824, "storageQuotaBytes": 26843545600, "bandwidthUsedBytes": 524288000, "bandwidthQuotaBytes": 107374182400, "objectCount": 1284, "bucketCount": 3 }
Errors
All errors return a JSON body with an error string and optional details.
{ "error": "Authentication required", "details": null, "requestId": "cb34396e-dd46-49d3-b613-ceea53c41525" }
| Status | Meaning |
|---|---|
400 | Bad request — missing or invalid parameters |
401 | Unauthorized — missing or expired credentials |
403 | Forbidden — valid credentials but insufficient permissions |
404 | Not found — bucket or object does not exist |
409 | Conflict — duplicate name or key |
413 | Payload too large — file exceeds the upload size limit |
429 | Rate limited — slow down requests |
500 | Internal server error — something went wrong on our end |
requestId you can share with support to help diagnose issues.