{"openapi":"3.1.0","info":{"title":"BulkImagen API","version":"1.0.0","description":"Generate images in bulk with hosted AI models. Credits are charged when a batch is created; generation runs asynchronously — poll GET /batches/{id} until `batch.done` is true.\n\nServer-to-server only: the API sends no CORS headers, so keys must never be used from a browser or mobile app.","contact":{"email":"support@bulkimagen.com","url":"https://bulkimagen.com/docs/api"}},"servers":[{"url":"https://bulkimagen.com/api/v1"}],"security":[{"apiKey":[]}],"paths":{"/models":{"get":{"operationId":"listModels","summary":"List available models, prices and legal size combinations","description":"Call this first. It returns each model's credit cost per resolution and the exact aspect-ratio × resolution pairs that are accepted, so a batch never has to be discovered by trial and error.","responses":{"200":{"description":"Model catalog.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModelCatalog"}}}},"400":{"description":"Invalid request, unknown model, illegal size, or blocked prompt.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Not enough credits, or this key's daily credit cap would be exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account disabled, plan does not include API access, or a plan limit was hit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited. Back off and retry after the Retry-After interval.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error. Safe to retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/me":{"get":{"operationId":"getMe","summary":"Account, credit balance, plan limits and this key's daily usage","responses":{"200":{"description":"Account snapshot.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Me"}}}},"400":{"description":"Invalid request, unknown model, illegal size, or blocked prompt.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Not enough credits, or this key's daily credit cap would be exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account disabled, plan does not include API access, or a plan limit was hit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited. Back off and retry after the Retry-After interval.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error. Safe to retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/batches":{"post":{"operationId":"createBatch","summary":"Create a batch (charges credits)","description":"Charges `total × creditCost[resolution]` credits up front and returns immediately. Generation is asynchronous — poll GET /batches/{id}.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBatchRequest"}}}},"responses":{"201":{"description":"Batch accepted and credits charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBatchResponse"}}}},"400":{"description":"Invalid request, unknown model, illegal size, or blocked prompt.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Not enough credits, or this key's daily credit cap would be exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account disabled, plan does not include API access, or a plan limit was hit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited. Back off and retry after the Retry-After interval.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error. Safe to retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"operationId":"listBatches","summary":"List batches, newest first","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"Opaque cursor from a previous response's `nextCursor`."}],"responses":{"200":{"description":"A page of batches.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchList"}}}},"400":{"description":"Invalid request, unknown model, illegal size, or blocked prompt.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Not enough credits, or this key's daily credit cap would be exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account disabled, plan does not include API access, or a plan limit was hit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited. Back off and retry after the Retry-After interval.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error. Safe to retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/batches/{id}":{"get":{"operationId":"getBatch","summary":"Get a batch with all of its tasks and result image URLs","description":"The polling endpoint. `batch.done` is true once nothing is pending or running. Result images are public URLs you can download directly.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Batch detail.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchDetail"}}}},"400":{"description":"Invalid request, unknown model, illegal size, or blocked prompt.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Not enough credits, or this key's daily credit cap would be exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account disabled, plan does not include API access, or a plan limit was hit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such batch on this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited. Back off and retry after the Retry-After interval.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error. Safe to retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/uploads":{"post":{"operationId":"uploadReferenceImages","summary":"Upload reference images (free, no credits charged)","description":"Returns URLs to pass as `refImages` when creating a batch. PNG / JPEG / WebP / GIF, max 10 MB each, max 20 files per request.","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"array","items":{"type":"string","format":"binary"}}}}}}},"responses":{"200":{"description":"Stored files.","content":{"application/json":{"schema":{"type":"object","properties":{"files":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string"},"name":{"type":"string"}}}}}}}}},"400":{"description":"Invalid request, unknown model, illegal size, or blocked prompt.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Not enough credits, or this key's daily credit cap would be exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account disabled, plan does not include API access, or a plan limit was hit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited. Back off and retry after the Retry-After interval.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error. Safe to retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"Your API key: `Authorization: Bearer bik_live_…`"}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthorized","invalid_api_key","key_revoked","account_disabled","api_not_available_on_plan","invalid_request","unknown_model","size_not_allowed","too_many_ref_images","refs_not_supported","content_blocked","prompt_too_long","insufficient_credits","daily_credit_cap_exceeded","batch_limit_exceeded","concurrent_limit_exceeded","rate_limited","not_found","internal_error"],"description":"Stable machine-readable code. These are not retryable — retrying returns the same failure until something changes on the account or in the request: unauthorized, invalid_api_key, key_revoked, account_disabled, api_not_available_on_plan, invalid_request, unknown_model, size_not_allowed, too_many_ref_images, refs_not_supported, content_blocked, prompt_too_long, insufficient_credits, daily_credit_cap_exceeded, batch_limit_exceeded, not_found."},"message":{"type":"string"},"details":{"type":"object","additionalProperties":true}}}}},"CreateBatchRequest":{"type":"object","required":["prompts","model"],"properties":{"prompts":{"type":"array","items":{"type":"string"},"minItems":1,"description":"One batch fans out across every prompt."},"model":{"type":"string","enum":["gpt-image-2","nano-banana-2","nano-banana-2-lite","nano-banana-pro","seedream-4-5","seedream-5-lite","seedream-5-pro","grok","flux-2-pro","z-image"],"description":"See GET /models for prices and supported sizes."},"aspectRatio":{"type":"string","default":"1:1"},"resolution":{"type":"string","enum":["1K","2K","4K"],"default":"1K"},"countPerCombo":{"type":"integer","minimum":1,"maximum":20,"default":1,"description":"Images per prompt (per reference image in `each` mode)."},"refMode":{"type":"string","enum":["none","each","combined"],"default":"none","description":"`each`: one task per (prompt, reference image). `combined`: all reference images attached to every task."},"refImages":{"type":"array","items":{"type":"string"},"description":"URLs from POST /uploads."},"quality":{"type":"string","enum":["auto","low","medium","high"],"default":"auto","description":"Honoured only by models where `supportsQuality` is true."},"background":{"type":"string","description":"BETA, may not apply to every image. \"transparent\", a #RRGGBB colour, or omitted for auto. Only honoured by models where `supportsBackground` is true."},"note":{"type":"string","description":"Free-text label shown in the dashboard."}}},"CreateBatchResponse":{"type":"object","properties":{"id":{"type":"string"},"total":{"type":"integer","description":"Number of images this batch will produce."},"creditsCharged":{"type":"integer"},"status":{"type":"string"}}},"Counts":{"type":"object","properties":{"pending":{"type":"integer"},"running":{"type":"integer"},"succeeded":{"type":"integer"},"failed":{"type":"integer"}}},"Batch":{"type":"object","properties":{"id":{"type":"string"},"createdAt":{"type":"integer","description":"Unix milliseconds."},"prompts":{"type":"array","items":{"type":"string"}},"model":{"type":"string"},"aspectRatio":{"type":"string"},"resolution":{"type":"string"},"background":{"type":"string","nullable":true,"description":"null when left on auto; otherwise \"transparent\" or a #RRGGBB colour."},"countPerCombo":{"type":"integer"},"refMode":{"type":"string"},"refImages":{"type":"array","items":{"type":"string"}},"total":{"type":"integer"},"note":{"type":"string","nullable":true},"counts":{"$ref":"#/components/schemas/Counts"},"previewUrl":{"type":"string","nullable":true},"createdViaApi":{"type":"boolean"}}},"BatchList":{"type":"object","properties":{"batches":{"type":"array","items":{"$ref":"#/components/schemas/Batch"}},"nextCursor":{"type":"string","nullable":true}}},"Task":{"type":"object","properties":{"id":{"type":"string"},"batchId":{"type":"string"},"prompt":{"type":"string"},"status":{"type":"string","enum":["pending","queued","running","succeeded","failed"]},"progress":{"type":"integer"},"resultUrls":{"type":"array","items":{"type":"string"},"description":"Public image URLs, downloadable without authentication."},"error":{"type":"string","nullable":true}}},"BatchDetail":{"type":"object","properties":{"batch":{"allOf":[{"$ref":"#/components/schemas/Batch"},{"type":"object","properties":{"done":{"type":"boolean","description":"True once no task is pending or running."},"creditsCharged":{"type":"integer"}}}]},"tasks":{"type":"array","items":{"$ref":"#/components/schemas/Task"}}}},"ModelCatalog":{"type":"object","properties":{"models":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"displayName":{"type":"string"},"blurb":{"type":"string"},"creditCost":{"type":"object","description":"Credits per image, keyed by resolution.","additionalProperties":{"type":"integer"}},"aspectRatios":{"type":"array","items":{"type":"string"}},"resolutions":{"type":"array","items":{"type":"string"}},"resolutionsByRatio":{"type":"object","description":"The only authoritative source of legal ratio × resolution pairs.","additionalProperties":{"type":"array","items":{"type":"string"}}},"supportsRefImages":{"type":"boolean","description":"False for text-only models, which reject any reference image with refs_not_supported. A null maxRefImages means no declared cap, not that refs are refused — check this flag."},"maxRefImages":{"type":"integer","nullable":true},"supportsQuality":{"type":"boolean"}}}},"defaults":{"type":"object","additionalProperties":true},"limits":{"type":"object","additionalProperties":true}}},"Me":{"type":"object","properties":{"user":{"type":"object","additionalProperties":true},"credits":{"type":"object","properties":{"balance":{"type":"integer"}}},"limits":{"type":"object","properties":{"maxImagesPerBatch":{"type":"integer"},"maxConcurrentBatches":{"type":"integer"},"activeBatches":{"type":"integer"}}},"key":{"type":"object","properties":{"id":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"}},"creditCapPerDay":{"type":"integer","nullable":true},"creditsUsedToday":{"type":"integer"},"capResetsAt":{"type":"integer","description":"Unix ms of the next 00:00 UTC."}}}}}}}}