Beezifi Storage API Docs
v1
OpenAPI JSON Home Dashboard →

API Reference

All systems operational
REST API  ·  JSON
API Version: v1
Base URL https://storage.beezifi.com/api

The 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.

ℹ All API requests must be made over HTTPS. HTTP requests will be redirected to HTTPS.

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...
⚠ Never expose your Secret Key in client-side code. Use API keys only on your server or backend functions.

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('objectKey', '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.object_key);
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={'objectKey': 'photos/photo.jpg'},
        files={'file': f},
    ).json()

print('Uploaded:', obj['object_key'])
# 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 "objectKey=photos/photo.jpg"

Buckets

GET /buckets List all 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,
  "created_at": "2026-01-15T10:00:00.000Z"
}]
POST /buckets Create a bucket
BodyTypeRequiredDescription
namestringrequiredUnique bucket name within your org. Lowercase letters, numbers, hyphens.
visibilitystringoptionalprivate (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

PUT /buckets/:bucketId/policy Set bucket visibility
BodyTypeRequiredDescription
visibilitystringrequiredprivate 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

GET /buckets/:bucketId/objects List objects in a bucket
QueryTypeRequiredDescription
prefixstringoptionalFilter objects by key prefix, e.g. images/
limitintegeroptionalMax results (default 100, max 1000)
offsetintegeroptionalPagination offset
includeDeletedbooleanoptionalInclude 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

[{
    "id":          "...",
    "object_key": "images/photo.jpg",
    "size_bytes": 204800,
    "content_type":"image/jpeg",
    "etag":       "d41d8cd9...",
    "created_at": "2026-01-15T10:00:00.000Z"
  }]
POST /buckets/:bucketId/objects/upload Upload an object

Upload a file using multipart/form-data. Maximum size is configurable (default 1 GB).

Form FieldTypeRequiredDescription
filefilerequiredThe file binary
keystringrequiredObject key (path), e.g. images/photo.jpg. Use / as a folder separator.
metadataJSON stringoptionalCustom 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('objectKey', '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={'objectKey': 'images/photo.jpg'},
        files={'file': ('photo.jpg', f, 'image/jpeg')},
    ).json()

201Uploaded object metadata

{
  "id":          "...",
  "object_key": "images/photo.jpg",
  "size_bytes": 204800,
  "content_type":"image/jpeg",
  "etag":       "d41d8cd9..."
}
GET /buckets/:bucketId/objects/:objectKey Download an object

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

DELETE /buckets/:bucketId/objects/:objectKey Delete an object

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 }

GET /public/objects/:bucketId/:objectKey Public download (no auth)

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
POST /buckets/:bucketId/signed-url Generate a signed URL

Generate a time-limited URL that grants temporary access to a private object — useful for sharing downloads without exposing your API key.

BodyTypeRequiredDescription
objectKeystringrequiredKey of the object to sign
expiresInSecondsintegeroptionalSeconds until expiry (default 3600, min 60, max 86400)
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","expiresInSeconds":3600}'

200{ "url": "https://storage.beezifi.com/...", "expiresAt": 1748000000 }

API Keys

GET /auth/api-keys List 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"
POST /auth/api-keys Create an API key
⚠ The secretKey is only returned once. Store it securely — it cannot be retrieved again.
BodyTypeRequiredDescription
labelstringrequiredHuman-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

GET /usage/summary Get storage & bandwidth 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"
}
StatusMeaning
400Bad request — missing or invalid parameters
401Unauthorized — missing or expired credentials
403Forbidden — valid credentials but insufficient permissions
404Not found — bucket or object does not exist
409Conflict — duplicate name or key
413Payload too large — file exceeds the upload size limit
429Rate limited — slow down requests
500Internal server error — something went wrong on our end
✓ Every response includes a requestId you can share with support to help diagnose issues.