AiWings API reference
Generate and edit images and videos with the best AI models from your own code. Everything AiWings does inside Claude, ChatGPT and Cursor is available here too.
Version v1 · Updated October 31, 2026
Introduction
The AiWings API is a JSON API over HTTPS. You send requests with an API key, AiWings runs the model, stores the result, and gives you back a permanent URL to the file.
All endpoints live under one base URL:
https://aiwings.io/api/v1- Requests and responses are JSON. Send
Content-Type: application/jsonwith a body. - Images and videos are jobs: you start one, then read its status until it's done. See How jobs work.
- The API uses the same credits as AiWings in your AI agents. There's no separate plan.
Quick start
- Create a key on the API page in your dashboard.
- Store it as an environment variable, for example
AIWINGS_API_KEY. - Create an image. With
"wait": truethe request returns once the image is ready (up to 60 seconds), so you get the URL in one call.
1curl https://aiwings.io/api/v1/images \2-H "Authorization: Bearer $AIWINGS_API_KEY" \3-H "Content-Type: application/json" \4-d '{5"prompt": "A ceramic coffee mug on a sunny kitchen counter",6"model": "gpt-image-2.5-flare",7"quality": "medium",8"aspect_ratio": "1:1",9"wait": true10}'
The response is an image object:
{
"id": "8f1c2a4e-5b7d-4e2f-9a31-0c6d8e7f1b22",
"object": "image",
"status": "succeeded",
"model": "gpt-image-2.5-flare",
"quality": "medium",
"aspect_ratio": "1:1",
"prompt": "A ceramic coffee mug on a sunny kitchen counter",
"output": {
"url": "https://…/generations/8f1c2a4e-5b7d-4e2f-9a31-0c6d8e7f1b22.png"
},
"credits": 6,
"error": null,
"created_at": "2026-10-31T09:41:12.512Z"
}Authentication
Every request needs your API key in the Authorization header, as a Bearer token:
Authorization: Bearer aiw_live_…- Keys start with
aiw_live_followed by 40 random characters. - Keys in the URL (for example
?api_key=) are always rejected, so they never end up in logs or browser history. - A missing, malformed or revoked key returns
401 authentication_failed. - The API does not allow browser (CORS) requests. Call it from your server, a script, or a backend function, never from front-end or mobile app code where anyone could read the key.
Security
AiWings is built so that a key does as little damage as possible if it ever leaks.
| Protection | What it means for you |
|---|---|
| Hashed storage | We store only a SHA-256 hash of each key. The full key is shown once when you create it, and nobody, including us, can read it again. |
| Instant revoke | Revoking a key on the API page blocks it from the very next request. There's no cache to wait for. |
| Per-key monthly limit | Give each key a monthly credit cap. When a key reaches it, new jobs return 403 spend_limit_reached until next month or until you raise the limit. |
| Rate limits | Each key is limited to 300 requests per minute, 60 of them creating jobs, and your account to 10 jobs rendering at once. |
| Least privilege | API keys can generate, read your generations and change defaults. They can't create keys, see billing details or change your plan. |
| HTTPS only | Keys only travel over TLS, and only in the Authorization header. |
Recommended practice:
- Use one key per app or environment (production, staging, a script), so you can revoke one without touching the others.
- Set a monthly limit on every key, sized to what that app should ever spend.
- Keep keys in environment variables or a secrets manager. Never commit them to git.
- To rotate a key: create a new one, deploy it, then revoke the old one. You can have up to 10 active keys.
- If a key leaks, revoke it right away and email Mejed@templyo.io.
How jobs work
Images take seconds and videos can take minutes, so every generation runs as a job. Creating one returns right away with a job object whose status is one of:
| Status | Meaning |
|---|---|
| processing | The model is rendering, or the file is being saved. |
| succeeded | Done. output.url is the permanent URL to the file. |
| failed | The model couldn't make it. error.message says why, and the credits are refunded automatically. |
Three ways to get the result:
- Wait on create. Add
"wait": true(or a number of seconds, up to 60) to the request body. Best for images. - Long-poll. Call
GET /v1/images/{id}?wait=30orGET /v1/videos/{id}?wait=30. The request returns as soon as the job finishes, or after 30 seconds with the current status. Best for videos. - Poll. Call the GET endpoint every few seconds without
wait.
Jobs keep running even if your request disconnects. A job started from your code also shows up in your dashboard library.
Idempotency
Networks fail. To retry a create request safely, send an Idempotency-Key header with a unique value (a UUID works well, 1–100 characters of letters, numbers, - _ : .).
If a job with that key already exists on your account, the API returns that job instead of starting a new one, so you're never charged twice. Replayed responses have the header Idempotent-Replayed: true and status 200 instead of 201.
curl -X POST "https://aiwings.io/api/v1/images" \
-H "Authorization: Bearer $AIWINGS_API_KEY" \
-H "Idempotency-Key: 9b2f4c1e-sneaker-hero" \
-H "Content-Type: application/json" \
-d '{
"prompt": "Studio photo of a red sneaker",
"wait": true
}'Errors
Errors use standard HTTP status codes and always have the same body. Include the request_id when you contact support. Every response also carries it in the X-Request-Id header.
{
"error": {
"type": "invalid_request",
"message": "GPT Image 2.5 Flare quality must be one of: low, medium, high, xhigh, max.",
"param": "quality",
"request_id": "req_4c1f0e6a9b2d4e7f8a1b2c3d4e5f6a7b"
}
}| Status | type | When |
|---|---|---|
| 400 | invalid_request | A field is missing, unknown, or not allowed for that model. param names the field. |
| 401 | authentication_failed | Missing, malformed or revoked API key. |
| 402 | insufficient_credits | Your balance can't cover this job. Top up in the dashboard. |
| 402 | subscription_required | Generating needs an active plan. |
| 403 | spend_limit_reached | This key reached its monthly credit limit. |
| 404 | not_found | No job with that id on your account. |
| 413 | payload_too_large | The JSON body is too big (64 KB max). |
| 429 | rate_limited | Too many requests for this key. Retry after the Retry-After header. |
| 429 | too_many_jobs | 10 jobs are already rendering. Wait for one to finish. |
| 502 | generation_failed | The model couldn't start the job. Credits were refunded. Retry shortly. |
| 503 | service_unavailable | Temporary problem on our side. Retry with backoff. |
| 500 | internal_error | Unexpected error. Retry, and contact support with the request_id if it repeats. |
Unknown fields are rejected rather than ignored, so a typo like "resoltion" fails loudly instead of quietly using a default.
Rate limits
| Limit | Value | Scope |
|---|---|---|
| All requests | 300 / minute | Per key |
| Requests that create or change something | 60 / minute | Per key |
| Jobs rendering at the same time | 10 | Per account (API jobs) |
Every response tells you where you stand:
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 287
X-RateLimit-Reset: 1761903720 # unix seconds when the window resetsOn 429, wait for the number of seconds in Retry-After, then retry. Need higher limits? Email Mejed@templyo.io.
Credits
- The API draws from the same credit balance as your AI agents and the dashboard.
- Images cost a fixed number of credits per image, by model and quality. Videos cost credits per second, by model and resolution. Jobs with a reference video use a higher per-second rate.
- Credits are charged when a job starts. Failed jobs are refunded automatically.
- Each job returns what it cost in
credits.GET /v1/modelslists every price andGET /v1/accountshows your balance.
Full price tables are under Image models and Video models, and plans are on the credits page.
Create an image
/v1/imagesGenerates a new image from a prompt, or edits images: pass reference images (your product, a character, a style) or the id of an earlier image to change it.
Body
promptstring · required- What to create, up to 4,000 characters. For edits, describe the change.
modelstring · optional- Model id, e.g.
gpt-image-2.5-flare. Defaults to your saved default. See Image models. qualitystring · optional- Model-specific:
low…maxfor GPT Image models,1K/2K/4Kfor Nano Banana models. Sets the price. aspect_ratiostring · default "1:1"- e.g.
1:1,3:2,16:9,9:16. Each model lists what it supports. reference_imagesstring[] · optional- Public URLs of images to use as references (product, character, style). Use uploads for local files. The maximum depends on the model (
max_reference_imagesinGET /v1/models); text-only models (Imagen 4, Flux Fast) have 0 and reject references. source_generation_idstring · optional- Id of an earlier image to edit. It's used as the first reference.
waitboolean | number · default false- Hold the request until the image is ready, up to 60 seconds. true = 60.
Headers
Idempotency-Keystring · optional- Makes retries safe. See Idempotency.
Returns 201 with an image object.
Edit with a reference image
curl -X POST "https://aiwings.io/api/v1/images" \
-H "Authorization: Bearer $AIWINGS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "Place this bottle on a mossy rock in a misty forest, soft morning light",
"model": "nano-banana-pro",
"quality": "2K",
"aspect_ratio": "4:5",
"reference_images": [
"https://example.com/bottle.png"
],
"wait": true
}'Change an earlier result
curl -X POST "https://aiwings.io/api/v1/images" \
-H "Authorization: Bearer $AIWINGS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "Same scene, but at night with warm string lights",
"source_generation_id": "8f1c2a4e-5b7d-4e2f-9a31-0c6d8e7f1b22",
"wait": true
}'Get an image
/v1/images/{id}Returns the current state of an image job. Add ?wait=30 to hold the request until it finishes (max 60).
curl "https://aiwings.io/api/v1/images/8f1c2a4e-5b7d-4e2f-9a31-0c6d8e7f1b22?wait=30" \
-H "Authorization: Bearer $AIWINGS_API_KEY"Create a video
/v1/videosStarts a video job: text to video, animate an image (first frame, optional last frame), or guide the video with reference images and clips. Videos include generated audio unless you turn it off.
Body
promptstring · depends on model- What happens in the video, up to 4,000 characters. Required for some models, see prompt_required in GET /v1/models.
modelstring · optional- Video model id, e.g.
seedance-2.0. Defaults to your saved default. resolutionstring · optional- e.g.
480p,720p,1080p. Sets the per-second price. durationinteger · optional- Length in seconds, within the model's min and max.
aspect_ratiostring · optional- e.g.
16:9,9:16,1:1,adaptive(match the first frame). audioboolean · default true- Generate a soundtrack and sound effects.
formatstring · default "mp4"- Output file format. Some models also offer
mov. first_framestring · optional- Public URL of an image the video starts from.
source_generation_idstring · optional- Id of one of your images to use as the first frame (instead of first_frame).
last_framestring · optional- Public URL of an image the video ends on. Needs a first frame.
reference_imagesstring[] · optional- Public image URLs for characters, products, style or scene. Mention them in the prompt as [Image1], [Image2]…
reference_videosstring[] · optional- Public MP4/MOV URLs for motion, camera or editing style. Uses the higher reference-video rate.
waitboolean | number · default false- Hold the request up to 60 seconds. Most videos take longer, so long-poll the GET endpoint instead.
1# 1. Start the job2curl https://aiwings.io/api/v1/videos \3-H "Authorization: Bearer $AIWINGS_API_KEY" \4-H "Content-Type: application/json" \5-H "Idempotency-Key: launch-teaser-001" \6-d '{7"prompt": "Slow dolly shot of a glass bottle on wet sand at sunset, waves rolling in",8"model": "seedance-2.0",9"resolution": "720p",10"duration": 5,11"aspect_ratio": "16:9",12"audio": true13}'1415# 2. Poll until status is "succeeded" (or "failed")16curl "https://aiwings.io/api/v1/videos/VIDEO_ID?wait=30" \17-H "Authorization: Bearer $AIWINGS_API_KEY"
Returns 201 with a video object:
{
"id": "2b9e6d10-7c3a-4f8e-b1d2-55a0c9e4f871",
"object": "video",
"status": "processing",
"model": "seedance-2.0",
"resolution": "720p",
"duration": 5,
"aspect_ratio": "16:9",
"audio": true,
"format": "mp4",
"prompt": "Slow dolly shot of a glass bottle on wet sand at sunset",
"output": null,
"credits": 115,
"error": null,
"created_at": "2026-10-31T09:45:03.020Z"
}Get a video
/v1/videos/{id}Returns the current state of a video job. Add ?wait=30 to long-poll: the request returns as soon as the video is ready, or after 30 seconds (max 60).
curl "https://aiwings.io/api/v1/videos/2b9e6d10-7c3a-4f8e-b1d2-55a0c9e4f871?wait=30" \
-H "Authorization: Bearer $AIWINGS_API_KEY"List generations
/v1/generationsYour images and videos, newest first, from the API, your AI agents and the dashboard.
Query
typestring · optionalimageorvideo.statusstring · optionalprocessing,succeededorfailed.limitinteger · default 20- 1 to 100.
cursorstring · optional- next_cursor from the previous page.
{
"object": "list",
"data": [
{
"id": "8f1c2a4e-5b7d-4e2f-9a31-0c6d8e7f1b22",
"object": "image",
"status": "succeeded",
"model": "gpt-image-2.5-flare",
"quality": "medium",
"aspect_ratio": "1:1",
"prompt": "A ceramic coffee mug on a sunny kitchen counter",
"output": {
"url": "https://…/generations/8f1c2a4e-5b7d-4e2f-9a31-0c6d8e7f1b22.png"
},
"credits": 6,
"error": null,
"created_at": "2026-10-31T09:41:12.512Z"
},
"…"
],
"has_more": true,
"next_cursor": "MjAyNi0xMC0zMVQwOTo0MToxMi41MTJa…"
}/v1/generations/{id}Any single generation, image or video. Supports ?wait like the endpoints above.
Upload a file
/v1/uploadsFor files on your machine or server. Ask for an upload URL, PUT the bytes to it, then pass the returned url anywhere a URL is accepted (reference_images, first_frame, last_frame, reference_videos). Files that are already public on the web can be passed directly.
Body
content_typestring · required- One of
image/jpeg,image/png,image/webp,image/gif,video/mp4,video/quicktime. size_bytesinteger · optional- File size, checked against the 50 MB limit.
filenamestring · optional- For your reference.
{
"id": "upl_6f1d2c3b4a5e6f708192a3b4",
"object": "upload",
"filename": "product.png",
"content_type": "image/png",
"upload_url": "https://…/object/upload/sign/…?token=…",
"upload_method": "PUT",
"upload_headers": {
"Content-Type": "image/png"
},
"url": "https://…/api-uploads/upl_6f1d2c3b4a5e6f708192a3b4.png",
"expires_at": "2026-10-31T11:41:12.512Z"
}The upload URL works once and expires after 2 hours. Uploaded files are public but unguessable, like outputs.
1# 1. Ask for an upload URL2curl https://aiwings.io/api/v1/uploads \3-H "Authorization: Bearer $AIWINGS_API_KEY" \4-H "Content-Type: application/json" \5-d '{ "content_type": "image/png", "filename": "product.png" }'67# 2. PUT the file to upload_url from the response8curl -X PUT "UPLOAD_URL" \9-H "Content-Type: image/png" \10--data-binary @product.png1112# 3. Use the returned "url" as a reference13curl https://aiwings.io/api/v1/images \14-H "Authorization: Bearer $AIWINGS_API_KEY" \15-H "Content-Type: application/json" \16-d '{ "prompt": "Put this product on a marble table, soft daylight", "reference_images": ["URL"] }'
List models
/v1/modelsEvery model with its options and credit prices. Filter with ?type=image or ?type=video. Use it to build model pickers or to check prices before you start a job.
{
"object": "list",
"data": [
{
"id": "nano-banana-2",
"object": "model",
"type": "image",
"name": "Nano Banana 2",
"description": "Best quality-per-credit (Gemini 3.1 Flash Image)",
"qualities": [
{
"value": "1K",
"credits": 8
},
{
"value": "2K",
"credits": 13
},
{
"value": "4K",
"credits": 19
}
],
"default_quality": "1K",
"aspect_ratios": [
"1:1",
"2:3",
"3:2",
"…"
],
"max_reference_images": 14
},
"…"
]
}Defaults
/v1/defaults/v1/defaultsDefaults are used whenever a request leaves out model, quality, resolution, duration, aspect_ratio or audio. They're shared with your AI agents and the dashboard. PATCH only changes the fields you send.
curl -X PATCH "https://aiwings.io/api/v1/defaults" \
-H "Authorization: Bearer $AIWINGS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"image": {
"model": "nano-banana-2",
"quality": "2K"
},
"video": {
"resolution": "1080p",
"duration": 8
}
}'{
"object": "defaults",
"image": {
"model": "nano-banana-2",
"quality": "2K"
},
"video": {
"model": "seedance-2.0",
"resolution": "1080p",
"duration": 8,
"aspect_ratio": "16:9",
"audio": true
}
}Account
/v1/accountYour credit balance, plan, and how much this key has spent this month.
{
"object": "account",
"credits": 1840,
"plan": "sub-pro",
"subscription_status": "active",
"renews_at": "2026-11-28T00:00:00Z",
"can_generate": true,
"api_key": {
"name": "Shopify sync",
"monthly_credit_limit": 1000,
"credits_used_this_month": 212
}
}Image object
Fields
idstring- Job id.
object"image"- Always image.
statusstring- processing, succeeded or failed.
modelstring- Model id used.
qualitystring- Quality used.
aspect_ratiostring- Aspect ratio used.
promptstring- The prompt.
outputobject | null- When succeeded: { url }, a permanent URL to the PNG.
creditsinteger- Credits charged. Refunded if the job fails.
errorobject | null- When failed: { message, refunded }.
created_atstring- ISO 8601 timestamp.
Video object
Fields
idstring- Job id.
object"video"- Always video.
statusstring- processing, succeeded or failed.
modelstring- Model id used.
resolutionstring- Resolution used.
durationinteger- Length in seconds.
aspect_ratiostring- Aspect ratio used.
audioboolean- Whether audio was generated.
formatstring- mp4 or mov.
promptstring- The prompt (may be empty for some image-to-video jobs).
outputobject | null- When succeeded: { url, format }.
creditsinteger- Credits charged. Refunded if the job fails.
errorobject | null- When failed: { message, refunded }.
created_atstring- ISO 8601 timestamp.
Image models
Credits per image. Live values are always in GET /v1/models?type=image.
| Model id | Name | Quality → credits | Max references |
|---|---|---|---|
gpt-image-2.5-flare | GPT Image 2.5 Flare | Low 2 · Medium 6 · High 16 · Xhigh 31 · Max 63 | 10 |
gpt-image-2.5-sunburst | GPT Image 2.5 Sunburst | Low 2 · Medium 6 · High 16 · Xhigh 31 · Max 63 | 10 |
gpt-image-2 | GPT Image 2 | Low 2 · Medium 6 · High 16 | 10 |
gpt-image-1.5 | GPT Image 1.5 | Low 2 · Medium 7 · High 17 | 10 |
nano-banana | Nano Banana | 1K 5 | 3 |
nano-banana-2 | Nano Banana 2 | 1K 8 · 2K 13 · 4K 19 | 14 |
nano-banana-pro | Nano Banana Pro | 1K 19 · 2K 19 · 4K 38 | 14 |
imagen-4-ultra | Imagen 4 Ultra | 1K 8 · 2K 8 | 0 |
imagen-4 | Imagen 4 | 1K 5 · 2K 5 | 0 |
imagen-4-fast | Imagen 4 Fast | 1K 3 | 0 |
seedream-5-lite | Seedream 5 Lite | 2K 5 · 3K 5 | 14 |
grok-imagine | Grok Imagine | 1K 3 | 1 |
flux-fast | Flux Fast | 1K 1 | 0 |
Video models
Credits per second of video. Live values are always in GET /v1/models?type=video.
| Model id | Name | Resolution → credits/s | With reference video | Duration |
|---|---|---|---|---|
seedance-2.0 | Seedance 2.0 | 480p 10 · 720p 23 · 1080p 57 · 4k 125 | 480p 13 · 720p 28 · 1080p 69 · 4k 157 | 4–15s |
seedance-2.5 | Seedance 2.5 | 480p 13 · 720p 29 | 480p 54 · 720p 121 | 4–30s |
Example: a 5-second seedance-2.0 video at 720p costs 23 × 5 = 115 credits.
Changelog
| Date | Change |
|---|---|
| October 31, 2026 | v1 released: images, videos, uploads, generations, models, defaults, account. |