curl --request POST \
--url https://api.apimart.ai/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-APIMart-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"
}'
import requests
import uuid
url = "https://api.apimart.ai/v1/images/generations"
payload = {
"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",
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json",
"Accept": "application/json",
"Idempotency-Key": str(uuid.uuid4()),
"X-APIMart-Response-Version": "2026-07-27",
}
response = requests.post(url, json=payload, headers=headers)
print(response.status_code, response.json())
const url = "https://api.apimart.ai/v1/images/generations";
const payload = {
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",
};
const headers = {
Authorization: "Bearer <token>",
"Content-Type": "application/json",
Accept: "application/json",
"Idempotency-Key": crypto.randomUUID(),
"X-APIMart-Response-Version": "2026-07-27",
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload),
})
.then(async (response) => {
console.log(response.status, await response.json());
})
.catch((error) => console.error("Error:", error));
{
"code": 202,
"request_id": "2026081111342261665927mpb4IPDb",
"data": {
"id": "task_01KZQE5CM0Y3KZ6M1N1BK619MX",
"object": "generation.task",
"type": "image",
"status": "pending",
"progress": 0,
"poll_url": "/v1/tasks/task_01KZQE5CM0Y3KZ6M1N1BK619MX"
}
}
{
"request_id": "20260811...",
"error": {
"message": "`response_format` for grok-imagine-2.0-ext only supports `url` (got: b64_json)",
"type": "invalid_response_format",
"param": "",
"code": "invalid_response_format"
}
}
{
"error": {
"code": 401,
"message": "Authentication failed. Please check your API key",
"type": "authentication_error"
}
}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up and try again",
"type": "payment_required"
}
}
{
"error": {
"code": 429,
"message": "Too many requests. Please try again later",
"type": "rate_limit_error"
}
}
Grok Imagine 2.0 Ext
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
POST
/
v1
/
images
/
generations
curl --request POST \
--url https://api.apimart.ai/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-APIMart-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"
}'
import requests
import uuid
url = "https://api.apimart.ai/v1/images/generations"
payload = {
"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",
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json",
"Accept": "application/json",
"Idempotency-Key": str(uuid.uuid4()),
"X-APIMart-Response-Version": "2026-07-27",
}
response = requests.post(url, json=payload, headers=headers)
print(response.status_code, response.json())
const url = "https://api.apimart.ai/v1/images/generations";
const payload = {
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",
};
const headers = {
Authorization: "Bearer <token>",
"Content-Type": "application/json",
Accept: "application/json",
"Idempotency-Key": crypto.randomUUID(),
"X-APIMart-Response-Version": "2026-07-27",
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload),
})
.then(async (response) => {
console.log(response.status, await response.json());
})
.catch((error) => console.error("Error:", error));
{
"code": 202,
"request_id": "2026081111342261665927mpb4IPDb",
"data": {
"id": "task_01KZQE5CM0Y3KZ6M1N1BK619MX",
"object": "generation.task",
"type": "image",
"status": "pending",
"progress": 0,
"poll_url": "/v1/tasks/task_01KZQE5CM0Y3KZ6M1N1BK619MX"
}
}
{
"request_id": "20260811...",
"error": {
"message": "`response_format` for grok-imagine-2.0-ext only supports `url` (got: b64_json)",
"type": "invalid_response_format",
"param": "",
"code": "invalid_response_format"
}
}
{
"error": {
"code": 401,
"message": "Authentication failed. Please check your API key",
"type": "authentication_error"
}
}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up and try again",
"type": "payment_required"
}
}
{
"error": {
"code": 429,
"message": "Too many requests. Please try again later",
"type": "rate_limit_error"
}
}
Text-to-image · async jobs. Submit
Model name is fixed
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.For object layers or selected-region editing, see Layers and region editing.
Do not put API keys in browser bundles (
VITE_* / NEXT_PUBLIC_*, LocalStorage, etc.). Prefer calling your own BFF from the browser; keep the APIMart key on the server.curl --request POST \
--url https://api.apimart.ai/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-APIMart-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"
}'
import requests
import uuid
url = "https://api.apimart.ai/v1/images/generations"
payload = {
"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",
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json",
"Accept": "application/json",
"Idempotency-Key": str(uuid.uuid4()),
"X-APIMart-Response-Version": "2026-07-27",
}
response = requests.post(url, json=payload, headers=headers)
print(response.status_code, response.json())
const url = "https://api.apimart.ai/v1/images/generations";
const payload = {
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",
};
const headers = {
Authorization: "Bearer <token>",
"Content-Type": "application/json",
Accept: "application/json",
"Idempotency-Key": crypto.randomUUID(),
"X-APIMart-Response-Version": "2026-07-27",
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload),
})
.then(async (response) => {
console.log(response.status, await response.json());
})
.catch((error) => console.error("Error:", error));
{
"code": 202,
"request_id": "2026081111342261665927mpb4IPDb",
"data": {
"id": "task_01KZQE5CM0Y3KZ6M1N1BK619MX",
"object": "generation.task",
"type": "image",
"status": "pending",
"progress": 0,
"poll_url": "/v1/tasks/task_01KZQE5CM0Y3KZ6M1N1BK619MX"
}
}
{
"request_id": "20260811...",
"error": {
"message": "`response_format` for grok-imagine-2.0-ext only supports `url` (got: b64_json)",
"type": "invalid_response_format",
"param": "",
"code": "invalid_response_format"
}
}
{
"error": {
"code": 401,
"message": "Authentication failed. Please check your API key",
"type": "authentication_error"
}
}
{
"error": {
"code": 402,
"message": "Insufficient balance. Please top up and try again",
"type": "payment_required"
}
}
{
"error": {
"code": 429,
"message": "Too many requests. Please try again later",
"type": "rate_limit_error"
}
}
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 |
Auth and recommended headers
string
required
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-APIMart-Response-Version | Prefer 2026-07-27 for a stable submit shape (data.id) |
Request parameters
string
required
Fixed value:
grok-imagine-2.0-extboolean
default:"false"
Whether to run content moderation before submitting the image task.
true: useomni-moderation-latestto review prompts and input imagesfalseor omitted: do not send a moderation request, adding no moderation cost or latency (default)
string
required
Prompt. Must be non-empty after trim. Trim before submit.
integer
default:"1"
Image count:
1–12. Explicit 0 errors. Omit for 1.string
Aspect ratio. Prefer ratio strings (UI should only show ratios):
Pixel aliases:
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 |
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).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.string
Quality-mode field. Verified value:
quality.- Omit (model is quality-mode by default), or
- Pass
resolution: "quality"explicitly
1K / 2K / 4K pixel tier; framing is controlled by size.Do not send a public
quality field — you get 400 invalid_quality. Use resolution.string
default:"url"
Only
url is allowed. May be omitted. b64_json / base64 → 400 invalid_response_format.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 |
Request examples
Minimal
{
"model": "grok-imagine-2.0-ext",
"prompt": "A red apple on a white ceramic plate, clean studio product photo"
}
Recommended
{
"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
PreferX-APIMart-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.idfor pollingrequest_idfor gateway debugging- the
Idempotency-Keyfor safe retries when outcome is unknown - original request params for UI / support
Idempotency and safe retries
Image generation is billable — strongly recommendIdempotency-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 |
Poll tasks
GET /v1/tasks/{task_id}?language=en
Authorization: Bearer YOUR_API_KEY
Accept: application/json
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 |
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
- Use
url[]for display; whenn>1, walk all entries - Pair by index only if
image_ids.length === url.length - Missing
image_idsstill allows display - 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_costis 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/apimart"
}
- Provide a base URL; the platform calls
{base}/callback - Must be public and pass SSRF checks
- If
webhook_secretis set, signature ishex(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 |
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-apimart, 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 |