Get API Key Get API
Docs

Grok Imagine 2.0 Ext Image Generation

- Async text-to-image; poll with task_id

  • 1–12 images per request; billed per successfully delivered image ($0.08 each)
  • URL output only; no image-to-image / streaming
  • Image URLs expire in 72 hours
Info

Text-to-image · async jobs. Submit POST /v1/images/generations, then poll Get task status.\
Model name is fixed grok-imagine-2.0-ext. Not supported: reference images, stream, or response_format values other than url.

Info

For object layers or selected-region editing, see Layers and region editing.

Warning

Do not put API keys in browser bundles (VITE_* / NEXT_PUBLIC_*, LocalStorage, etc.). Prefer calling your own BFF from the browser; keep the OpenVeer key on the server.

Request example

curl --request POST \
  --url https://api.openveer.com/v1/images/generations \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --header 'Accept: application/json' \
  --header 'Idempotency-Key: 8eacb46d-ef4e-4f4e-82de-830bd8bc67e2' \
  --header 'X-OpenVeer-Response-Version: 2026-07-27' \
  --data '{
    "model": "grok-imagine-2.0-ext",
    "prompt": "A red apple on a white ceramic plate, clean studio product photo",
    "n": 1,
    "size": "1:1",
    "resolution": "quality",
    "response_format": "url"
  }'

Response example

{
  "code": 202,
  "request_id": "2026081111342261665927mpb4IPDb",
  "data": {
    "id": "task_01KZQE5CM0Y3KZ6M1N1BK619MX",
    "object": "generation.task",
    "type": "image",
    "status": "pending",
    "progress": 0,
    "poll_url": "/v1/tasks/task_01KZQE5CM0Y3KZ6M1N1BK619MX"
  }
}

Capabilities and limits

Dimension Contract
Model Fixed grok-imagine-2.0-ext
Capability Text-to-image only
Mode Async task
Count n 1–12, default 1
size 7 aspect ratios + 5 pixel aliases (below)
Output response_format=url only (also the default)
Quality Public field resolution; verified value quality
Not supported Image-to-image, stream=true, public quality, style, b64_json / base64
Billing Fixed unit price; charge successfully delivered images
Authorization string

Bearer token. Get a key from the API Key page.

Authorization: Bearer YOUR_API_KEY
Header Notes
Content-Type application/json (submit)
Accept application/json
Idempotency-Key Strongly recommended. New UUID per user-confirmed generation; network retries must reuse the same key and body
X-OpenVeer-Response-Version Prefer 2026-07-27 for a stable submit shape (data.id)

Request parameters

model string

Fixed value: grok-imagine-2.0-ext

nsfw_check boolean

Whether to run content moderation before submitting the image task.

  • true: use omni-moderation-latest to review prompts and input images
  • false or omitted: do not send a moderation request, adding no moderation cost or latency (default)
prompt string

Prompt. Must be non-empty after trim. Trim before submit.

n integer

Image count: 1–12. Explicit 0 errors. Omit for 1.

size string

Aspect ratio. Prefer ratio strings (UI should only show ratios):

size Orientation Typical use
1:1 Square Product, avatar
2:3 Portrait Poster, full-body
3:2 Landscape Photo, wide scene
3:4 Portrait E-commerce, people
4:3 Landscape Display art
9:16 Vertical Story / short-video cover
16:9 Wide Banner, video cover

Pixel aliases: 1024x1024 (1:1), 1024x1792 (2:3), 1792x1024 (3:2), 720x1280 (9:16), 1280x720 (16:9).

Values outside the whitelist return 400 invalid_size (e.g. 1:2, 2:1, 4:5, auto).

Note



Actual pixels for a given ratio may differ from the alias table (e.g. 1:1 may return 1408×1408). Trust the returned image; do not rewrite size from measured pixels.

resolution string

Quality-mode field. Verified value: quality.

  • Omit (model is quality-mode by default), or
  • Pass resolution: "quality" explicitly

Not a 1K / 2K / 4K pixel tier; framing is controlled by size.

Warning



Do not send a public quality field — you get 400 invalid_quality. Use resolution.

response_format string

Only url is allowed. May be omitted. b64_json / base64 → 400 invalid_response_format.

webhook string

Optional public HTTPS base URL. On terminal status the platform POSTs {webhook}/callback. Server-side only — see Webhook.

Unsupported parameters

Parameter Behavior
quality 400 invalid_quality → use resolution
style 400 invalid_style
image_urls / image_with_roles 400 invalid_image_input
stream: true 400 invalid_stream
response_format: "b64_json" / "base64" 400 invalid_response_format

Build requests with a whitelist; do not forward a generic image-form object from other models.

Request examples

Minimal

{
  "model": "grok-imagine-2.0-ext",
  "prompt": "A red apple on a white ceramic plate, clean studio product photo"
}
{
  "model": "grok-imagine-2.0-ext",
  "prompt": "A red apple on a white ceramic plate, clean studio product photo",
  "n": 1,
  "size": "1:1",
  "resolution": "quality",
  "response_format": "url"
}

Submit response

Prefer X-OpenVeer-Response-Version: 2026-07-27. Success is HTTP 202; task id is data.id (do not rely on legacy data[0].task_id).

Persist:

  • data.id for polling
  • request_id for gateway debugging
  • the Idempotency-Key for safe retries when outcome is unknown
  • original request params for UI / support

Idempotency and safe retries

Image generation is billable — strongly recommend Idempotency-Key (1–191 printable ASCII chars; UUID is easiest; retained \~24 hours).

Scenario Behavior Action
Same key + same body already done Replay; header Idempotency-Replayed: true Use the same task id
Same key still in flight 409 idempotency_in_progress + Retry-After Wait, retry same key and body
Same key, different body 409 idempotency_key_reused New logical job needs a new key
Outcome indeterminate 409 idempotency_result_indeterminate Do not mint a new key; investigate with the old one

On POST network timeout when you cannot tell if the server accepted the job, do not immediately create a new key — retry with the same key / body / response version.

Poll tasks

GET /v1/tasks/{task_id}?language=en
Authorization: Bearer YOUR_API_KEY
Accept: application/json

Optional language: zh / en / ko / ja (failure message localization only). See Get task status.

Statuses

status Terminal Handling
pending / processing No Keep polling (result may be absent — not a failure)
completed Yes Parse result.images
failed Yes Show error.message; cost is 0 (pre-charge refunded)
unknown No Short retries; if it persists, contact support with the task id

Poll about every 2 seconds; cap near 10 minutes or 120 attempts. Honor Retry-After on 429. Tasks are kept \~3 days by default — keep the task id if the client times out.

Completed example

{
  "code": 200,
  "data": {
    "id": "task_01KZQE5CM0Y3KZ6M1N1BK619MX",
    "status": "completed",
    "progress": 100,
    "created": 1786419262,
    "completed": 1786419275,
    "actual_time": 13,
    "estimated_time": 100,
    "cost": 0.08,
    "credits_cost": 0.8,
    "result": {
      "images": [
        {
          "expires_at": 1786505675,
          "url": [
            "https://example.com/image/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.jpg"
          ],
          "image_ids": [
            "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
          ]
        }
      ]
    }
  }
}

Parsing url and image_ids

result.images[]
  ├─ url[]          ← authoritative display/download field (array)
  ├─ image_ids[]    ← optional opaque IDs
  └─ expires_at     ← Unix seconds; multiply by 1000 for JS Date
  1. Use url[] for display; when n>1, walk all entries
  2. Pair by index only if image_ids.length === url.length
  3. Missing image_ids still allows display
  4. Links last 72 hours — download promptly; also trust expires_at

Billing

Base price \$0.08 per image (successful deliveries):

n Estimated base
1 \$0.08
4 \$0.32
8 \$0.64
12 \$0.96
  • Pre-submit UI should say “estimate”; final USD is data.cost
  • data.credits_cost is the credits view (currently \~ USD × 10)
  • Pre-charge by requested count; settle on successful count (partial refunds if partial failure)
  • Full failure: cost=0, pre-charge refunded
  • Do not build price keys from resolution; this model is flat per image

Webhook (optional)

{
  "webhook": "https://your-service.example.com/openveer"
}
  • Provide a base URL; the platform calls {base}/callback
  • Must be public and pass SSRF checks
  • If webhook_secret is set, signature is hex(HMAC-SHA256(secret, raw_body)) over raw bytes
  • Callback body matches task query data (no extra {code,data} wrapper)
  • Still keep low-frequency polling as a fallback

Common errors

HTTP error.code Cause Action
400 invalid_request Empty prompt / bad JSON Validate input
400 invalid_n n outside 1–12 Clamp count
400 invalid_size Size not whitelisted Fixed select options
400 invalid_response_format Not url Fix or omit
400 invalid_quality Public quality sent Use resolution
400 invalid_style style sent Remove
400 invalid_image_input Reference images Switch models
400 invalid_stream stream=true Remove
400 invalid_idempotency_key Bad key Use UUID
401 Auth failure Bad key Fix server credentials
402 Payment required Low balance Top up
409 idempotency_* Idempotency conflict See table above
429 Rate limit Too fast Honor Retry-After
5xx Server error — Keep Idempotency-Key; do not blindly rotate

Prefer error.message for UI. Do not surface raw auth internals to end users.

Differences from 1.5 (summary)

Item Grok Imagine 1.5 2.0 Ext
Model grok-imagine-1.5-openveer, etc. grok-imagine-2.0-ext
Image-to-image Supported (see 1.5 docs) Not supported
Count See 1.5 docs 1–12
Quality field See 1.5 docs resolution (quality); never public quality
Output See 1.5 docs URL only
URL TTL See 1.5 docs (often 24h) 72 hours
Unit price See 1.5 docs \$0.08 / image

This documentation is built and hosted on Mintlify, a developer documentation platform.