{"version":1,"resources":["https://stablestudio.dev/api/jobs/{jobId}","DELETE https://stablestudio.dev/api/jobs/{jobId}","https://stablestudio.dev/api/generate/sora-2/generate","https://stablestudio.dev/api/generate/sora-2-pro/generate","https://stablestudio.dev/api/generate/veo-3.1/generate","https://stablestudio.dev/api/generate/veo-3.1-fast/generate","https://stablestudio.dev/api/generate/wan-2.6/t2v","https://stablestudio.dev/api/generate/wan-2.6/i2v","https://stablestudio.dev/api/generate/gpt-image-2/generate","https://stablestudio.dev/api/generate/gpt-image-2/edit","https://stablestudio.dev/api/generate/gpt-image-1.5/generate","https://stablestudio.dev/api/generate/gpt-image-1.5/edit","https://stablestudio.dev/api/generate/nano-banana/generate","https://stablestudio.dev/api/generate/nano-banana/edit","https://stablestudio.dev/api/generate/nano-banana-pro/generate","https://stablestudio.dev/api/generate/nano-banana-pro/edit","https://stablestudio.dev/api/generate/flux-2-pro/generate","https://stablestudio.dev/api/generate/flux-2-pro/edit","https://stablestudio.dev/api/generate/flux-2-max/generate","https://stablestudio.dev/api/generate/flux-2-max/edit","https://stablestudio.dev/api/generate/grok/generate","https://stablestudio.dev/api/generate/grok/edit","https://stablestudio.dev/api/generate/grok-video/generate","https://stablestudio.dev/api/generate/seedance/t2v","https://stablestudio.dev/api/generate/seedance/i2v","https://stablestudio.dev/api/generate/seedance-fast/t2v","https://stablestudio.dev/api/generate/seedance-fast/i2v","https://stablestudio.dev/api/jobs","https://stablestudio.dev/api/upload","https://stablestudio.dev/api/upload/confirm"],"mppResources":["https://stablestudio.dev/api/generate/sora-2/generate","https://stablestudio.dev/api/generate/sora-2-pro/generate","https://stablestudio.dev/api/generate/veo-3.1/generate","https://stablestudio.dev/api/generate/veo-3.1-fast/generate","https://stablestudio.dev/api/generate/wan-2.6/t2v","https://stablestudio.dev/api/generate/wan-2.6/i2v","https://stablestudio.dev/api/generate/gpt-image-2/generate","https://stablestudio.dev/api/generate/gpt-image-2/edit","https://stablestudio.dev/api/generate/gpt-image-1.5/generate","https://stablestudio.dev/api/generate/gpt-image-1.5/edit","https://stablestudio.dev/api/generate/nano-banana/generate","https://stablestudio.dev/api/generate/nano-banana/edit","https://stablestudio.dev/api/generate/nano-banana-pro/generate","https://stablestudio.dev/api/generate/nano-banana-pro/edit","https://stablestudio.dev/api/generate/flux-2-pro/generate","https://stablestudio.dev/api/generate/flux-2-pro/edit","https://stablestudio.dev/api/generate/flux-2-max/generate","https://stablestudio.dev/api/generate/flux-2-max/edit","https://stablestudio.dev/api/generate/grok/generate","https://stablestudio.dev/api/generate/grok/edit","https://stablestudio.dev/api/generate/grok-video/generate","https://stablestudio.dev/api/generate/seedance/t2v","https://stablestudio.dev/api/generate/seedance/i2v","https://stablestudio.dev/api/generate/seedance-fast/t2v","https://stablestudio.dev/api/generate/seedance-fast/i2v","https://stablestudio.dev/api/upload"],"description":"Pay-per-generation AI image and video creation. No subscriptions ever.","ownershipProofs":["0xe0cee2e160542a97298bb30716ba38f917003404eb7f2c84a72344bccf8abb0f439e43c858bed768a3c0b2ca0246c9c745a6a18c98b83c6919289170c4c607f11b"],"instructions":"# StableStudio API\n\n> AI image/video generation via micropayments. USDC on Base, Solana, or Tempo. No API keys.\n\nBase URL: `https://stablestudio.dev`\n\n## Recommended Defaults\n\n- **Image generation:** `gpt-image-2` — Best default quality. Use it for most image tasks unless the user prioritizes speed or explicitly requests another model.\n- **Fast image generation:** `nano-banana-pro` — Use when speed matters or the user wants a faster draft; supports up to 4K resolution.\n- **Video generation:** `veo-3.1` — Best quality/cost ratio, supports up to 1080p resolution\n\n## Payment Flow\n\n1. `POST /api/generate/{model}/{operation}` without payment header\n   - Returns `402` with `PAYMENT-REQUIRED` header (base64 JSON)\n\n2. Decode requirements, sign USDC authorization, POST with `PAYMENT-SIGNATURE` header\n   - Returns `200` with `{jobId, status:\"pending\"}` and `PAYMENT-RESPONSE` header\n\n3. Poll `GET /api/jobs/{jobId}` with `SIGN-IN-WITH-X` header until complete\n\n## 402 Response Format\n\nResponse body is empty `{}`. Requirements in header:\n\n```\nPAYMENT-REQUIRED: <base64>\n```\n\nDecoded:\n\n```json\n{\n  \"x402Version\": 2,\n  \"accepts\": [\n    {\n      \"scheme\": \"exact\",\n      \"network\": \"eip155:8453\",\n      \"amount\": \"134000\",\n      \"asset\": \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\",\n      \"payTo\": \"0xfbd7b7Ed48146aD9bEfF956212c77cE056815ad0\"\n    }\n  ],\n  \"resource\": {\n    \"url\": \"https://stablestudio.dev/api/generate/nano-banana-pro/generate\",\n    \"description\": \"Nano Banana Pro - generate\"\n  }\n}\n```\n\n`amount` is USDC micro-units (6 decimals). 134000 = $0.134.\n\n## Routes\n\n| Endpoint                                 | Cost          | Time             |\n| ---------------------------------------- | ------------- | ---------------- |\n| `/api/generate/nano-banana/generate`     | $0.045–$0.151 | ~5s              |\n| `/api/generate/nano-banana/edit`         | $0.045–$0.151 | ~5s              |\n| `/api/generate/nano-banana-pro/generate` | $0.13–$0.24   | ~10s             |\n| `/api/generate/nano-banana-pro/edit`     | $0.13–$0.24   | ~10s             |\n| `/api/generate/gpt-image-2/generate`     | $0.005–$0.21  | can take minutes |\n| `/api/generate/gpt-image-2/edit`         | $0.005–$0.21  | can take minutes |\n| `/api/generate/gpt-image-1.5/generate`   | $0.009–$0.20  | ~3s              |\n| `/api/generate/gpt-image-1.5/edit`       | $0.009–$0.20  | ~3s              |\n| `/api/generate/flux-2-pro/generate`      | $0.02–$0.04   | ~5s              |\n| `/api/generate/flux-2-pro/edit`          | $0.03–$0.06   | ~5s              |\n| `/api/generate/flux-2-max/generate`      | $0.04–$0.17   | ~8s              |\n| `/api/generate/flux-2-max/edit`          | $0.04–$0.17   | ~8s              |\n| `/api/generate/grok/generate`            | $0.07         | ~3s              |\n| `/api/generate/grok/edit`                | $0.022        | ~3s              |\n| `/api/generate/grok-video/generate`      | $0.15–$0.75   | ~17s             |\n| `/api/generate/seedance/t2v`             | $0.09–$0.54/s | 1-3min           |\n| `/api/generate/seedance/i2v`             | $0.09–$0.54/s | 1-3min           |\n| `/api/generate/seedance-fast/t2v`        | $0.08–$0.17/s | 1-3min           |\n| `/api/generate/seedance-fast/i2v`        | $0.08–$0.17/s | 1-3min           |\n| `/api/generate/wan-2.6/t2v`              | $0.50–$2.25   | 2-5min           |\n| `/api/generate/wan-2.6/i2v`              | $0.50–$2.25   | 2-5min           |\n| `/api/generate/sora-2/generate`          | $0.40–$1.20   | 1-3min           |\n| `/api/generate/sora-2-pro/generate`      | $1.20–$6.00   | 2-5min           |\n| `/api/generate/veo-3.1/generate`         | $1.60–$3.20   | 1-2min           |\n| `/api/generate/veo-3.1-fast/generate`    | $1.00–$2.00   | ~30s             |\n| `/api/upload`                            | $0.01         | instant          |\n\nCanonical OpenAPI spec: `GET /openapi.json`.\n\n## Input Schemas\n\nAll edit/i2v endpoints that take media require the [File Upload](#file-upload) flow first — use the returned `blobUrl` in the appropriate `images`, `image`, or `urls` field.\n\n**nano-banana generate** (Gemini 3.1 Flash):\n\n```json\n{\n  \"prompt\": \"string\",\n  \"aspectRatio\": \"1:1|1:4|1:8|2:3|3:2|3:4|4:1|4:3|4:5|5:4|8:1|9:16|16:9|21:9\",\n  \"imageSize\": \"512|1K|2K|4K\",\n  \"thinkingLevel\": \"minimal|high\"\n}\n```\n\n**nano-banana edit** (1–14 reference images):\n\n```json\n{\n  \"prompt\": \"string\",\n  \"aspectRatio\": \"...same as generate\",\n  \"imageSize\": \"512|1K|2K|4K\",\n  \"thinkingLevel\": \"minimal|high\",\n  \"images\": [\"https://blob-url...\"]\n}\n```\n\n**nano-banana-pro generate:**\n\n```json\n{\n  \"prompt\": \"string\",\n  \"aspectRatio\": \"1:1|2:3|3:2|3:4|4:3|4:5|5:4|9:16|16:9|21:9\",\n  \"imageSize\": \"1K|2K|4K\"\n}\n```\n\n**nano-banana-pro edit** (1–14 reference images):\n\n```json\n{\n  \"prompt\": \"string\",\n  \"aspectRatio\": \"...same as generate\",\n  \"imageSize\": \"1K|2K|4K\",\n  \"images\": [\"https://blob-url...\"]\n}\n```\n\n**gpt-image-2 generate:**\n\n```json\n{\n  \"prompt\": \"string\",\n  \"quality\": \"low|medium|high\",\n  \"size\": \"1024x1024|1536x1024|1024x1536|auto\",\n  \"background\": \"opaque|auto\",\n  \"output_format\": \"png|jpeg|webp\",\n  \"moderation\": \"low|auto\"\n}\n```\n\n**gpt-image-2 edit** (adds `images`):\n\n```json\n{\n  \"prompt\": \"string\",\n  \"quality\": \"low|medium|high\",\n  \"size\": \"1024x1024|1536x1024|1024x1536|auto\",\n  \"background\": \"opaque|auto\",\n  \"output_format\": \"png|jpeg|webp\",\n  \"moderation\": \"low|auto\",\n  \"images\": [\"https://blob-url...\"]\n}\n```\n\n**gpt-image-1.5 generate:**\n\n```json\n{\n  \"prompt\": \"string\",\n  \"quality\": \"low|medium|high\",\n  \"size\": \"1024x1024|1536x1024|1024x1536|auto\",\n  \"background\": \"transparent|opaque|auto\",\n  \"output_format\": \"png|jpeg|webp\",\n  \"moderation\": \"low|auto\"\n}\n```\n\n**gpt-image-1.5 edit** (adds `input_fidelity`, `images`):\n\n```json\n{\n  \"prompt\": \"string\",\n  \"quality\": \"low|medium|high\",\n  \"size\": \"1024x1024|1536x1024|1024x1536|auto\",\n  \"background\": \"transparent|opaque|auto\",\n  \"output_format\": \"png|jpeg|webp\",\n  \"moderation\": \"low|auto\",\n  \"input_fidelity\": \"high|low\",\n  \"images\": [\"https://blob-url...\"]\n}\n```\n\n**flux-2-pro generate:**\n\n```json\n{\n  \"prompt\": \"string\",\n  \"aspect_ratio\": \"1:1|16:9|9:16|3:2|2:3|4:5|5:4|4:3|3:4\",\n  \"resolution\": \"0.5 MP|1 MP|2 MP\",\n  \"output_format\": \"webp|jpg|png\",\n  \"output_quality\": 80,\n  \"safety_tolerance\": 2,\n  \"prompt_upsampling\": false\n}\n```\n\n**flux-2-pro edit** (1–8 reference images):\n\n```json\n{\n  \"prompt\": \"string\",\n  \"aspect_ratio\": \"...same as generate\",\n  \"resolution\": \"0.5 MP|1 MP|2 MP\",\n  \"images\": [\"https://blob-url...\"]\n}\n```\n\n**flux-2-max generate** (up to 4 MP):\n\n```json\n{\n  \"prompt\": \"string\",\n  \"aspect_ratio\": \"1:1|16:9|9:16|3:2|2:3|4:5|5:4|4:3|3:4\",\n  \"resolution\": \"0.5 MP|1 MP|2 MP|4 MP\",\n  \"output_format\": \"webp|jpg|png\",\n  \"output_quality\": 80,\n  \"safety_tolerance\": 2,\n  \"prompt_upsampling\": false\n}\n```\n\n**flux-2-max edit** (1–10 reference images):\n\n```json\n{\n  \"prompt\": \"string\",\n  \"aspect_ratio\": \"...same as generate\",\n  \"resolution\": \"0.5 MP|1 MP|2 MP|4 MP\",\n  \"images\": [\"https://blob-url...\"]\n}\n```\n\n**grok generate** (13 aspect ratios including ultra-wide):\n\n```json\n{\n  \"prompt\": \"string\",\n  \"aspect_ratio\": \"1:1|16:9|9:16|4:3|3:4|3:2|2:3|2:1|1:2|19.5:9|9:19.5|20:9|9:20\"\n}\n```\n\n**grok edit:**\n\n```json\n{\n  \"prompt\": \"string\",\n  \"aspect_ratio\": \"...same as generate\",\n  \"images\": [\"https://blob-url...\"]\n}\n```\n\n**grok-video generate** (single endpoint — pass `image` for image-to-video):\n\n```json\n{\n  \"prompt\": \"string\",\n  \"duration\": \"3|6|9|12|15\",\n  \"resolution\": \"480p|720p\",\n  \"aspect_ratio\": \"1:1|16:9|9:16|4:3|3:4|3:2|2:3\",\n  \"image\": \"https://blob-url...\"\n}\n```\n\n**seedance / seedance-fast t2v** (Seedance 2 Pro/Fast happy path):\n\n```json\n{\n  \"prompt\": \"string\",\n  \"duration\": \"5\",\n  \"aspectRatio\": \"16:9\",\n  \"outputResolution\": \"720p\"\n}\n```\n\nOptional advanced fields: `resolution` (`720x720|720x960|960x720|1280x720|720x1280|1280x540`), `upscaleResolution: \"4k\"`, `callBackUrl`.\n\n**seedance / seedance-fast i2v** (first/last-frame keyframe):\n\n```json\n{\n  \"prompt\": \"optional guidance\",\n  \"duration\": \"5\",\n  \"aspectRatio\": \"16:9\",\n  \"outputResolution\": \"720p\",\n  \"mode\": \"keyframe\",\n  \"urls\": [\"https://first-image...\", \"https://optional-last-image...\"],\n  \"urlMediaTypes\": [\"image\", \"image\"]\n}\n```\n\n**seedance / seedance-fast i2v** (reference mode with images/video/audio):\n\n```json\n{\n  \"prompt\": \"@image1 keeps the character identity while @video1 supplies the camera move, synced to @audio1\",\n  \"duration\": \"5\",\n  \"aspectRatio\": \"16:9\",\n  \"outputResolution\": \"720p\",\n  \"mode\": \"reference\",\n  \"urls\": [\"https://image-reference...\", \"https://video-reference...\"],\n  \"urlMediaTypes\": [\"image\", \"video\"],\n  \"audioUrls\": [\"https://audio-reference...\"]\n}\n```\n\nSeedance `urlMediaTypes` must align 1:1 with `urls`: use `\"image\"` for images and `\"video\"` for videos. StableStudio verifies media types from each URL before charging and persists the verified `urlMediaTypes`, but callers should still include it so `@image1` and `@video1` references are unambiguous. In reference mode, `@imageN` counts image URLs only, `@videoN` counts video URLs only, and `@audioN` counts `audioUrls` only. Use one strong reference first, then add more control if needed; overloaded prompts with many references can conflict.\n\nFor character references, a clean fashion-sketch reference can preserve identity cues with fewer visual artifacts than heavily stylized photo filters. Generate a sketch from the source photo first, upload that sketch, and use it as `@image1` in reference mode. A useful sketch prompt is: \"Create a fashion sketch illustration of the person from the reference photo. Three views side by side: full body front, medium portrait, full body three-quarter. Style: loose expressive pencil lines with selective watercolor fill, cool grey-blue palette, white paper negative space. Skin in light pencil with minimal hatching; hair in sharp dark ink lines. Preserve facial features, hairstyle, clothing silhouette, and distinguishing features.\" Also describe the character in the Seedance prompt itself so the model has both visual and text anchors. For early drafts, use `seedance-fast`; for final quality, switch to `seedance`. Front-facing or three-quarter character references usually give the most consistent results.\n\nSeedance reference/prompt sources:\n\n- [WaveSpeed Seedance 2.0 Guide](https://wavespeed.ai/blog/posts/seedance-2-0-complete-guide-multimodal-video-creation/) — multimodal reference limits, @ mention syntax, and motion/audio use cases.\n- [Magic Hour Reference Guide](https://magichour.ai/blog/seedance-20-reference-guide) — identity, motion, audio sync, and common reference failure modes.\n- [SeaArt Best Prompts](https://www.seaart.ai/blog/seedance-2-0-prompt) — five-segment, CRAFT, and timeline prompt structures.\n\nUse `seedance-fast` for the default happy path. Use `seedance` for Pro quality, 1080p, or higher-fidelity output. `seedance-fast` supports 480p/720p. 4K is available through `upscaleResolution: \"4k\"` and is significantly more expensive.\n\n**wan-2.6 t2v:**\n\n```json\n{\n  \"prompt\": \"string\",\n  \"duration\": \"5|10|15\",\n  \"size\": \"1280*720|720*1280|1920*1080|1080*1920\",\n  \"negativePrompt\": \"string\",\n  \"enablePromptExpansion\": true,\n  \"multiShots\": false,\n  \"audioUrl\": \"https://...\",\n  \"seed\": 0\n}\n```\n\nWan audio URLs must be HTTPS mp3 or wav files, 3-30 seconds long, and at most 15MB.\n\n**wan-2.6 i2v:**\n\n```json\n{\n  \"prompt\": \"string\",\n  \"image\": \"https://blob-url...\",\n  \"duration\": \"5|10|15\",\n  \"resolution\": \"720p|1080p\",\n  \"negativePrompt\": \"string\",\n  \"enablePromptExpansion\": true,\n  \"multiShots\": false,\n  \"audioUrl\": \"https://...\",\n  \"seed\": 0\n}\n```\n\nWan `multiShots` only has an effect when `enablePromptExpansion` is true.\n\n**sora-2 generate** (pass `input_reference` for image-to-video):\n\n```json\n{\n  \"prompt\": \"string\",\n  \"seconds\": \"4|8|12\",\n  \"size\": \"1280x720|720x1280\",\n  \"input_reference\": \"https://blob-url...\",\n  \"autoCrop\": true\n}\n```\n\n**sora-2-pro generate** (same as sora-2, extra sizes):\n\n```json\n{\n  \"prompt\": \"string\",\n  \"seconds\": \"4|8|12\",\n  \"size\": \"1280x720|720x1280|1792x1024|1024x1792\",\n  \"input_reference\": \"https://blob-url...\",\n  \"autoCrop\": true\n}\n```\n\n**veo-3.1 generate:**\n\n```json\n{\n  \"prompt\": \"string\",\n  \"durationSeconds\": \"4|6|8\",\n  \"resolution\": \"720p|1080p\",\n  \"aspectRatio\": \"16:9|9:16\",\n  \"negativePrompt\": \"string\",\n  \"imageMode\": \"none|first-frame|reference|interpolation\",\n  \"image\": \"https://first-frame-blob-url...\",\n  \"lastFrame\": \"https://last-frame-blob-url...\",\n  \"referenceImages\": [\"https://blob-url...\"]\n}\n```\n\n**veo-3.1-fast generate:**\n\n```json\n{\n  \"prompt\": \"string\",\n  \"durationSeconds\": \"4|6|8\",\n  \"resolution\": \"720p|1080p\",\n  \"aspectRatio\": \"16:9|9:16\",\n  \"imageMode\": \"none|first-frame|reference|interpolation\",\n  \"image\": \"https://first-frame-blob-url...\",\n  \"lastFrame\": \"https://last-frame-blob-url...\",\n  \"referenceImages\": [\"https://blob-url...\"]\n}\n```\n\nVeo 3.1 Fast does not support `negativePrompt`; omit it or use `veo-3.1`.\n\nVeo modes: omit `image`/`lastFrame`/`referenceImages` for pure text-to-video; pass `image` alone for image-to-video (first frame); pass `image` + `lastFrame` with `imageMode: \"interpolation\"` to animate between frames; pass up to 3 `referenceImages` with `imageMode: \"reference\"` for style guidance.\n\n## File Upload\n\nUpload images, video, or audio for editing, image-to-video, or reference video generation. Three-step flow:\n\n**Step 1: Get upload token** (payment, $0.01)\n\n```\nPOST /api/upload\nPAYMENT-SIGNATURE: <signed payment>\nContent-Type: application/json\n\n{\"filename\": \"reference.mp4\", \"contentType\": \"video/mp4\"}\n```\n\nReturns:\n\n```json\n{\n  \"uploadId\": \"uuid\",\n  \"clientToken\": \"vercel_blob_...\",\n  \"pathname\": \"uploads/uuid/image.png\",\n  \"expiresAt\": \"...\"\n}\n```\n\n**Step 2: Upload file directly to Vercel Blob**\n\n```bash\ncurl -X PUT \"https://vercel.com/api/blob/?pathname=uploads/uuid/image.png\" \\\n  -H \"authorization: Bearer $clientToken\" \\\n  -H \"x-content-type: image/png\" \\\n  -H \"x-api-version: 11\" \\\n  --data-binary @image.png\n```\n\nReturns `{\"url\": \"https://....blob.vercel-storage.com/...\"}`.\n\n**Step 3: Confirm upload** (SIGN-IN-WITH-X auth, no payment)\n\n```\nPOST /api/upload/confirm\nSIGN-IN-WITH-X: <base64>\nContent-Type: application/json\n\n{\"uploadId\": \"uuid\", \"blobUrl\": \"https://....blob.vercel-storage.com/...\"}\n```\n\nReturns `{\"success\": true, \"upload\": {\"id\": \"...\", \"blobUrl\": \"...\"}}`.\n\nUse the `blobUrl` in edit/i2v requests.\n\n## Job Polling (SIGN-IN-WITH-X)\n\nJob routes require wallet signature authentication (no payment):\n\n```\nGET /api/jobs/{jobId}\nSIGN-IN-WITH-X: <base64>\n```\n\nHeader contains base64-encoded CAIP-122 message:\n\n```json\n{\n  \"domain\": \"stablestudio.dev\",\n  \"address\": \"0x...\",\n  \"uri\": \"https://stablestudio.dev/api/jobs/{jobId}\",\n  \"version\": \"1\",\n  \"chainId\": \"eip155:8453\",\n  \"nonce\": \"<random>\",\n  \"issuedAt\": \"<ISO8601>\",\n  \"expirationTime\": \"<ISO8601>\",\n  \"signature\": \"0x...\"\n}\n```\n\nIf auth missing/invalid, returns 402 with SIWX extension:\n\n```json\n{\n  \"x402Version\": 2,\n  \"accepts\": [],\n  \"extensions\": {\n    \"sign-in-with-x\": {\n      \"info\": {\n        \"domain\": \"stablestudio.dev\",\n        \"uri\": \"https://stablestudio.dev/api/jobs/{jobId}\",\n        \"version\": \"1\",\n        \"nonce\": \"<server-generated>\",\n        \"issuedAt\": \"<ISO8601>\",\n        \"expirationTime\": \"<ISO8601>\"\n      },\n      \"supportedChains\": [{ \"chainId\": \"eip155:8453\", \"type\": \"eip191\" }],\n      \"schema\": { \"...\": \"...\" }\n    }\n  }\n}\n```\n\n**Routes:**\n\n- `GET /api/jobs/{jobId}` — Get job status\n- `GET /api/jobs` — List jobs (`?limit=20&status=complete`)\n- `DELETE /api/jobs/{jobId}` — Delete failed job\n\n**Response:**\n\n```json\n{ \"status\": \"complete\", \"result\": { \"imageUrl\": \"https://...\" } }\n```\n\nVideos return `{videoUrl, thumbnailUrl}`. Returned URLs expire after roughly 20 minutes — download the asset immediately once the job completes.\n\n**Do not resubmit a generation while its job is `pending` or `loading`.** Normal generation can take several minutes, especially GPT Image and video models. Keep polling the original `jobId`; duplicate submissions create duplicate paid jobs.\n\n**Polling intervals:**\n\n| Model family                   | Poll every |\n| ------------------------------ | ---------- |\n| Most image models              | 5s         |\n| `gpt-image-2`, `gpt-image-1.5` | 10s        |\n| Video models                   | 15s        |\n"}