{"version":1,"resources":["https://stablestudio.dev/api/upload","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/generate/arrow-1.1/vectorize","https://stablestudio.dev/api/generate/arrow-1.1-max/vectorize","https://stablestudio.dev/api/jobs","https://stablestudio.dev/api/jobs/{jobId}","DELETE https://stablestudio.dev/api/jobs/{jobId}","https://stablestudio.dev/api/upload/confirm"],"mppResources":["https://stablestudio.dev/api/upload","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/generate/arrow-1.1/vectorize","https://stablestudio.dev/api/generate/arrow-1.1-max/vectorize"],"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- **Image to SVG conversion:** `arrow-1.1` — Use `/api/generate/arrow-1.1/vectorize` when the user wants to convert an existing image into an SVG.\n- **Video generation:** `veo-3.1` — Best quality/cost ratio, supports up to 1080p resolution\n\n## Payment Flow\n\nGeneration endpoints are high-intent paid calls. The unpaid 402 challenge may include `checkout_session` metadata with the selected model, operation, prompt/media summary, price, preview image, and a completion handler for the same paid endpoint. Payment terms remain authoritative in the x402/MPP challenge headers; legacy clients can keep using the normal paid POST and retry flow.\n\n1. `POST /api/generate/{model}/{operation}` without payment header\n   - Returns `402` with `PAYMENT-REQUIRED` header (base64 JSON)\n   - Response JSON may include `checkout_session` for high-intent review UI. Treat it as display/flow metadata, not payment authority.\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\nPayment requirements are in the 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\nThe response body may also include a UCP-style checkout session:\n\n```json\n{\n  \"checkout_session\": {\n    \"status\": \"ready_for_complete\",\n    \"line_items\": [\n      {\n        \"item\": {\n          \"title\": \"GPT Image 2 Edit\",\n          \"image_url\": \"https://example.com/input.png\"\n        }\n      }\n    ],\n    \"payment\": {\n      \"handlers\": [\n        {\n          \"config\": {\n            \"complete_url\": \"https://stablestudio.dev/api/generate/gpt-image-2/edit\",\n            \"method\": \"POST\",\n            \"body\": {\n              \"prompt\": \"...\"\n            }\n          }\n        }\n      ]\n    }\n  }\n}\n```\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\n### Convert\n\nUse these endpoints when the user has an existing image and asks to convert it to SVG.\n\n| Endpoint                                | Cost  | Time |\n| --------------------------------------- | ----- | ---- |\n| `/api/generate/arrow-1.1/vectorize`     | $0.15 | ~30s |\n| `/api/generate/arrow-1.1-max/vectorize` | $0.20 | ~60s |\n\nCanonical OpenAPI spec: `GET /openapi.json`.\n\n## Input Schemas\n\nMedia fields (`images`, `image`, `urls`, `input_reference`, `referenceImages`, etc.) accept any publicly reachable HTTPS URL — your own hosting, Vercel Blob, StableUpload, S3, or anywhere else on the web. No upload to StableStudio is required. Images must be jpeg/png/gif/webp and at most 10MB; every URL is verified reachable with the right content type before you are charged. If your file only exists locally, the [File Upload](#file-upload) flow ($0.01) gives you a hosted URL.\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://image-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://image-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://image-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://image-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://image-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://image-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://image-url...\"]\n}\n```\n\n**Image to SVG / Image to SVG Max** (convert an image URL to SVG):\n\n```json\n{\n  \"image\": \"https://image-url...\",\n  \"target_size\": 1024,\n  \"auto_crop\": false,\n  \"max_output_tokens\": 4096\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://image-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://image-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://image-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://image-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-image-url...\",\n  \"lastFrame\": \"https://last-frame-image-url...\",\n  \"referenceImages\": [\"https://image-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-image-url...\",\n  \"lastFrame\": \"https://last-frame-image-url...\",\n  \"referenceImages\": [\"https://image-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\nOptional — media URLs in generate/edit requests can come from anywhere on the public web. Use this flow only when your file exists locally and you need a hosted URL. 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 returned `blobUrl` like any other media URL 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"}