Developers
VdoBloom API
Generate images and videos from your own code, or let your AI assistant do it through our hosted MCP server. Every call spends the credits in your account at exactly the prices you see in the app — no separate plan, and credits you buy never expire.
Quick start
- Create a key in Settings → Developer. Tick the API terms box first. The key starts with
vdb_and is shown once. - Check what you can spend, then generate:
export VDB_KEY=vdb_your_key
curl https://vdobloom.com/api/v1/balance -H "Authorization: Bearer $VDB_KEY"
curl https://vdobloom.com/api/v1/images/generations \
-H "Authorization: Bearer $VDB_KEY" -H "Content-Type: application/json" \
-d '{"model": "google/nano-banana", "prompt": "a lighthouse at dusk, film photo", "wait": true}'Authentication
Send your key as a bearer token on every request. Keys are stored hashed; if one leaks, revoke it in Settings and create a new one. A key can't create or revoke keys.
Authorization: Bearer vdb_...Endpoints
| GET | /models | Models with credit prices (?type=image|image_edit|video) |
| POST | /images/generations | Text to image |
| POST | /images/edits | Edit or combine 1–10 images |
| POST | /videos/generations | Text to video, or image to video with image_url |
| GET | /jobs/{id} | Job status and result |
| GET | /creations | Your images and videos (?type=&limit=&before=) |
| GET | /balance | Credits left |
Base URL: https://vdobloom.com/api/v1. Bodies are JSON.
Images
wait: true holds the request until the image is ready (up to ~2 minutes); otherwise you get a job back at once. resolution applies to models priced by resolution (1K / 2K / 4K).
curl https://vdobloom.com/api/v1/images/generations \
-H "Authorization: Bearer $VDB_KEY" -H "Content-Type: application/json" \
-d '{"model": "nano-banana-pro", "prompt": "studio photo of a ceramic mug", "aspect_ratio": "4:5", "resolution": "2K"}'
curl https://vdobloom.com/api/v1/images/edits \
-H "Authorization: Bearer $VDB_KEY" -H "Content-Type: application/json" \
-d '{"model": "auto-image-edit", "prompt": "put the mug on a marble counter",
"image_urls": ["https://example.com/mug.png"], "wait": true}'Image URLs must be public https links to PNG, JPEG, WebP, GIF, HEIC or AVIF files up to 10 MB. We fetch them once and keep our own copy.
Videos
Videos take one to ten minutes, so this returns a job immediately. The price depends on model, duration and resolution — it's in the job's credit_cost and in GET /models.
curl https://vdobloom.com/api/v1/videos/generations \
-H "Authorization: Bearer $VDB_KEY" -H "Content-Type: application/json" \
-H "Idempotency-Key: order-1234" \
-d '{"model": "bytedance/seedance-2-fast", "prompt": "slow push-in on a paper boat drifting down a rainy street",
"duration": 5, "resolution": "720p", "aspect_ratio": "9:16"}'
# image to video: add "image_url": "https://example.com/first-frame.png"Jobs & polling
curl https://vdobloom.com/api/v1/jobs/job_8f3c... -H "Authorization: Bearer $VDB_KEY"
{
"id": "job_8f3c...", "object": "job", "kind": "video", "model": "bytedance/seedance-2-fast",
"status": "completed", // processing | completed | failed
"credit_cost": 50,
"result": {"video_id": "...", "video_url": "https://...mp4", "thumbnail_url": null},
"error": null, "created_at": "2026-09-28T10:00:00Z", "completed_at": "2026-09-28T10:02:41Z"
}Poll every 20–60 s, or set a webhook. Send an Idempotency-Key header on generation calls: repeating a request with the same key returns the original job instead of charging again (reusing a key for a different request is refused with 422). A failed generation is refunded automatically.
Result links (image_url, video_url) are temporary. Download the file and store it yourself as soon as the job completes.
Webhooks
Add a webhook URL to a key in Settings → Developer. When a job made with that key finishes we POST:
POST https://your-server.com/vdobloom-webhook
X-VdoBloom-Signature: t=1790500000,v1=5f2b...
X-VdoBloom-Event: job.completed
{"id": "evt_job_8f3c...", "type": "job.completed", "created": 1790500000, "data": { ...the job... }}Verify the signature with the signing secret shown when you saved the URL: HMAC-SHA256 of "<t>.<raw body>", compared in constant time, and reject old timestamps. Answer with any 2xx; anything else is retried after 30 s, 2 min, 10 min, 1 h and 6 h. The event id stays the same across retries, so use it to skip duplicates.
// Node.js (Express: app.post(path, express.raw({type: "application/json"}), handler))
const crypto = require("crypto");
function verify(rawBody, header, secret, toleranceSec = 300) {
const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
if (Math.abs(Date.now() / 1000 - Number(parts.t)) > toleranceSec) return false;
const expected = crypto.createHmac("sha256", secret).update(`${parts.t}.`).update(rawBody).digest("hex");
return parts.v1?.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(parts.v1), Buffer.from(expected));
}# Python
import hashlib, hmac, time
def verify(raw_body: bytes, header: str, secret: str, tolerance: int = 300) -> bool:
parts = dict(p.split("=", 1) for p in header.split(","))
if abs(time.time() - int(parts["t"])) > tolerance:
return False
expected = hmac.new(secret.encode(), f"{parts['t']}.".encode() + raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, parts.get("v1", ""))Webhook URLs must be https on port 443 and resolve to a public address; private, loopback and cloud metadata addresses are refused.
MCP server (Claude, ChatGPT and other AI clients)
Point any MCP client at https://vdobloom.com/mcp (Streamable HTTP). In Claude or ChatGPT, add it as a custom connector and sign in — no key to paste. Command-line clients can send a key:
claude mcp add --transport http vdobloom https://vdobloom.com/mcp \
--header "Authorization: Bearer vdb_your_key"Step-by-step setup for Claude, Claude Code, ChatGPT, Cursor and Codex is on the VdoBloom MCP server page.
The server exposes 13 tools:
list_models: models you can use, with credit prices (passmodelfor its full price table).get_balance: your remaining VdoBloom credits.generate_image: text-to-image; returns a job.edit_image: edit or combine 1-10 images with an instruction; returns a job.generate_video: text-to-video, or image-to-video withimage_url; returns a job.generate_speech: text to speech for narration (up to 10,000 characters per call).generate_music: background music or a song from a style prompt, instrumental by default.get_status: status of a job: processing, completed (with result) or failed (with error).list_creations: your recent images and videos, newest first.list_tools: every other VdoBloom toolrun_toolcan run (effects, presenters, ads, utilities, audio, design), with each tool's inputs.run_tool: run a tool fromlist_tools; passestimate_onlyfirst to get the price without running.create_upload: an upload link for a file on your device (photo, video or audio).get_upload: status of an upload; when ready, thefile_urlto pass to other tools.
Each connected app shows up as a key in Settings → Developer; revoke it there to disconnect.
Using a file from your device
Tools take links, so a photo, video or audio file that only exists on your device needs an upload first. create_upload (kind: image, video or audio, optional filename) returns an upload_id and an upload_url: a VdoBloom page you open in your browser to pick the file. The link works once, for one file, for about 15 minutes. Limits: images 10 MB, videos 100 MB, audio 25 MB. Uploading costs no credits.
get_upload (upload_id) reports waiting, uploading, ready, expired or failed. Once ready it returns a file_url to pass to any tool that takes a link of that kind. The link works for about a day, after which the file is removed.
The file type is checked from the file itself, and photos go through the same checks as uploads in the app. Uploading a photo of a person is not consent: tools that use someone's photo still ask for their own consent confirmation.
Errors & limits
{"error": {"code": "insufficient_credits", "message": "Insufficient credits: this request costs 50 credits.", "status": 402}}| 400 | invalid_request | A field is missing or not allowed for that model. |
| 401 | unauthorized | Missing, invalid or revoked API key. |
| 402 | insufficient_credits | Your balance is below the price of the request. |
| 403 | forbidden | The feature or model is switched off. |
| 404 | not_found | No such job (or not yours). |
| 422 | invalid_request | The Idempotency-Key was already used for a different request — use a new key. |
| 429 | rate_limited | Over 120 requests or 20 generations per minute for your account (all keys together). |
| 5xx | server_error | Something failed on our side — retry with the same Idempotency-Key. |
Prompts go through the same content rules as the app; a blocked prompt fails the job and is not charged.
Models & prices
Prices are credits per request (videos: the cheapest duration/resolution — the full table per model is in GET /models). They are the same prices as in the app.
Loading prices…