{
  "openapi": "3.1.0",
  "info": {
    "title": "PixAI API - OpenAPI 2.0",
    "description": "Users own the copyrights to images generated through the API. PixAI does not claim any copyright over user-generated works. However, users must ensure that generated content does not infringe any third-party rights and complies with applicable local laws and regulations.\n\nPixAI's official models (e.g. Haruka, Tsubaki) are copyrighted by PixAI. We grant approved users the right to use these models for commercial activities, but reselling or redistributing the model files themselves is prohibited.\n\nFor details, please refer to:\n",
    "termsOfService": "https://pixai.art/terms",
    "license": {
      "name": "Apache 2.0",
      "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
    },
    "version": "2.0.0"
  },
  "servers": [
    {
      "url": "https://api.pixai.art/v2"
    }
  ],
  "tags": [
    {
      "name": "image",
      "description": "Image generation and editing endpoints"
    },
    {
      "name": "video",
      "description": "Video generation endpoints"
    },
    {
      "name": "task",
      "description": "Read a task and its results"
    },
    {
      "name": "media",
      "description": "Upload input files and resolve media IDs to URLs"
    },
    {
      "name": "model",
      "description": "Find models, LoRAs, sizes and color palettes"
    }
  ],
  "paths": {
    "/image/create": {
      "post": {
        "tags": [
          "image"
        ],
        "summary": "Create an image generation task",
        "description": "Start an asynchronous image generation task with the simplified v2 API. The response returns the new task's ID.\n\nThe v2 API provides a streamlined interface with user-friendly parameters such as `aspectRatio`, `mode`, and named `style` presets, replacing the raw pixel dimensions and internal parameter names of v1.\n",
        "operationId": "createImage",
        "x-codeSamples": [
          {
            "id": "curl",
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X POST https://api.pixai.art/v2/image/create \\\n  -H \"Authorization: Bearer $PIXAI_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"modelVersionId\": \"1983308862240288769\",\n    \"prompt\": \"1girl, green hair, solo, standing\",\n    \"aspectRatio\": \"9:16\",\n    \"mode\": \"standard\",\n    \"batchSize\": 4,\n    \"seed\": 12345\n  }'\n"
          },
          {
            "id": "js",
            "lang": "javascript",
            "label": "JavaScript (fetch)",
            "source": "const response = await fetch(\"https://api.pixai.art/v2/image/create\", {\n  method: \"POST\",\n  headers: {\n    \"Authorization\": `Bearer ${PIXAI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    modelVersionId: \"1983308862240288769\",\n    prompt: \"1girl, green hair, solo, standing\",\n    aspectRatio: \"9:16\",\n    mode: \"standard\",\n    batchSize: 4,\n    seed: 12345,\n  }),\n});\nconst task = await response.json();\nconsole.log(task);\n"
          },
          {
            "id": "python",
            "lang": "python",
            "label": "Python (requests)",
            "source": "import requests\n\nresponse = requests.post(\n    \"https://api.pixai.art/v2/image/create\",\n    headers={\n        \"Authorization\": f\"Bearer {PIXAI_API_KEY}\",\n        \"Content-Type\": \"application/json\",\n    },\n    json={\n        \"modelVersionId\": \"1983308862240288769\",\n        \"prompt\": \"1girl, green hair, solo, standing\",\n        \"aspectRatio\": \"9:16\",\n        \"mode\": \"standard\",\n        \"batchSize\": 4,\n        \"seed\": 12345,\n    },\n)\ntask = response.json()\nprint(task)\n"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateImageRequest"
              },
              "example": {
                "modelVersionId": "1983308862240288769",
                "prompt": "1girl, green hair, solo, standing",
                "aspectRatio": "9:16",
                "mode": "standard",
                "batchSize": 4,
                "seed": 12345
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Image generation task created successfully.\n\nExample Response:\n```json\n{\n  \"id\": \"1943547603237249965\",\n  \"status\": \"waiting\",\n  \"createdAt\": \"2025-11-07T14:54:35.000Z\",\n  \"updatedAt\": \"2025-11-07T14:54:35.000Z\",\n  \"outputs\": { \"mediaIds\": [], \"mediaUrls\": [] }\n}\n```\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Task"
                }
              }
            }
          },
          "400": {
            "description": "The request was rejected before a task was created. `code` says why:\n- `BAD_REQUEST` with `data.issues`: the body failed validation (each issue names the field in `path`), or a field is not supported by this model (`message` says which).\n- `INVALID_ARGUMENT`: a field is not allowed for this model family, e.g. `mode` on an SDXL model or `sampling` on Tsubaki. Only `mode` and `sampling` are checked: `mode` works only on Tsubaki models, `sampling` only on SDXL and SD v1. Remove whichever the model does not accept.\n- `IMAGE_SIZE_NOT_ALLOWED`: `width`/`height` fall outside the model's size ranges (`data.reason`). Pick a size from `GET /v2/generation-model/{modelVersionId}/size-config`, or send `aspectRatio`/`size` instead.\n- `INPUT_IMAGE_TOO_LARGE`: a `contextImages` entry is 4000 px or larger on a side.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "defined": false,
                  "code": "BAD_REQUEST",
                  "status": 400,
                  "message": "Input validation failed",
                  "data": {
                    "issues": [
                      {
                        "code": "custom",
                        "path": [],
                        "message": "Either modelId or modelVersionId must be provided"
                      }
                    ]
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required. Ensure a valid Bearer token is provided.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The account cannot run this task right now. `code` says why:\n- `INSUFFICIENT_BALANCE`: not enough credits for the task.\n- `WAITING_NUM_EXCEEDED`: too many of your tasks are still `waiting`. Wait for some to start before submitting more (see [Limits](/en/docs/quick-start/limits)).\n- `LORA_NUM_EXCEEDED`: more `loras` than your plan allows.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`NOT_FOUND`: no model version has the given `modelVersionId`. `FILE_NOT_FOUND`: a `contextImages` media ID does not exist.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "- `NSFW_PROMPT_REJECTED`: the prompt was rejected by content moderation. Rephrase it; `data.logId` identifies the decision if you contact support.\n- `INVALID_INPUT`: a value is not available for this model or plan, e.g. a `mode` the model does not offer. `message` names the value.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Task creation failed due to an internal server error. Retry with exponential backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/frame-video/create": {
      "post": {
        "tags": [
          "video"
        ],
        "summary": "Create an image-to-video task",
        "description": "Animates an image into a video with PixAI's Tsubaki video model. The video starts on `firstFrameMediaId` and, when you send `lastFrameMediaId`, ends on it. The output keeps the first frame's aspect ratio.\n\nFrames are image media IDs: upload your own with `POST /v2/media/image/upload-url`, or reuse an image you generated. Media owned by another user is rejected.\n\nImage-to-video needs a PixAI membership. Credits are charged when the task is created. Poll `GET /v2/task/{id}` for the result; a finished task's video is `outputs.videoMediaId`.\n",
        "operationId": "createFrameVideo",
        "x-codeSamples": [
          {
            "id": "curl",
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X POST https://api.pixai.art/v2/frame-video/create \\\n  -H \"Authorization: Bearer $PIXAI_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"model\": \"tbkv1.0.1\",\n    \"firstFrameMediaId\": \"1943547603237249965\",\n    \"prompt\": \"she turns around and smiles, hair blowing in the wind\",\n    \"duration\": 5\n  }'\n"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "model": {
                    "enum": [
                      "tbkv1.0.1",
                      "tbkv1.0"
                    ],
                    "type": "string",
                    "description": "The video model. `tbkv1.0.1` is the latest Tsubaki video model."
                  },
                  "firstFrameMediaId": {
                    "type": "string",
                    "description": "Image media ID of the first frame."
                  },
                  "lastFrameMediaId": {
                    "type": "string",
                    "description": "Image media ID of the last frame. Send the first frame again to make a loop."
                  },
                  "prompt": {
                    "default": null,
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "What should happen in the video."
                  },
                  "duration": {
                    "type": "integer",
                    "minimum": 5,
                    "maximum": 15,
                    "default": 5,
                    "description": "Length in whole seconds."
                  },
                  "mode": {
                    "enum": [
                      "basic",
                      "professional"
                    ],
                    "type": "string",
                    "default": "basic",
                    "description": "`professional` adds a 1080p upscale on `tbkv1.0.1` and costs more. It has no effect on `tbkv1.0`."
                  },
                  "generateAudio": {
                    "type": "boolean",
                    "default": true,
                    "description": "Whether to generate a soundtrack."
                  },
                  "audioLanguage": {
                    "default": null,
                    "enum": [
                      "none",
                      "chinese",
                      "english",
                      "japanese",
                      "korean",
                      null
                    ],
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Language of speech in the soundtrack. `none` for no speech."
                  }
                },
                "required": [
                  "model",
                  "firstFrameMediaId"
                ],
                "additionalProperties": false
              },
              "example": {
                "model": "tbkv1.0.1",
                "firstFrameMediaId": "1943547603237249965",
                "prompt": "she turns around and smiles, hair blowing in the wind",
                "duration": 5
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The task was created. Poll `GET /v2/task/{id}` with its `id`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Task"
                }
              }
            }
          },
          "400": {
            "description": "- `INVALID_REFERENCE_MEDIA`: a frame is missing, is not an image, or belongs to another user. `data.code` is `invalid_input` or `media_not_owned`, and `data.mediaId` names the frame.\n- `BAD_REQUEST` with `data.issues`: the body failed validation.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/CannotRun"
          },
          "500": {
            "$ref": "#/components/responses/CreationFailed"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/reference-video/create": {
      "post": {
        "tags": [
          "video"
        ],
        "summary": "Create a reference video task",
        "description": "Generates a video guided by reference images, and depending on the model, reference videos and audio.\n\nEach model accepts different references:\n\n- `tbkv1.0.1`, `tbkv1.0` (Tsubaki): 1–6 images, no videos, up to 3 audio clips, `duration` 5–15.\n- `v4.0`, `v4.0.1` (Seedance 2, Seedance 2 Fast): up to 9 images, up to 3 videos, up to 3 audio clips, `duration` 4–15.\n- `v4.0.3` (Seedance 2.5): up to 30 images, up to 10 videos, up to 10 audio clips, `duration` 4–30.\n- `v3.3` (Vidu): 1–7 images, no videos or audio, `duration` 3–16.\n\nEvery model needs at least one image or video, except `v4.0.3`, which also accepts audio alone.\n\nReference files must meet these limits:\n\n- Video: MP4 or MOV, H.264 or HEVC, 24–60 fps, 2–15 s per clip and 15 s in total (30 s on `v4.0.3`), up to 50 MB (200 MB on `v4.0.3`).\n- Audio: WAV or MP3, 2–15 s per clip and 15 s in total (30 s on `v4.0.3`), under 15 MiB.\n\nCheck a file with `GET /v2/media/{mediaId}/info` before sending it. On `v4.0` and `v4.0.1`, counts and clip lengths are checked after the task is charged: a task that breaks them fails instead of being refused.\n\nCredits are charged when the task is created. Poll `GET /v2/task/{id}` for the result; a finished task's video is `outputs.videoMediaId`.\n",
        "operationId": "createReferenceVideo",
        "x-codeSamples": [
          {
            "id": "curl",
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X POST https://api.pixai.art/v2/reference-video/create \\\n  -H \"Authorization: Bearer $PIXAI_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"model\": \"tbkv1.0.1\",\n    \"prompt\": \"the girl walks through the city at night\",\n    \"referenceImageMediaIds\": [\"1943547603237249965\"],\n    \"ratio\": \"9:16\",\n    \"duration\": 5\n  }'\n"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "model": {
                    "type": "string",
                    "minLength": 1,
                    "enum": [
                      "tbkv1.0.1",
                      "tbkv1.0",
                      "v4.0",
                      "v4.0.1",
                      "v4.0.3",
                      "v3.3"
                    ],
                    "description": "The video model. See the table above for what each accepts. An unknown value answers `403 MODEL_VERSION_NOT_EXISTS`."
                  },
                  "prompt": {
                    "default": null,
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "What should happen in the video. Describe how to use the references."
                  },
                  "referenceImageMediaIds": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "default": [],
                    "description": "Image media IDs."
                  },
                  "referenceVideoMediaIds": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "default": [],
                    "description": "Video media IDs. Not accepted by Tsubaki or Vidu."
                  },
                  "referenceAudioMediaIds": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "default": [],
                    "description": "Audio media IDs, uploaded with `POST /v2/media/audio/upload-url`. Not accepted by Vidu."
                  },
                  "duration": {
                    "type": "integer",
                    "default": 5,
                    "description": "Length in whole seconds. The allowed range depends on `model`."
                  },
                  "ratio": {
                    "enum": [
                      "adaptive",
                      "1:1",
                      "2:3",
                      "3:2",
                      "3:4",
                      "4:3",
                      "9:16",
                      "16:9",
                      "21:9"
                    ],
                    "type": "string",
                    "description": "Output aspect ratio. Omitted or `adaptive` follows the references. Seedance models do not take `2:3` or `3:2`, and Vidu ignores this field.\n"
                  },
                  "mode": {
                    "enum": [
                      "basic",
                      "professional"
                    ],
                    "type": "string",
                    "default": "basic",
                    "description": "`professional` adds an upscale (1080p on `v4.0`, 720p on `v4.0.1`) and costs more. Not accepted by `v4.0.3`."
                  },
                  "generateAudio": {
                    "type": "boolean",
                    "default": true,
                    "description": "Whether to generate a soundtrack."
                  },
                  "audioLanguage": {
                    "default": null,
                    "enum": [
                      "none",
                      "chinese",
                      "english",
                      "japanese",
                      "korean",
                      null
                    ],
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Language of speech in the soundtrack. `none` for no speech."
                  }
                },
                "required": [
                  "model"
                ]
              },
              "example": {
                "model": "tbkv1.0.1",
                "prompt": "the girl walks through the city at night",
                "referenceImageMediaIds": [
                  "1943547603237249965"
                ],
                "ratio": "9:16",
                "duration": 5
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The task was created. Poll `GET /v2/task/{id}` with its `id`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Task"
                }
              }
            }
          },
          "400": {
            "description": "- `BAD_REQUEST` with `data.issues`: the body failed validation, e.g. too many references for `v4.0.3`.\n- `VALIDATION_ERROR`: the combination is not valid for this model, e.g. `mode: professional` on `v4.0.3`, or a video or audio reference for Vidu. `message` says which.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/CannotRun"
          },
          "422": {
            "description": "`INVALID_INPUT`: a reference file was refused before the task was charged. `message` reads `Invalid reference media: <reason>`, sometimes followed by the media ID in parentheses. Reasons include `too_many_reference_images`, `reference_video_not_supported` and `unsupported_reference_video_format`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/CreationFailed"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/gen-task/inpaint": {
      "post": {
        "tags": [
          "image"
        ],
        "summary": "Create an inpaint, outpaint or redraw task",
        "description": "Edits an existing image:\n\n- **Inpaint** (`fillType: inpaint`): redraws the masked area.\n- **Outpaint** (`fillType: outpaint`): extends the image beyond its edges. Place the original on a larger white canvas and send that as `baseImageMediaId`; the mask marks the new area.\n- **Redraw** (`fillType: inpaint`, no mask): redraws the whole image, keeping it closer to the original as `strength` goes down.\n\nA masked edit takes two extra images, always sent together:\n\n- `maskMediaId`: same size as the base image, white where to redraw and black where to keep.\n- `maskedImageMediaId`: the base image with the white area of the mask painted gray (`#808080`).\n\nThe output has the size of the masked image when a mask is sent, otherwise of the base image. Images are media IDs; see `POST /v2/media/image/upload-url`.\n\nUse `modelPreset: \"v1\"`. `GET /v2/gen-task/inpaint/constraints` lists the size limits and `sdeditPreset` names of a preset. Credits are charged when the task is created; the result is `outputs.mediaIds[0]` of `GET /v2/task/{id}`.\n",
        "operationId": "createInpaint",
        "x-codeSamples": [
          {
            "id": "curl",
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X POST https://api.pixai.art/v2/gen-task/inpaint \\\n  -H \"Authorization: Bearer $PIXAI_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"modelPreset\": \"v1\",\n    \"fillType\": \"inpaint\",\n    \"baseImageMediaId\": \"1943547603237249965\",\n    \"maskMediaId\": \"1943547603237249966\",\n    \"prompt\": \"red scarf\"\n  }'\n"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "modelPreset": {
                    "type": "string",
                    "minLength": 1,
                    "description": "The inpaint model. Use `v1`.",
                    "example": "v1"
                  },
                  "fillType": {
                    "enum": [
                      "inpaint",
                      "outpaint"
                    ],
                    "type": "string"
                  },
                  "baseImageMediaId": {
                    "type": "string",
                    "description": "Image media ID of the image to edit."
                  },
                  "maskMediaId": {
                    "type": "string",
                    "description": "Image media ID of the mask, white where to redraw and black where to keep. Send it with `maskedImageMediaId`, or omit both to redraw the whole image."
                  },
                  "maskedImageMediaId": {
                    "type": "string",
                    "description": "Image media ID of the base image with the mask's white area painted `#808080`. Send it with `maskMediaId`."
                  },
                  "prompt": {
                    "type": "string",
                    "maxLength": 10000,
                    "default": "",
                    "description": "What to draw in the edited area."
                  },
                  "strength": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 1,
                    "multipleOf": 0.01,
                    "description": "How far the result may depart from the original. Lower keeps it closer."
                  },
                  "seed": {
                    "type": "integer",
                    "description": "Random seed. Omit for a random one."
                  },
                  "promptHelper": {
                    "enum": [
                      "enable",
                      "disable",
                      "low",
                      "medium"
                    ],
                    "type": "string",
                    "default": "enable",
                    "description": "How much PixAI may expand the prompt."
                  },
                  "sdeditPreset": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64,
                    "description": "A redraw preset name from `GET /v2/gen-task/inpaint/constraints`. Sending one to a preset without any answers `SDEDIT_NOT_AVAILABLE`."
                  },
                  "sdedit": {
                    "type": "object",
                    "properties": {
                      "spectralScale": {
                        "type": "number",
                        "minimum": 0,
                        "maximum": 1
                      },
                      "hfsBlurSigma": {
                        "type": "number",
                        "minimum": 0,
                        "maximum": 32
                      },
                      "hfsEnd": {
                        "type": "number",
                        "minimum": 0,
                        "maximum": 1
                      },
                      "colorCorrection": {
                        "type": "boolean",
                        "description": "Match the colors of the original."
                      }
                    },
                    "description": "Fine-tuning for redraws. With `sdeditPreset`, only `colorCorrection` is taken from here."
                  }
                },
                "required": [
                  "baseImageMediaId",
                  "fillType",
                  "modelPreset"
                ]
              },
              "example": {
                "modelPreset": "v1",
                "fillType": "inpaint",
                "baseImageMediaId": "1943547603237249965",
                "maskMediaId": "1943547603237249966",
                "prompt": "red scarf"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The task was created. Poll `GET /v2/task/{id}` with its `id`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Task"
                }
              }
            }
          },
          "400": {
            "description": "- `INVALID_MODEL_PRESET`: unknown `modelPreset`.\n- `INVALID_MEDIA`: an image media ID does not exist or is not an image.\n- `INVALID_SDEDIT_PRESET`: unknown `sdeditPreset`.\n- `SDEDIT_NOT_AVAILABLE`: this `modelPreset` takes no `sdeditPreset` or `sdedit`.\n- `BAD_REQUEST` with `data.issues`: the body failed validation.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/CannotRun"
          },
          "500": {
            "$ref": "#/components/responses/CreationFailed"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/gen-task/inpaint/constraints": {
      "get": {
        "tags": [
          "image"
        ],
        "summary": "Get the limits of an inpaint preset",
        "description": "Returns the size limits and redraw presets of an inpaint `modelPreset`. An unknown preset answers `null` fields rather than an error. No authentication is needed.",
        "operationId": "getInpaintConstraints",
        "parameters": [
          {
            "name": "modelPreset",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "example": "v1"
          }
        ],
        "responses": {
          "200": {
            "description": "The preset's limits.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "modelPreset": {
                      "type": "string"
                    },
                    "constraints": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "Size limits for the image, or `null` if the preset sets none.",
                      "properties": {
                        "minWidth": {
                          "type": "integer"
                        },
                        "maxWidth": {
                          "type": "integer"
                        },
                        "minHeight": {
                          "type": "integer"
                        },
                        "maxHeight": {
                          "type": "integer"
                        },
                        "maxPixels": {
                          "type": "integer",
                          "description": "Maximum width × height."
                        },
                        "dimensionStep": {
                          "type": "integer",
                          "description": "Width and height must be multiples of this."
                        }
                      }
                    },
                    "sdeditPresets": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "Redraw presets by name, for `sdeditPreset`.",
                      "additionalProperties": {
                        "type": "object"
                      }
                    },
                    "defaultSdeditPreset": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {},
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/task/{id}": {
      "get": {
        "tags": [
          "task"
        ],
        "summary": "Get a task",
        "description": "Reads a task created by any v2 endpoint. Poll it every few seconds until `status` is `completed`, `failed` or `cancelled`.\n\nWhere the result is:\n\n- Images (`taskKind` `t2i`, `i2i`, `inpaint`): `outputs.mediaIds` and `outputs.mediaUrls`.\n- Videos (`taskKind` `i2v-inhouse`, `reference-video`): `outputs.videoMediaId`. Resolve it with `GET /v2/media/batch?ids=<videoMediaId>` and download `fileUrl`. `outputs.mediaIds` then holds only the poster image.\n\nGenerated media is not kept forever. Download results soon after they finish.\n",
        "operationId": "getTask",
        "x-codeSamples": [
          {
            "id": "curl",
            "lang": "bash",
            "label": "cURL",
            "source": "curl https://api.pixai.art/v2/task/1943547603237249965 \\\n  -H \"Authorization: Bearer $PIXAI_API_KEY\"\n"
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The task ID."
          },
          {
            "name": "with_parameters",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "true"
              ]
            },
            "description": "Send `true` to include the stored task parameters in `parameters`."
          }
        ],
        "responses": {
          "200": {
            "description": "The task.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Task"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "`NOT_FOUND`: no task with this ID is visible to you. A request without an API key gets this for every task.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/media/image/upload-url": {
      "post": {
        "tags": [
          "media"
        ],
        "summary": "Get an upload URL for an image",
        "description": "Step 1 of uploading an image you want to use as an input, for example a `contextImages` entry, a video frame or an inpaint base image.\n\n1. Call this endpoint to get `uploadUrl` and `externalId`.\n2. Send the raw image bytes to `uploadUrl` with an HTTP `PUT` and the file's real `Content-Type` (for example `image/png`). Do not use a multipart form.\n3. Call `POST /v2/media/image/register` with the `externalId`. Its `id` is the media ID you pass to other endpoints.\n",
        "operationId": "getImageUploadUrl",
        "x-codeSamples": [
          {
            "id": "curl",
            "lang": "bash",
            "label": "cURL",
            "source": "# 1. Get an upload URL\nUPLOAD=$(curl -s -X POST https://api.pixai.art/v2/media/image/upload-url \\\n  -H \"Authorization: Bearer $PIXAI_API_KEY\" \\\n  -H \"Content-Type: application/json\" -d '{}')\nURL=$(echo \"$UPLOAD\" | jq -r .uploadUrl)\nEXTERNAL_ID=$(echo \"$UPLOAD\" | jq -r .externalId)\n\n# 2. Upload the bytes\ncurl -X PUT \"$URL\" -H \"Content-Type: image/png\" --data-binary @input.png\n\n# 3. Register it and read the media ID\ncurl -s -X POST https://api.pixai.art/v2/media/image/register \\\n  -H \"Authorization: Bearer $PIXAI_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d \"{\\\"externalId\\\": \\\"$EXTERNAL_ID\\\"}\" | jq -r .id\n"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "isEphemeral": {
                    "type": "boolean",
                    "default": false,
                    "description": "Mark the file as a short-lived generation input. Ephemeral files are private, and their URLs are signed and expire."
                  }
                }
              },
              "example": {}
            }
          }
        },
        "responses": {
          "200": {
            "description": "The upload target.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UploadUrl"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/media/image/register": {
      "post": {
        "tags": [
          "media"
        ],
        "summary": "Register an uploaded image",
        "description": "Step 3 of uploading an image: turns the uploaded file into a media item. Call it after the `PUT` to `uploadUrl` has succeeded. The returned `id` is the media ID to pass to other endpoints.\n",
        "operationId": "registerImage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "externalId": {
                    "type": "string",
                    "format": "uuid",
                    "description": "The `externalId` returned by `POST /v2/media/image/upload-url`."
                  },
                  "isEphemeral": {
                    "type": "boolean",
                    "description": "Send the same value you sent to `upload-url`."
                  }
                },
                "required": [
                  "externalId"
                ]
              },
              "example": {
                "externalId": "3f2b8c1e-6a4d-4f6e-9b1a-2c7d5e8f9a01"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The registered image. `width` and `height` can be `0` until processing finishes a few seconds later; read them from `GET /v2/media/batch` if you need them.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Media"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/media/audio/upload-url": {
      "post": {
        "tags": [
          "media"
        ],
        "summary": "Get an upload URL for an audio file",
        "description": "Step 1 of uploading an audio clip for `referenceAudioMediaIds` of `POST /v2/reference-video/create`. The flow is the same as for images: `PUT` the bytes to `uploadUrl` with the file's `Content-Type` (`audio/mpeg` or `audio/wav`), then call `POST /v2/media/audio/register`.\n\nOnly WAV and MP3 are accepted, under 15 MiB per clip. Duration limits depend on the video model; they are checked when the video task is created, not at upload.\n",
        "operationId": "getAudioUploadUrl",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "isEphemeral": {
                    "type": "boolean",
                    "default": false,
                    "description": "Mark the file as a short-lived generation input. Ephemeral files are private, and their URLs are signed and expire."
                  }
                }
              },
              "example": {}
            }
          }
        },
        "responses": {
          "200": {
            "description": "The upload target.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UploadUrl"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/media/audio/register": {
      "post": {
        "tags": [
          "media"
        ],
        "summary": "Register an uploaded audio file",
        "description": "Step 3 of uploading an audio clip. The returned `id` is the media ID to pass in `referenceAudioMediaIds`.",
        "operationId": "registerAudio",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "externalId": {
                    "type": "string",
                    "minLength": 1,
                    "description": "The `externalId` returned by `POST /v2/media/audio/upload-url`."
                  }
                },
                "required": [
                  "externalId"
                ]
              },
              "example": {
                "externalId": "3f2b8c1e-6a4d-4f6e-9b1a-2c7d5e8f9a01"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The registered audio file.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "id"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "The media ID."
                    },
                    "fileUrl": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "URL of the file."
                    },
                    "duration": {
                      "type": [
                        "number",
                        "null"
                      ],
                      "description": "Length in seconds."
                    },
                    "size": {
                      "type": [
                        "number",
                        "null"
                      ],
                      "description": "Size in bytes."
                    },
                    "codec": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/media/{mediaId}/info": {
      "get": {
        "tags": [
          "media"
        ],
        "summary": "Inspect a video or audio file",
        "description": "Returns the duration, size, containers and codecs of a video or audio media item, so you can check a reference file against the model's limits before creating a reference video task.\n",
        "operationId": "getMediaInfo",
        "parameters": [
          {
            "name": "mediaId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "A video or audio media ID."
          }
        ],
        "responses": {
          "200": {
            "description": "The media metadata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "mediaId": {
                      "type": "string"
                    },
                    "durationSeconds": {
                      "type": [
                        "number",
                        "null"
                      ],
                      "description": "Length in seconds."
                    },
                    "sizeBytes": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Size in bytes, as a decimal string."
                    },
                    "containers": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Container formats, lowercase, e.g. `mp3` or `mov`."
                    },
                    "videoStreams": {
                      "type": "array",
                      "description": "One entry per video stream.",
                      "items": {
                        "type": "object",
                        "properties": {
                          "codec": {
                            "type": "string"
                          },
                          "width": {
                            "type": "integer"
                          },
                          "height": {
                            "type": "integer"
                          },
                          "averageFrameRate": {
                            "type": "number"
                          }
                        }
                      }
                    },
                    "audioStreams": {
                      "type": "array",
                      "description": "One entry per audio stream.",
                      "items": {
                        "type": "object",
                        "properties": {
                          "codec": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`NOT_VIDEO_OR_AUDIO`: the media is an image.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "`MEDIA_NOT_FOUND`: no media has this ID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/media/batch": {
      "get": {
        "tags": [
          "media"
        ],
        "summary": "Get media URLs by ID",
        "description": "Resolves up to 100 media IDs to their URLs, for example the `outputs.mediaIds` or `outputs.videoMediaId` of a finished task. No authentication is needed for public media.\n\nIDs that do not exist are left out, and the order of the result is not guaranteed, so match items by `id`.\n",
        "operationId": "batchGetMedia",
        "parameters": [
          {
            "name": "ids",
            "in": "query",
            "required": true,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              ],
              "description": "Media IDs to resolve (1–100). Accepts comma-separated (`?ids=1,2,3`), bracket notation (`?ids[]=1&ids[]=2`), or repeated (`?ids=1&ids=2`).",
              "type": "string"
            },
            "description": "Comma-separated media IDs, 1 to 100, e.g. `?ids=1,2,3`. Repeating the parameter (`?ids=1&ids=2`) also works."
          }
        ],
        "responses": {
          "200": {
            "description": "The media items found.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Media"
                  }
                }
              }
            }
          }
        },
        "security": [
          {},
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/generation-model/search": {
      "get": {
        "tags": [
          "model"
        ],
        "summary": "Search models and LoRAs",
        "description": "Searches the [PixAI Model Market](https://pixai.art/model). Use it to find a base model for `modelVersionId`, or LoRAs for `loras` of `POST /v2/image/create`.\n\nTo use a result, pass its `latestAvailableVersionId`, not its `id`: generation endpoints take **version** IDs. A LoRA's default trigger words are in `latestAvailableVersion.extra.triggerWords`.\n\nTo find LoRAs that work with a base model, send `usageType=LORA` and the base model's type in `loraBaseModelTypes` (the `type` of a model item, e.g. `SDXL_MODEL`).\n\nResults depend on who is asking: send your API key to get the same content rating as your account. Anonymous requests get stricter filtering.\n",
        "operationId": "searchGenerationModels",
        "parameters": [
          {
            "name": "usageType",
            "in": "query",
            "required": true,
            "schema": {
              "anyOf": [
                {
                  "const": "ALL"
                },
                {
                  "const": "MODEL"
                },
                {
                  "const": "LORA"
                }
              ],
              "type": "string",
              "enum": [
                "ALL",
                "MODEL",
                "LORA"
              ]
            },
            "description": "`MODEL` for base models, `LORA` for LoRAs, `ALL` for both."
          },
          {
            "name": "keyword",
            "in": "query",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 256
            },
            "description": "Free-text query. Results rank by relevance and popularity; without a keyword, by popularity."
          },
          {
            "name": "loraBaseModelTypes",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "With `usageType=LORA`: comma-separated base model types the LoRA must work with, e.g. `SDXL_MODEL`."
          },
          {
            "name": "baseModelIds",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "With `usageType=LORA`: comma-separated base model IDs the LoRA must work with."
          },
          {
            "name": "source",
            "in": "query",
            "schema": {
              "enum": [
                "ANY",
                "PIXAI",
                "EXTERNAL"
              ],
              "type": "string",
              "default": "ANY"
            },
            "description": "With `usageType=LORA`: `PIXAI` for LoRAs trained on PixAI, `EXTERNAL` for imported ones."
          },
          {
            "name": "baseModelType",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "With `usageType=MODEL`: comma-separated model types, e.g. `SDXL_MODEL,MMDIT26B_MODEL`."
          },
          {
            "name": "permittedUse",
            "in": "query",
            "schema": {
              "enum": [
                "COMMERCIAL",
                "PERSONAL"
              ],
              "type": "string"
            },
            "description": "Only models whose license allows this use."
          },
          {
            "name": "postedWithin",
            "in": "query",
            "schema": {
              "enum": [
                "today",
                "this-week",
                "this-month"
              ],
              "type": "string"
            }
          },
          {
            "name": "authorId",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Only models by this user."
          },
          {
            "name": "size",
            "in": "query",
            "schema": {
              "type": "integer",
              "maximum": 50,
              "exclusiveMinimum": 0,
              "default": 24,
              "minimum": 1
            },
            "description": "Page size."
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 10000,
              "default": 0
            },
            "description": "Number of results to skip. Pages can overlap slightly; de-duplicate by `id`."
          }
        ],
        "responses": {
          "200": {
            "description": "One page of results.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "hasMore"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ModelListItem"
                      }
                    },
                    "hasMore": {
                      "type": "boolean",
                      "description": "Whether another page may follow."
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {},
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/generation-model/{id}": {
      "get": {
        "tags": [
          "model"
        ],
        "summary": "Get a model or LoRA",
        "description": "Reads one model by its **model** ID (the `id` of a search result).",
        "operationId": "getGenerationModel",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The model ID."
          }
        ],
        "responses": {
          "200": {
            "description": "The model.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ModelListItem"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "triggerWords": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Default trigger words of the latest version."
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/ModelNotFound"
          }
        },
        "security": [
          {},
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/generation-model/{modelId}/versions": {
      "get": {
        "tags": [
          "model"
        ],
        "summary": "List the versions of a model",
        "description": "Lists a model's versions, newest first. Pass a version's `id` as `modelVersionId` or `loras[].modelId` to pin an older version.",
        "operationId": "listGenerationModelVersions",
        "parameters": [
          {
            "name": "modelId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The model ID."
          },
          {
            "name": "baseModelType",
            "in": "query",
            "schema": {
              "enum": [
                "ANY_LORA",
                "ANY_MODEL",
                "ANY_NON_SDXL_LORA",
                "ANY_NON_USER_LORA",
                "ANY_SDXL_LORA",
                "ANY_USER_LORA",
                "ANY_VAE",
                "CHAT",
                "DIT5A_MODEL_INTERNAL",
                "DIT7A_LORA",
                "DIT7A_MODEL",
                "DIT7A_VAE",
                "DIT7B_LORA",
                "DIT7B_MODEL",
                "DIT7B_VAE",
                "DIT7C_LORA",
                "DIT7C_MODEL",
                "DIT7C_VAE",
                "DIT7D_LORA",
                "DIT7D_MODEL",
                "DIT7D_VAE",
                "DIT7_LORA",
                "DIT7_MODEL",
                "DIT7_VAE",
                "DIT9_LORA",
                "DIT9_MODEL",
                "DIT9_VAE",
                "LORA",
                "MMDIT26A_MODEL",
                "MMDIT26B_MODEL",
                "MULTI_LORA",
                "SD3_MEDIUM_MODEL",
                "SDXL_LORA",
                "SDXL_MODEL",
                "SDXL_VAE",
                "SD_V1_MODEL",
                "UNKNOWN_LORA",
                "UNKNOWN_MODEL",
                "USER_DIT26A_MODEL",
                "USER_DIT26B_MODEL",
                "USER_LORA",
                "USER_MULTI_LORA",
                "USER_SDXL_LORA",
                "VAE",
                "VIDEO_MODEL",
                "VIDEO_MODEL_LORA",
                "Z_IMAGE_V1_MODEL"
              ],
              "type": "string"
            },
            "description": "Only versions for this base model type."
          }
        ],
        "responses": {
          "200": {
            "description": "The versions.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ModelVersion"
                  }
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/ModelNotFound"
          }
        },
        "security": [
          {},
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/generation-model-version/{id}": {
      "get": {
        "tags": [
          "model"
        ],
        "summary": "Get a model version",
        "description": "Reads one model version by its **version** ID, the ID that generation endpoints take. Use it to look up a LoRA's trigger words and base model before generating.",
        "operationId": "getGenerationModelVersion",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The model version ID."
          }
        ],
        "responses": {
          "200": {
            "description": "The version.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ModelVersion"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/ModelNotFound"
          }
        },
        "security": [
          {},
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/generation-model/{modelVersionId}/size-config": {
      "get": {
        "tags": [
          "model"
        ],
        "summary": "Get the sizes a model version accepts",
        "description": "Lists the sizes a model version accepts for `width`/`height` of `POST /v2/image/create`. Despite the path, the parameter is a **version** ID.\n\nA custom `width`/`height` must fall inside one range's `minWidth`–`maxWidth` and `minHeight`–`maxHeight` and be a multiple of its `step`. Presets are ready-made sizes and may lie outside those bounds. Entries whose `accessStatus` is `membership_required` need a higher membership tier than your account has.\n",
        "operationId": "getModelSizeConfig",
        "parameters": [
          {
            "name": "modelVersionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The model version ID."
          }
        ],
        "responses": {
          "200": {
            "description": "The size ranges.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ranges": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string"
                          },
                          "minWidth": {
                            "type": "integer"
                          },
                          "maxWidth": {
                            "type": "integer"
                          },
                          "minHeight": {
                            "type": "integer"
                          },
                          "maxHeight": {
                            "type": "integer"
                          },
                          "step": {
                            "type": "integer",
                            "description": "Width and height must be multiples of this."
                          },
                          "accessStatus": {
                            "type": "string",
                            "enum": [
                              "available",
                              "membership_required"
                            ]
                          },
                          "presets": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "string"
                                },
                                "width": {
                                  "type": "integer"
                                },
                                "height": {
                                  "type": "integer"
                                },
                                "ratioLabel": {
                                  "type": "string",
                                  "description": "e.g. `9:16`."
                                },
                                "accessStatus": {
                                  "type": "string",
                                  "enum": [
                                    "available",
                                    "membership_required"
                                  ]
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/ModelNotFound"
          }
        },
        "security": [
          {},
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/color-palettes/presets": {
      "get": {
        "tags": [
          "model"
        ],
        "summary": "List color palette presets",
        "description": "Lists PixAI's official color palettes for `colorPalette` of `POST /v2/image/create`. To use one, send the whole preset object with `\"source\": \"preset\"` added.\n\n`name` is localized: pass `?lang=ja` (or `ko`, `en`), or an `Accept-Language` header.\n",
        "operationId": "listColorPalettePresets",
        "responses": {
          "200": {
            "description": "The presets.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "palettes": {
                      "type": "array",
                      "items": {
                        "allOf": [
                          {
                            "$ref": "#/components/schemas/ColorPalette"
                          },
                          {
                            "type": "object",
                            "properties": {
                              "coverUrl": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "Preview image."
                              }
                            }
                          }
                        ]
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {},
          {
            "bearerAuth": []
          }
        ]
      }
    }
  },
  "components": {
    "schemas": {
      "CreateImageRequest": {
        "type": "object",
        "required": [
          "modelVersionId",
          "prompt"
        ],
        "additionalProperties": false,
        "properties": {
          "modelVersionId": {
            "type": "string",
            "minLength": 1,
            "description": "The unique identifier for the model version to use for generation. Preferred replacement for the deprecated `modelId` field.\n\nHow to find modelVersionId:\n1. Open the model page on PixAI.\n2. Click the model version you'd like to use.\n3. Copy the last path segment of the URL — that's the modelVersionId.\n\nExample URL: `https://pixai.art/model/<id>-<slug>/<modelVersionId>` → modelVersionId is `<modelVersionId>`.\n\n<img src=\"/images/find-modelid.png\" alt=\"Find modelVersionId\" />\n",
            "example": "1983308862240288769"
          },
          "modelId": {
            "type": "string",
            "minLength": 1,
            "x-fold": true,
            "x-badge": [
              {
                "type": "deprecated",
                "info": "Please use `modelVersionId` instead. `modelId` is ambiguous: it actually expects a model **version** ID instead of a model ID.\n"
              }
            ],
            "description": "The unique identifier for the model version to use for generation. Taken from the model version's URL on PixAI.\n\nHow to find modelId:\n1. Open the model page on PixAI.\n2. Click the model version you'd like to use.\n3. Copy the last path segment of the URL — that's the modelId.\n\nExample URL: `https://pixai.art/model/<id>-<slug>/<modelVersionId>` → modelId is `<modelVersionId>`.\n\n<img src=\"/images/find-modelid.png\" alt=\"Find modelId\" />\n",
            "example": "1983308862240288769"
          },
          "prompt": {
            "type": "string",
            "minLength": 1,
            "maxLength": 10000,
            "description": "The main prompt describing the content you want to generate. Up to 10,000 characters on Tsubaki.2 and Tsubaki.3, 4,096 on other models.\n",
            "example": "1girl, green hair, solo, standing"
          },
          "negativePrompt": {
            "type": "string",
            "maxLength": 4096,
            "description": "Text describing elements to avoid in the generated image.\n",
            "example": "nsfw, lowres, bad anatomy"
          },
          "aspectRatio": {
            "type": "string",
            "enum": [
              "1:1",
              "2:3",
              "3:2",
              "3:4",
              "4:3",
              "3:5",
              "5:3",
              "9:16",
              "16:9",
              "1:3",
              "3:1"
            ],
            "description": "The aspect ratio of the generated image. Defaults to `1:1` when neither `aspectRatio`/`size` nor `width`/`height` is sent. Cannot be combined with `width` and `height`.\n\nAvailable ratios: `1:1`, `2:3`, `3:2`, `3:4`, `4:3`, `3:5`, `5:3`, `9:16`, `16:9`, `1:3`, `3:1`\n\nAll ratios are supported across all model types (SDXL, DiT, Tsubaki.2).\n\nSee [Supported Resolutions](/en/docs/references/supported-resolutions) for the full resolution mapping per size tier.\n",
            "example": "1:1"
          },
          "size": {
            "type": "string",
            "enum": [
              "1k",
              "1.5k"
            ],
            "description": "The output resolution tier. Defaults to `1k` when neither `aspectRatio`/`size` nor `width`/`height` is sent. Cannot be combined with `width` and `height`. The longest edge is capped at 1536 px for `1.5k`.\n- `1k`: ~1 megapixel (e.g. 1024×1024 at 1:1).\n- `1.5k`: ~2.36 megapixels (e.g. 1536×1536 at 1:1).\n\nSee [Supported Resolutions](/en/docs/references/supported-resolutions) for the full mapping table.\n",
            "example": "1k"
          },
          "width": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10240,
            "description": "Exact output width in pixels, for sizes the `aspectRatio`/`size` presets do not cover (e.g. Tsubaki.3's larger outputs). Send together with `height` and without `aspectRatio` and `size`.\n\nThe size must fall within one of the model's size ranges and be a multiple of its `step`. Read them from `GET https://api.pixai.art/v2/generation-model/{modelVersionId}/size-config` (no authentication needed): each entry of `ranges` gives `minWidth`/`maxWidth`, `minHeight`/`maxHeight` and `step`, plus ready-made `presets`. A size outside every range returns `400 IMAGE_SIZE_NOT_ALLOWED`.\n",
            "example": 1024
          },
          "height": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10240,
            "description": "Exact output height in pixels. Send together with `width`; see `width` for the allowed sizes.\n",
            "example": 1024
          },
          "mode": {
            "type": "string",
            "x-badge": [
              {
                "type": "tsubaki2",
                "info": "Only available for the **Tsubaki.2** and **Tsubaki.3** model families. Rejected with `400 INVALID_ARGUMENT` on other model types.\n"
              }
            ],
            "enum": [
              "lite",
              "standard",
              "pro",
              "ultra"
            ],
            "description": "The inference profile controlling generation quality and speed.\n- `lite`: Fastest, basic quality.\n- `standard`: Balanced speed and quality.\n- `pro`: Higher quality, slower.\n- `ultra`: Highest quality, slowest.\n\nNot every mode is offered on every model or plan; an unavailable mode returns `422 INVALID_INPUT` naming the mode.\n",
            "example": "standard"
          },
          "style": {
            "x-badge": [
              {
                "type": "tsubaki2",
                "info": "Only available for the **Tsubaki.2** and **Tsubaki.3** model families. Silently ignored for other model types.\n"
              }
            ],
            "description": "The style to apply during image generation. Can be a named preset or a custom style string.\n",
            "oneOf": [
              {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "type",
                  "key"
                ],
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "preset"
                    ]
                  },
                  "key": {
                    "type": "string",
                    "enum": [
                      "anime-watercolor-impasto",
                      "art-crayon",
                      "bold-line-soft-color",
                      "chibi",
                      "classic-japanese",
                      "clean-flat-illustration",
                      "colored-pencil-grain",
                      "cool-warm-oil-contrast",
                      "desaturated-cool",
                      "flat-anime-pastel",
                      "glossy-glass-anime",
                      "grey-blocks-lineless",
                      "hard-line-monochrome-accent",
                      "high-contrast-retro-vivid",
                      "holographic",
                      "korean-style",
                      "lineart-watercolor-airy",
                      "low-saturation-expressive-eyes",
                      "lucid-dreamy",
                      "luminous-retro-impasto",
                      "minimal-flat-color",
                      "modern-oil-glamour",
                      "moe-pastel",
                      "oil-watercolor-blend",
                      "painterly-doodle",
                      "paper-watercolor",
                      "pencil-sketch",
                      "poster-graffiti",
                      "retro-comic-fusion",
                      "retro-oil-glamour",
                      "retro-tv-anime",
                      "semi-realistic",
                      "stable-vaporwave",
                      "tinted-sketch",
                      "vintage-collage"
                    ],
                    "description": "A named preset style key. Available presets:\n- `anime-watercolor-impasto` — Watercolor Glow\n- `art-crayon` — Art Crayon\n- `bold-line-soft-color` — Glint & Gloom\n- `chibi` — Chibi\n- `classic-japanese` — Classic Anime\n- `clean-flat-illustration` — Clean Flat-Illustration\n- `colored-pencil-grain` — Chromatic Pencil\n- `cool-warm-oil-contrast` — Seasonal Glow\n- `desaturated-cool` — Cool Softlight\n- `flat-anime-pastel` — Pastel Flat\n- `glossy-glass-anime` — Glassy Anime\n- `grey-blocks-lineless` — Grey Wash\n- `hard-line-monochrome-accent` — Sharp Ink\n- `high-contrast-retro-vivid` — Neon Vivid\n- `holographic` — Hyper Pop\n- `korean-style` — Polished Manhwa\n- `lineart-watercolor-airy` — Luminous Wash\n- `low-saturation-expressive-eyes` — Muted & Transparent\n- `lucid-dreamy` — Lucid Dreamy\n- `luminous-retro-impasto` — Luminous Impasto\n- `minimal-flat-color` — Minimal Flat\n- `modern-oil-glamour` — Modern Glam Anime\n- `moe-pastel` — Moe Pastel\n- `oil-watercolor-blend` — Water-Infused Oil\n- `painterly-doodle` — Tender Brushstroke\n- `paper-watercolor` — Soft Aqueous\n- `pencil-sketch` — Pencil Sketch\n- `poster-graffiti` — Neon Poster\n- `retro-comic-fusion` — Retro Fusion\n- `retro-oil-glamour` — Retro Glam Anime\n- `retro-tv-anime` — 90s Retro-Cell\n- `semi-realistic` — Semi-Real\n- `stable-vaporwave` — Neon Vaporwave\n- `tinted-sketch` — Tinted Sketch\n- `vintage-collage` — Vintage Collage\n"
                  }
                }
              },
              {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "type",
                  "custom"
                ],
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "custom"
                    ]
                  },
                  "custom": {
                    "type": "string",
                    "description": "A raw style prompt string injected as a prefix to the generation prompt. This is an advanced option — incorrect values may degrade output quality.\n"
                  }
                }
              }
            ],
            "discriminator": {
              "propertyName": "type"
            }
          },
          "loras": {
            "type": "array",
            "maxItems": 15,
            "description": "Apply one or more LoRA adapters to fine-tune output style or content. How many can be combined depends on your plan (3 without a membership, up to 15); more returns `403 LORA_NUM_EXCEEDED`.\n\nUse a LoRA made for the same base model as the generation model: a LoRA's page on PixAI shows its base model.\n\nHow to find LoRA modelId:\n1. Open the LoRA model page on PixAI.\n2. Click the LoRA version you'd like to use.\n3. Copy the last path segment of the URL — that's the LoRA version ID.\n\nExample URL: `https://pixai.art/model/<loraModelId>/<loraVersionId>` → LoRA version ID is `<loraVersionId>`.\n",
            "items": {
              "$ref": "#/components/schemas/LoraItem"
            }
          },
          "contextImages": {
            "type": "array",
            "maxItems": 3,
            "x-badge": [
              {
                "type": "tsubaki3",
                "info": "Only available for **Tsubaki.3** (`modelVersionId` `2024383379556065549`). Other models return `400 BAD_REQUEST` (\"This feature is not yet supported for this model\").\n"
              }
            ],
            "description": "Reference images for in-context generation, e.g. keeping a character consistent or taking a pose from another image.\n\nEach item is a media ID: an ID from a finished task's `outputs.mediaIds`, or one returned by [Upload an image or video](/en/docs/api/media/uploadMedia). Each image must be under 4000 px on both sides.\n",
            "items": {
              "type": "string",
              "description": "A media ID."
            },
            "example": [
              "1943547603237249965"
            ]
          },
          "seed": {
            "type": "integer",
            "description": "Random seed for reproducible generation. Omit to use a randomly generated seed.\n",
            "example": 42
          },
          "batchSize": {
            "type": "integer",
            "enum": [
              1,
              4
            ],
            "default": 1,
            "description": "Number of images to generate in one task. Supported values are `1` and `4`. Defaults to `1`.\n",
            "example": 4
          },
          "sampling": {
            "type": "object",
            "x-badge": [
              {
                "type": "sdxl-sdv1",
                "info": "Only available for **SDXL** and **SD v1** model families.\n"
              }
            ],
            "description": "Advanced sampling parameters for fine-tuning the diffusion process. All fields are optional — omitting a field uses the model's default.\n\nRefer to the [Models](/en/docs/references/models) page for allowed sampling methods per model.\n",
            "additionalProperties": false,
            "properties": {
              "method": {
                "type": "string",
                "description": "Sampler algorithm used during generation. Supported methods vary by model — see the [Models](/en/docs/references/models) page.\n",
                "example": "DPM++ 2M Karras"
              },
              "steps": {
                "type": "integer",
                "minimum": 1,
                "maximum": 100,
                "description": "Number of diffusion steps. Higher values can improve detail but increase generation time and cost.\n",
                "example": 25
              },
              "cfgScale": {
                "type": "number",
                "description": "Classifier-Free Guidance (CFG) scale. Controls the balance between prompt adherence and creative freedom. Higher values follow the prompt more strictly.\n",
                "example": 7
              }
            }
          },
          "promptHelper": {
            "type": "string",
            "enum": [
              "enable",
              "disable",
              "low",
              "medium"
            ],
            "default": "enable",
            "description": "Whether to use the built-in prompt helper to enhance the prompt before generation.\n- `enable`: Automatically enhance the prompt (default).\n- `disable`: Use the prompt as-is.\n- `low` / `medium`: How freely the helper rewrites the prompt, on Tsubaki.2 and Tsubaki.3. Other models treat both as `enable`.\n",
            "x-callout": "Enabling this field will incur additional charges."
          },
          "callbackUrl": {
            "type": "string",
            "format": "uri",
            "description": "A publicly accessible URL to receive task status updates via POST request (webhook).\n\nWe will send a POST request to the callback URL when the task status changes.\n",
            "example": "https://your-server.example.com/webhook"
          },
          "colorPalette": {
            "x-badge": [
              {
                "type": "tsubaki3",
                "info": "Only available for **Tsubaki.3** (`modelVersionId` `2024383379556065549`). Other models return `400 BAD_REQUEST` (\"This feature is not yet supported for this model\").\n"
              }
            ],
            "description": "Steer the colors of the image. Take a preset from `GET /v2/color-palettes/presets` and send it whole, with `\"source\": \"preset\"` added.\n",
            "allOf": [
              {
                "$ref": "#/components/schemas/ColorPalette"
              },
              {
                "type": "object",
                "required": [
                  "source"
                ],
                "properties": {
                  "source": {
                    "type": "string",
                    "enum": [
                      "preset",
                      "user"
                    ]
                  }
                }
              }
            ]
          }
        }
      },
      "LoraItem": {
        "type": "object",
        "required": [
          "modelId"
        ],
        "additionalProperties": false,
        "properties": {
          "modelId": {
            "type": "string",
            "description": "The LoRA model version ID from the PixAI Model Market.",
            "example": "1744880666293972790"
          },
          "weight": {
            "type": "number",
            "minimum": 0,
            "maximum": 1,
            "default": 1,
            "description": "The influence weight of the LoRA adapter. Range 0.0–1.0.",
            "example": 0.7
          },
          "triggerWords": {
            "type": "string",
            "description": "Custom trigger words for this LoRA. If omitted, the LoRA's default trigger words are added automatically; an empty string adds none.\n"
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "code",
          "status",
          "message"
        ],
        "properties": {
          "code": {
            "type": "string",
            "description": "Machine-readable error code, e.g. `BAD_REQUEST` or `INSUFFICIENT_BALANCE`. Branch on this, not on `message`."
          },
          "status": {
            "type": "integer",
            "description": "The HTTP status code."
          },
          "message": {
            "type": "string",
            "description": "Human-readable detail, often naming the field or value at fault."
          },
          "data": {
            "type": "object",
            "description": "Code-specific detail, e.g. `issues` for validation errors or `reason` for `IMAGE_SIZE_NOT_ALLOWED`."
          },
          "defined": {
            "type": "boolean",
            "description": "Whether `code` is one this endpoint declares."
          }
        }
      },
      "Task": {
        "type": "object",
        "required": [
          "id",
          "status",
          "createdAt",
          "updatedAt"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "The unique identifier for the task."
          },
          "status": {
            "type": "string",
            "description": "The current status of the task.",
            "enum": [
              "waiting",
              "running",
              "completed",
              "cancelled",
              "failed"
            ]
          },
          "createdAt": {
            "type": "string",
            "description": "The time the task was created.",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "description": "The time the task was last updated.",
            "format": "date-time"
          },
          "startedAt": {
            "type": "string",
            "description": "The time the task started running.",
            "format": "date-time"
          },
          "endAt": {
            "type": "string",
            "description": "The time the task finished.",
            "format": "date-time"
          },
          "taskKind": {
            "type": "string",
            "description": "What the task makes: `t2i` or `i2i` for images, `inpaint` for `POST /v2/gen-task/inpaint`, `i2v-inhouse` for `POST /v2/frame-video/create`, `reference-video` for `POST /v2/reference-video/create`.\n"
          },
          "paidQuota": {
            "type": "integer",
            "description": "Credits charged for the task."
          },
          "taskStatusMsgI18n": {
            "type": "object",
            "description": "Why a `failed` task failed.",
            "properties": {
              "key": {
                "type": "string",
                "description": "A stable message key."
              },
              "defaultMessage": {
                "type": "string",
                "description": "The message in English."
              }
            }
          },
          "outputs": {
            "type": "object",
            "description": "The outputs produced by the task.",
            "properties": {
              "videoMediaId": {
                "type": "string",
                "description": "For video tasks, the media ID of the video. Resolve it with `GET /v2/media/batch?ids=<videoMediaId>` and download `fileUrl`. `mediaIds` then holds only the poster image.\n"
              },
              "seed": {
                "type": "string",
                "description": "The seed used, as a decimal string."
              },
              "mediaIds": {
                "type": "array",
                "description": "Media IDs of the generated images. Use these IDs to fetch detailed information about each generated image.\n\nGenerated images are not permanently retained — retrieve them as soon as possible.\n",
                "items": {
                  "type": "string",
                  "description": "The unique identifier for a generated media item."
                }
              },
              "mediaUrls": {
                "type": "array",
                "description": "Public URLs of the generated images.\n\nGenerated images are not permanently retained — retrieve them as soon as possible. If an image is unavailable, its entry may be `null`.\n",
                "items": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "The URL of the media item, or null if unavailable."
                }
              }
            }
          }
        }
      },
      "UploadUrlRequest": {
        "type": "object",
        "properties": {
          "isEphemeral": {
            "type": "boolean",
            "default": false,
            "description": "Mark the file as a short-lived generation input. Ephemeral files are private, and their URLs are signed and expire."
          }
        }
      },
      "UploadUrl": {
        "type": "object",
        "required": [
          "uploadUrl",
          "externalId"
        ],
        "properties": {
          "uploadUrl": {
            "type": "string",
            "description": "Presigned URL. `PUT` the raw file bytes to it with the file's `Content-Type`."
          },
          "externalId": {
            "type": "string",
            "description": "Pass this to the matching `register` endpoint after the upload."
          }
        }
      },
      "Media": {
        "type": "object",
        "required": [
          "id",
          "type"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "The media ID."
          },
          "type": {
            "type": "string",
            "enum": [
              "IMAGE",
              "VIDEO",
              "AUDIO"
            ]
          },
          "urls": {
            "type": "array",
            "description": "Image URLs by variant. `PUBLIC` is the full image.",
            "items": {
              "type": "object",
              "properties": {
                "variant": {
                  "type": "string",
                  "enum": [
                    "PUBLIC",
                    "THUMBNAIL",
                    "STILL_THUMBNAIL"
                  ]
                },
                "url": {
                  "type": "string"
                }
              }
            }
          },
          "width": {
            "type": [
              "number",
              "null"
            ]
          },
          "height": {
            "type": [
              "number",
              "null"
            ]
          },
          "fileUrl": {
            "type": [
              "string",
              "null"
            ],
            "description": "URL of the file itself, e.g. the MP4 of a video."
          },
          "hlsUrl": {
            "type": [
              "string",
              "null"
            ],
            "description": "HLS stream of a video. Often `null` for generated videos; use `fileUrl`."
          },
          "thumbnailUrl": {
            "type": [
              "string",
              "null"
            ],
            "description": "Poster image of a video. Often `null` for generated videos; the task's `outputs.mediaIds` holds the poster."
          },
          "duration": {
            "type": [
              "number",
              "null"
            ],
            "description": "Length of a video or audio file in seconds. Can be `0` for generated videos."
          }
        }
      },
      "ModelVersion": {
        "type": "object",
        "required": [
          "id",
          "modelId"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "The version ID. Pass it as `modelVersionId`, or as `loras[].modelId` for a LoRA."
          },
          "modelId": {
            "type": "string",
            "description": "The ID of the model this version belongs to."
          },
          "modelTitle": {
            "type": "string"
          },
          "name": {
            "type": "string",
            "description": "Version name."
          },
          "modelType": {
            "type": [
              "string",
              "null"
            ],
            "description": "e.g. `SDXL_MODEL`, `MMDIT26B_MODEL` or `SDXL_LORA`."
          },
          "loraBaseModelType": {
            "type": [
              "string",
              "null"
            ],
            "description": "For a LoRA, the base model type it was trained for. Use a base model of this type."
          },
          "loraBaseModelId": {
            "type": [
              "string",
              "null"
            ],
            "description": "For a LoRA, the base model it was trained on."
          },
          "status": {
            "type": [
              "string",
              "null"
            ],
            "description": "Only `available` versions can be used for generation."
          },
          "extra": {
            "type": "object",
            "description": "Version details. `triggerWords` holds the default trigger words of a LoRA.",
            "properties": {
              "triggerWords": {
                "type": "string"
              }
            }
          },
          "mediaId": {
            "type": [
              "string",
              "null"
            ],
            "description": "Cover image media ID."
          }
        }
      },
      "ModelListItem": {
        "type": "object",
        "required": [
          "id",
          "title",
          "type"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "The model ID. Generation endpoints take a version ID instead; use `latestAvailableVersionId`."
          },
          "title": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "description": "e.g. `SDXL_MODEL`, `MMDIT26B_MODEL` or `SDXL_LORA`."
          },
          "category": {
            "type": [
              "string",
              "null"
            ]
          },
          "loraBaseModelTypes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "For a LoRA, the base model types it works with."
          },
          "permittedUse": {
            "type": "string",
            "enum": [
              "PERSONAL",
              "COMMERCIAL"
            ],
            "description": "What the license allows."
          },
          "mediaId": {
            "type": [
              "string",
              "null"
            ],
            "description": "Cover image media ID."
          },
          "latestAvailableVersionId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The newest usable version. Pass it as `modelVersionId`, or as `loras[].modelId` for a LoRA."
          },
          "latestAvailableVersion": {
            "type": [
              "object",
              "null"
            ],
            "description": "The newest usable version.",
            "properties": {
              "id": {
                "type": "string",
                "description": "Same as `latestAvailableVersionId`."
              },
              "name": {
                "type": "string"
              },
              "modelType": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "loraBaseModelType": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "For a LoRA, the base model type it was trained for."
              },
              "extra": {
                "type": "object",
                "description": "`triggerWords` holds the default trigger words of a LoRA.",
                "properties": {
                  "triggerWords": {
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      },
      "ColorPalette": {
        "type": "object",
        "required": [
          "id",
          "name",
          "palette",
          "createdAt",
          "updatedAt"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "palette": {
            "type": "object",
            "description": "Colors for the whole image and, optionally, the background and characters. `overall` or `background` is required.",
            "properties": {
              "overall": {
                "$ref": "#/components/schemas/PaletteColors"
              },
              "background": {
                "$ref": "#/components/schemas/PaletteColors"
              },
              "character": {
                "$ref": "#/components/schemas/PaletteColors"
              }
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "PaletteColors": {
        "type": "object",
        "required": [
          "colors"
        ],
        "properties": {
          "colors": {
            "type": "array",
            "minItems": 1,
            "maxItems": 12,
            "items": {
              "type": "object",
              "required": [
                "hex",
                "ratio"
              ],
              "properties": {
                "hex": {
                  "type": "string",
                  "description": "`#RRGGBB`."
                },
                "ratio": {
                  "type": "number",
                  "minimum": 0,
                  "maximum": 100,
                  "description": "Share of the image, in percent."
                }
              }
            }
          }
        }
      }
    },
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "API-Key",
        "description": "In all requests that require authentication\n"
      }
    },
    "headers": {
      "X-Trace-Id": {
        "description": "A unique identifier for the request. Useful for debugging and tracing.",
        "schema": {
          "type": "string"
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "`UNAUTHORIZED`: no API key was sent. An invalid, revoked or expired key answers `{\"message\": \"invalid token\", \"code\": 40100001}` instead, with a numeric `code`.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "CannotRun": {
        "description": "The account cannot run this task right now. `code` says why:\n\n- `INSUFFICIENT_BALANCE`: not enough credits for the task.\n- `WAITING_NUM_EXCEEDED`: too many of your tasks are still `waiting` (`data.currentWaitingTasks`). Wait for some to start before submitting more.\n- `REQUIRE_MEMBERSHIP`: the feature needs a PixAI membership (image-to-video).\n- `NSFW_PROMPTS_DETECTED`: the prompt was refused because the account is in safe mode.\n",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "CreationFailed": {
        "description": "`CREATION_FAILED`: the task could not be created. Retry with exponential backoff.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "ModelNotFound": {
        "description": "`NOT_FOUND`: no such model or version, or it is private. The two cases are not told apart.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    }
  }
}