BlockRun

Image Generation API

Generate images using GPT Image (including ChatGPT Images 2.0), Google Nano Banana, CogView-4, or xAI Grok Imagine.

Endpoint

POST https://blockrun.ai/api/v1/images/generations

Request

{
  "model": "google/nano-banana",
  "prompt": "A futuristic city at sunset",
  "size": "1024x1024",
  "n": 1
}

Parameters

ParameterTypeRequiredDescription
modelstringYesModel to use (see below)
promptstringYesImage description
sizestringNoImage dimensions (default: "1024x1024")
qualitystringNo"standard" or "hd" (model-dependent)
nintegerNoNumber of images (default: 1)

Available Models

Model IDProviderSizesPrice
openai/gpt-image-1OpenAI1024x1024, 1536x1024, 1024x1536$0.021
openai/gpt-image-2OpenAI1024x1024, 1536x1024, 1024x1536$0.063
google/nano-bananaGoogle1024x1024$0.053
google/nano-banana-proGoogle1024x1024, 2048x2048, 4096x4096$0.105
zai/cogview-4Zhipu AI512x512 – 1440x1440$0.015
xai/grok-imagine-imagexAI1024x1024$0.021
xai/grok-imagine-image-proxAI1024x1024$0.074

CogView-4 Sizes

zai/cogview-4 supports flexible sizes (multiples of 16, max 1440×1440):

SizeUse Case
512x512Thumbnails, icons
768x768Social media
1024x1024Standard (default)
768x1344Portrait / mobile
1344x768Landscape / banner
1440x1440High resolution

How it works — hybrid sync/async flow & settlement

This endpoint is hybrid: fast generations complete synchronously, slow ones switch to an async job you poll. The split is purely by elapsed time:

  1. POST /v1/images/generations with an x-payment (or PAYMENT-SIGNATURE) header. The gateway verifies the payment authorization (no USDC moves yet) and starts generation.
  2. Fast path (≤30s inline window — most models): generation finishes inline. The gateway settles the payment and returns 200 with the standard { created, data: [...] } body below. This is the only moment a fast-path call is charged.
  3. Slow path (>30s — e.g. openai/gpt-image-2 under load): the gateway returns 202 with an async job envelope { id, status: "queued", poll_url, price, payment_status: "verified" }. No USDC has moved.
  4. GET {poll_url} — poll every 2–5s with an x-payment header signed by the same wallet (a fresh signature works; the gateway enforces wallet binding, not signature byte-equality; with no header it returns a normal x402 402 challenge so clients can re-sign automatically). While the job runs you get 202 (status: queued | in_progress). When it finishes you get 200 with the image URLs, and that is the moment you are charged — settlement happens exactly once, on the first poll that observes status: "completed".
GuaranteeMeaning
payment_status: "verified"Signature/authorization checked only — not a charge.
Upstream fails (status: "failed")payment_status: "not_charged" — no USDC is ever transferred.
You never pollNothing settles; the signed authorization simply expires. You are not charged.
Idempotent re-pollsPolling an already-settled job returns the same URLs again (payment.status: "already_settled") — never double-charged.
Settlement timingFast path: inside the 200 POST. Slow path: on the first completed poll. Identical to /v1/videos/generations and /v1/images/image2image.

Async job envelope (202)

{
  "id": "img_8f3a…",
  "object": "image.generation.job",
  "status": "queued",
  "model": "openai/gpt-image-2",
  "size": "1024x1024",
  "n": 1,
  "price": { "amount": "0.063000", "currency": "USD" },
  "payment_status": "verified",
  "created": 1706000000,
  "poll_url": "/api/v1/images/generations/img_8f3a…",
  "poll_instructions": "…"
}

status enum: queuedin_progresscompleted | failed.

Poll responses

  • 202 running: { id, object, status: "queued" | "in_progress", model, payment_status: "verified" }
  • 200 completed (charged here): the standard body below plus price: { amount, currency } and payment: { status: "settled", tx_hash, network }, with PAYMENT-RESPONSE and X-Payment-Receipt (on-chain tx hash) headers.
  • 200 failed (not charged): { id, object, status: "failed", model, error, payment_status: "not_charged" }
OpenAI-compatible clients and the async envelope

Plain OpenAI SDKs don't understand the 202 envelope. Use a model that completes inline, or the official BlockRun SDKs — Go blockrun-llm-go ≥ v0.17.0 handles the hybrid flow transparently and always returns the synchronous {data:[...]} shape.

Response

{
  "created": 1706000000,
  "data": [
    {
      "url": "https://blockrun.ai/api/media/media/images/2026/04/17/<id>.jpg",
      "source_url": "https://<upstream-host>/...",
      "backed_up": true,
      "revised_prompt": "..."
    }
  ],
  "price": { "amount": "0.015000", "currency": "USD" },
  "payment": { "status": "settled", "tx_hash": "0x…", "network": "base" }
}

Response Fields

FieldTypeDescription
createdintegerUnix timestamp
dataarrayArray of generated images
data[].urlstringPermanent URL. When GCS backup succeeds, this is a blockrun-hosted proxy URL; otherwise the upstream URL. For openai/gpt-image-1 and openai/gpt-image-2 this is a base64 data URI
data[].source_urlstringOriginal upstream URL (omitted for data URIs)
data[].backed_upbooleantrue when the image was mirrored to BlockRun's GCS bucket (omitted for data URIs)
data[].revised_promptstringExpanded prompt (when the model rewrites it)
Why both url and source_url?

Upstream image URLs are usually temporary (they can expire within an hour). BlockRun mirrors each generated image to durable cloud storage and returns the permanent proxy URL as url; source_url is the original (possibly short-lived) upstream URL.

Examples

Via ClawRouter (recommended for local use)

ClawRouter handles x402 payments automatically. Start it with openclaw gateway start, then call localhost:8402 directly.

curl -X POST http://localhost:8402/v1/images/generations \
  -H "Content-Type: application/json" \
  -d '{"model":"zai/cogview-4","prompt":"a futuristic city at night","size":"1024x1024"}'

Open the returned URL directly:

URL=$(curl -s -X POST http://localhost:8402/v1/images/generations \
  -H "Content-Type: application/json" \
  -d '{"model":"google/nano-banana","prompt":"your prompt here","size":"1024x1024"}' \
  | python3 -c "import sys,json; print(json.load(sys.stdin)['data'][0]['url'])")

open "$URL"   # macOS
xdg-open "$URL"   # Linux

Direct API

Pricing

ModelSizePrice
CogView-4up to 1440x1440$0.015
CogView-41440x1440$0.02
GPT Image 11024x1024$0.021
ChatGPT Images 2.01024x1024$0.063
ChatGPT Images 2.01536x1024 / 1024x1536$0.126
Grok Imagine1024x1024$0.021
Grok Imagine Pro1024x1024$0.074
Nano Banana1024x1024$0.053
Nano Banana Pro1024x1024$0.105
Nano Banana Pro 4K4096x4096$0.158

Error Codes

CodeDescription
400Invalid request (bad prompt or parameters)
402Payment required (insufficient balance)
403Content policy violation
429Rate limit exceeded
500Server error

Model Selection Guide

Use CaseRecommended
Cheapestzai/cogview-4
Chinese promptszai/cogview-4
Highest qualitygoogle/nano-banana-pro
Fast & reliablegoogle/nano-banana
Best prompt followingopenai/gpt-image-2
Image editing (img2img)openai/gpt-image-1, openai/gpt-image-2, google/nano-banana, or google/nano-banana-pro
Multi-image fusion (ref + logo → 1 image)google/nano-banana(-pro) (≤3) or openai/gpt-image-1/2 (≤4) — see Image Editing
Multilingual text in images / character consistencyopenai/gpt-image-2
xAI-style stylizationxai/grok-imagine-image-pro

OpenAI Compatibility

This endpoint is compatible with OpenAI's Images API:

from openai import OpenAI

client = OpenAI(
    base_url="https://blockrun.ai/api/v1",
    api_key="unused"  # x402 payment handled via header
)

response = client.images.generate(
    model="zai/cogview-4",
    prompt="A futuristic city",
    size="1024x1024"
)
print(response.data[0].url)

What's next?