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

  1. Create a key in Settings → Developer. Tick the API terms box first. The key starts with vdb_ and is shown once.
  2. 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/modelsModels with credit prices (?type=image|image_edit|video)
POST/images/generationsText to image
POST/images/editsEdit or combine 1–10 images
POST/videos/generationsText to video, or image to video with image_url
GET/jobs/{id}Job status and result
GET/creationsYour images and videos (?type=&limit=&before=)
GET/balanceCredits 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 (pass model for 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 with image_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 tool run_tool can run (effects, presenters, ads, utilities, audio, design), with each tool's inputs.
  • run_tool: run a tool from list_tools; pass estimate_only first 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, the file_url to 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}}
400invalid_requestA field is missing or not allowed for that model.
401unauthorizedMissing, invalid or revoked API key.
402insufficient_creditsYour balance is below the price of the request.
403forbiddenThe feature or model is switched off.
404not_foundNo such job (or not yours).
422invalid_requestThe Idempotency-Key was already used for a different request — use a new key.
429rate_limitedOver 120 requests or 20 generations per minute for your account (all keys together).
5xxserver_errorSomething 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…