# BulkImagen API Generate images in bulk with hosted AI models. One HTTP call creates a batch of many images; you poll until it finishes and download the results. Base URL: https://bulkimagen.com/api/v1 Auth: Authorization: Bearer bik_live_... OpenAPI: https://bulkimagen.com/api/v1/openapi.json ## Getting a key API access is on paid plans. Create a key at https://bulkimagen.com/dashboard/api-keys. The key is shown once; only a hash is stored. Server-to-server only — the API sends no CORS headers, so never put a key in browser or mobile app code. Optionally set a per-key daily credit cap when creating it. Recommended when an autonomous agent holds the key: it bounds the worst case if a loop misbehaves. ## The workflow 1. GET /api/v1/models — pick a model, read its credit price and legal sizes. 2. Estimate cost: images x creditCost[resolution]. CONFIRM THIS WITH THE USER before spending. Credits are charged the moment the batch is created. 3. (Optional) POST /api/v1/uploads to add reference images. 4. POST /api/v1/batches — returns { id, total, creditsCharged }. 5. Poll GET /api/v1/batches/{id} every ~5 seconds until batch.done is true. 6. Download each task's resultUrls. They are public URLs; no auth needed. ## Endpoints GET /api/v1/models Model catalog: per-resolution credit cost, aspectRatios, resolutions, resolutionsByRatio (the authoritative legal pairs), maxRefImages, supportsQuality, plus defaults and platform limits. Always read this instead of hardcoding model names or prices. GET /api/v1/me { user, credits.balance, limits{maxImagesPerBatch, maxConcurrentBatches, activeBatches}, key{creditCapPerDay, creditsUsedToday, capResetsAt} }. Check balance before submitting. POST /api/v1/batches Body: { prompts: string[] required, the batch fans out over all of them model: string required, a key from GET /models aspectRatio?: string default "1:1" resolution?: "1K"|"2K"|"4K" default "1K" countPerCombo?: number 1-20, images per prompt refMode?: "none"|"each"|"combined" refImages?: string[] urls from POST /uploads quality?: "auto"|"low"|"medium"|"high" only if supportsQuality background?: "transparent"|"#RRGGBB" BETA; only if supportsBackground note?: string } Returns 201 { id, total, creditsCharged, status }. Fan-out: total images = refMode none/no refs : prompts x countPerCombo refMode each : prompts x refImages x countPerCombo refMode combined : prompts x countPerCombo (all refs on every image) GET /api/v1/batches?limit=20&cursor=... Newest first. Pass back nextCursor verbatim for the next page. GET /api/v1/batches/{id} { batch: { ..., counts{pending,running,succeeded,failed}, done }, tasks: [...] } A batch is finished when batch.done is true. Each task carries resultUrls. Failed tasks are refunded automatically. POST /api/v1/uploads multipart/form-data, repeated field "file". PNG/JPEG/WebP/GIF, max 10MB each, max 20 per request. Free — no credits are charged. Returns { files:[{url,name}] }. ## Models and prices (credits per image) - gpt-image-2 — GPT Image 2. Credits/image: 1K=5 2K=10 4K=20. Ratios: auto 1:3 9:21 1:2 9:16 2:3 3:4 4:5 1:1 5:4 4:3 3:2 16:9 2:1 21:9 3:1, max 4 ref images. - nano-banana-2 — Nano Banana 2. Credits/image: 1K=4 2K=6 4K=10. Ratios: auto 1:8 1:4 9:16 2:3 3:4 4:5 1:1 5:4 4:3 3:2 16:9 21:9 4:1 8:1, max 4 ref images. - nano-banana-2-lite — Nano Banana 2 Lite. Credits/image: 1K=3. Ratios: auto 1:8 1:4 9:16 2:3 3:4 4:5 1:1 5:4 4:3 3:2 16:9 21:9 4:1 8:1, max 4 ref images. - nano-banana-pro — Nano Banana Pro. Credits/image: 1K=5 2K=6 4K=10. Ratios: auto 9:16 2:3 3:4 4:5 1:1 5:4 4:3 3:2 16:9 21:9, max 4 ref images. - seedream-4-5 — Seedream 4.5. Credits/image: 2K=6 4K=6. Ratios: 9:16 3:4 2:3 1:1 3:2 4:3 16:9 21:9, max 4 ref images. - seedream-5-lite — Seedream 5.0 Lite. Credits/image: 2K=5 4K=5. Ratios: 9:16 3:4 2:3 1:1 3:2 4:3 16:9 21:9, max 4 ref images. - seedream-5-pro — Seedream 5.0 Pro. Credits/image: 1K=6 2K=12. Ratios: 9:16 3:4 2:3 1:1 3:2 4:3 16:9 21:9, max 4 ref images. - grok — Grok Imagine 2.0. Credits/image: 1K=4. Ratios: 9:16 2:3 1:1 3:2 16:9, max 1 ref images. - flux-2-pro — Flux 2 Pro. Credits/image: 1K=5 2K=6. Ratios: 9:16 2:3 3:4 1:1 4:3 3:2 16:9, max 8 ref images. - z-image — Z-Image. Credits/image: 1K=1. Ratios: 9:16 3:4 1:1 4:3 16:9, text-only (no reference images). Not every aspect ratio works at every resolution. resolutionsByRatio in GET /api/v1/models is the only authoritative source; sending an illegal pair returns size_not_allowed. ## Plan limits - free: no API access, up to 4 images/batch, 1 concurrent batches. - starter: 2 API keys, up to 10 images/batch, 1 concurrent batches. - studio: 5 API keys, up to 50 images/batch, 10 concurrent batches. - scale: 10 API keys, up to 100 images/batch, 20 concurrent batches. ## Errors Every failure is { "error": { "code", "message", "details"? } }. The code is stable; branch on it, not on the message. - unauthorized (HTTP 401) [not retryable]: No Authorization header. - invalid_api_key (HTTP 401) [not retryable]: Key not recognized. - key_revoked (HTTP 401) [not retryable]: Key was revoked or has expired. - account_disabled (HTTP 403) [not retryable]: Account is disabled. - api_not_available_on_plan (HTTP 403) [not retryable]: Plan does not include API access (free plan, or a downgrade). - invalid_request (HTTP 400) [not retryable]: Malformed body or missing field. - unknown_model (HTTP 400) [not retryable]: Model key is not in GET /models. - size_not_allowed (HTTP 400) [not retryable]: That aspectRatio is not offered at that resolution — check resolutionsByRatio. - too_many_ref_images (HTTP 400) [not retryable]: More reference images than the model accepts. - refs_not_supported (HTTP 400) [not retryable]: That model is text-only and takes no reference images — drop them, or pick a model with maxRefImages set. - content_blocked (HTTP 400) [not retryable]: Prompt hit the content policy. Edit the prompt. - prompt_too_long (HTTP 400) [not retryable]: A prompt is longer than the model accepts. details.promptIndex says which one; shorten it or split it. - insufficient_credits (HTTP 402) [not retryable]: Balance is lower than the batch cost. - daily_credit_cap_exceeded (HTTP 402) [not retryable]: This key's daily cap would be exceeded. Resets 00:00 UTC. - batch_limit_exceeded (HTTP 403) [not retryable]: More images than the plan allows in one batch. - concurrent_limit_exceeded (HTTP 403): Too many batches already running. Wait for one to finish. - rate_limited (HTTP 429): Slow down; honour Retry-After. - not_found (HTTP 404) [not retryable]: No such batch on this account. - internal_error (HTTP 500): Server-side failure. Retry. Codes marked [not retryable] will fail identically on retry until something changes (edit the prompt, buy credits, raise the cap, upgrade the plan). Do not loop on them — report the reason to the user instead. ## Example curl -X POST https://bulkimagen.com/api/v1/batches \ -H "Authorization: Bearer $BULKIMAGEN_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "prompts": ["a red fox in snow", "a red fox in autumn leaves"], "model": "nano-banana-pro", "aspectRatio": "16:9", "resolution": "1K", "countPerCombo": 4 }' # -> {"id":"b_...","total":8,"creditsCharged":40,"status":"pending"} curl https://bulkimagen.com/api/v1/batches/b_... \ -H "Authorization: Bearer $BULKIMAGEN_API_KEY"