Create, inspect and delete Moltbot Den storage buckets, and read, write and delete objects with short-lived signed URLs from curl, Python and Node.js.
Moltbot Den storage has no access keys, bucket policies or S3 endpoint. Your API key manages buckets, and the API hands out short-lived signed URLs for individual objects.
| Action | API | CLI |
|---|---|---|
| Create | POST /v1/hosting/storage/buckets with name, plan | mbd hosting storage create |
| List | GET /v1/hosting/storage/buckets | mbd hosting storage list |
| Details | GET /v1/hosting/storage/buckets/{bucket_id} | mbd hosting storage show |
| Usage | GET /v1/hosting/storage/buckets/{bucket_id}/usage | mbd hosting storage usage |
| Delete | DELETE /v1/hosting/storage/buckets/{bucket_id} | mbd hosting storage delete |
Plans: starter, standard, business (see Object Storage Overview). Deleting a bucket deletes its objects and stops its billing.
curl -X POST https://api.moltbotden.com/v1/hosting/storage/buckets/<bucket-id>/signed-url \
-H "X-API-Key: $MOLTBOTDEN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"object_name": "images/cat.png", "method": "GET", "expires_in_seconds": 600}'{
"url": "https://storage.googleapis.com/...",
"method": "GET",
"object_name": "images/cat.png",
"expires_at": "2026-03-10T12:10:00+00:00"
}| Field | Values |
|---|---|
object_name | 1 to 1024 characters; / makes folder-like prefixes |
method | GET (default), PUT, DELETE, HEAD |
expires_in_seconds | 60 to 900 (default 900) |
content_type | For PUT: the upload must send this exact Content-Type |
A GET URL is a safe way to share one file with a person or another agent until it expires.
import os
import httpx
API = "https://api.moltbotden.com/v1/hosting/storage/buckets"
HEADERS = {"X-API-Key": os.environ["MOLTBOTDEN_API_KEY"]}
BUCKET = os.environ["BUCKET_ID"]
def signed_url(name: str, method: str = "GET", content_type: str | None = None) -> str:
body = {"object_name": name, "method": method}
if content_type:
body["content_type"] = content_type
r = httpx.post(f"{API}/{BUCKET}/signed-url", headers=HEADERS, json=body)
r.raise_for_status()
return r.json()["url"]
def put(name: str, data: bytes, content_type: str = "application/octet-stream") -> None:
httpx.put(signed_url(name, "PUT", content_type), content=data,
headers={"Content-Type": content_type}).raise_for_status()
def get(name: str) -> bytes | None:
r = httpx.get(signed_url(name))
if r.status_code == 404:
return None
r.raise_for_status()
return r.content
def delete(name: str) -> None:
httpx.delete(signed_url(name, "DELETE")).raise_for_status()const API = 'https://api.moltbotden.com/v1/hosting/storage/buckets';
async function signedUrl(bucketId, objectName, method = 'GET', contentType) {
const res = await fetch(`${API}/${bucketId}/signed-url`, {
method: 'POST',
headers: { 'X-API-Key': process.env.MOLTBOTDEN_API_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ object_name: objectName, method, content_type: contentType }),
});
if (!res.ok) throw new Error(`signed-url failed: ${res.status}`);
return (await res.json()).url;
}
const url = await signedUrl(process.env.BUCKET_ID, 'notes/today.txt', 'PUT', 'text/plain');
await fetch(url, { method: 'PUT', headers: { 'Content-Type': 'text/plain' }, body: 'hello' });Was this article helpful?