{
  "openapi": "3.1.0",
  "info": {
    "title": "Fittins AI API",
    "version": "1.0.0",
    "summary": "Premium on-model fashion photos and videos from your product photos.",
    "description": "The Fittins AI API creates studio-quality on-model photos of your products up to 8K and fashion videos up to 4K. Included in the Pro, Business, Enterprise plans; uses the same credits as fittins.ai. Docs: https://fittins.ai/docs/api",
    "contact": {
      "name": "Fittins AI",
      "url": "https://fittins.ai/support",
      "email": "support@fittins.ai"
    },
    "termsOfService": "https://fittins.ai/terms"
  },
  "servers": [
    {
      "url": "https://api.fittins.ai/v1"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Images"
    },
    {
      "name": "Videos"
    },
    {
      "name": "Generations"
    },
    {
      "name": "Uploads"
    },
    {
      "name": "Files"
    },
    {
      "name": "Models and locations"
    },
    {
      "name": "Webhooks"
    },
    {
      "name": "Account"
    }
  ],
  "paths": {
    "/images": {
      "post": {
        "operationId": "createImage",
        "summary": "Create an on-model photo",
        "tags": [
          "Images"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{8,64}$"
            },
            "description": "Retry safely: the same key and body return the same generation for 24 hours."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "product_images",
                  "model_id",
                  "prompt"
                ],
                "properties": {
                  "product_images": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 3,
                    "description": "1 to 3 photos of the product: { \"url\": \"https://…\" } or { \"upload_id\": \"upl_…\" }. Flat lays, hanger and ghost-mannequin shots and packshots all work. Different angles of one item are fine; another colour of the same item goes in a separate generation.",
                    "items": {
                      "$ref": "#/components/schemas/ImageRef"
                    }
                  },
                  "model_id": {
                    "type": "string",
                    "pattern": "^mdl_(lib|own)_",
                    "description": "A library model (mdl_lib_…) or one of your custom models (mdl_own_…). List them with GET /v1/models."
                  },
                  "prompt": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 1500,
                    "description": "3 to 1500 characters: pose, framing, light, mood, setting."
                  },
                  "location_id": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^loc_(lib|own)_",
                    "description": "A library or custom location (loc_lib_…, loc_own_…). Adds 10 credits. Leave it out to describe the setting in the prompt."
                  },
                  "aspect_ratio": {
                    "type": "string",
                    "enum": [
                      "1:1",
                      "9:16",
                      "16:9",
                      "3:4",
                      "4:3",
                      "3:2",
                      "2:3"
                    ],
                    "default": "1:1"
                  },
                  "tier": {
                    "type": "string",
                    "enum": [
                      "turbo",
                      "default",
                      "premium",
                      "ultra"
                    ],
                    "default": "default",
                    "description": "turbo · default · premium (Kickstart plan and up) · ultra (Business and up). With location_id, the photo costs 10 credits more."
                  },
                  "quality": {
                    "type": "string",
                    "enum": [
                      "1k",
                      "2k",
                      "4k",
                      "8k"
                    ],
                    "default": "1k",
                    "description": "1k · 2k · 4k · 8k. 2K, 4K and 8K are upscaled from the generated photo."
                  },
                  "metadata": {
                    "type": "object",
                    "maxProperties": 20,
                    "additionalProperties": {
                      "type": "string",
                      "maxLength": 500
                    },
                    "description": "Your own references, returned unchanged: up to 20 keys (letters, digits, - or _, up to 40 characters), values up to 500 characters. metadata.sku (or reference) is shown on the result in My Generations."
                  },
                  "webhook_url": {
                    "type": "string",
                    "format": "uri",
                    "pattern": "^https://",
                    "maxLength": 2048,
                    "description": "An https address we call once when this generation ends: succeeded, failed or canceled. The call carries only its id, type and status, not the result, and isn't signed, so read the result with GET /v1/generations/{id}. See Webhooks."
                  }
                }
              },
              "example": {
                "product_images": [
                  {
                    "url": "https://cdn.mystore.com/p/tshirt-red-front.jpg"
                  }
                ],
                "model_id": "mdl_lib_DM5rQvl3KtlR7nqumd6I",
                "prompt": "full body, plain light grey background, soft studio light, front view",
                "aspect_ratio": "3:4",
                "tier": "default",
                "quality": "2k",
                "metadata": {
                  "sku": "TSHIRT-RED-M"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The generation an earlier request with the same Idempotency-Key made.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Generation"
                }
              }
            }
          },
          "202": {
            "description": "Accepted and queued.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Generation"
                },
                "example": {
                  "id": "gen_7Hq2Mz9TkQ4x1bVnR8sL",
                  "object": "generation",
                  "type": "image",
                  "status": "queued",
                  "created_at": "2026-11-04T17:02:11.000Z",
                  "started_at": null,
                  "completed_at": null,
                  "input": {
                    "model_id": "mdl_lib_DM5rQvl3KtlR7nqumd6I",
                    "product_images": [
                      {
                        "url": "https://cdn.mystore.com/p/tshirt-red-front.jpg"
                      }
                    ],
                    "location_id": null,
                    "prompt": "full body, plain light grey background, soft studio light, front view",
                    "aspect_ratio": "3:4",
                    "tier": "default",
                    "quality": "2k"
                  },
                  "output": null,
                  "credits": {
                    "estimated": 50,
                    "charged": 0
                  },
                  "project_id": null,
                  "metadata": {
                    "sku": "TSHIRT-RED-M"
                  },
                  "error": null,
                  "livemode": true
                }
              }
            }
          },
          "400": {
            "description": "invalid_request or invalid_image; param names the field.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked API key (invalid_api_key).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "insufficient_credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The plan does not include the API or this option (api_not_in_plan, not_in_plan, storage_full).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown model, location or upload.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "idempotency_conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests (rate_limited) or generations (concurrency_limit). See Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/videos": {
      "post": {
        "operationId": "createVideo",
        "summary": "Create a fashion video",
        "tags": [
          "Videos"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{8,64}$"
            },
            "description": "Retry safely: the same key and body return the same generation for 24 hours."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "product_images",
                  "model_id",
                  "prompt"
                ],
                "properties": {
                  "product_images": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 3,
                    "description": "1 to 3 photos of the product: { \"url\": \"https://…\" } or { \"upload_id\": \"upl_…\" }. Flat lays, hanger and ghost-mannequin shots and packshots all work. Different angles of one item are fine; another colour of the same item goes in a separate generation.",
                    "items": {
                      "$ref": "#/components/schemas/ImageRef"
                    }
                  },
                  "model_id": {
                    "type": "string",
                    "pattern": "^mdl_(lib|own)_",
                    "description": "A library model (mdl_lib_…) or one of your custom models (mdl_own_…). List them with GET /v1/models."
                  },
                  "prompt": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 1500,
                    "description": "3 to 1500 characters: the motion and setting, for example \"model walks towards the camera\"."
                  },
                  "location_id": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^loc_(lib|own)_",
                    "description": "A library or custom location (loc_lib_…, loc_own_…). Adds 10 credits. Leave it out to describe the setting in the prompt."
                  },
                  "aspect_ratio": {
                    "type": "string",
                    "enum": [
                      "1:1",
                      "16:9",
                      "9:16"
                    ],
                    "default": "9:16"
                  },
                  "duration_seconds": {
                    "type": "integer",
                    "enum": [
                      5,
                      10
                    ],
                    "default": 5
                  },
                  "tier": {
                    "type": "string",
                    "enum": [
                      "turbo",
                      "default",
                      "premium",
                      "ultra"
                    ],
                    "default": "default",
                    "description": "turbo · default · premium · ultra (Business and up)."
                  },
                  "quality": {
                    "type": "string",
                    "enum": [
                      "1k",
                      "2k",
                      "4k"
                    ],
                    "default": "1k"
                  },
                  "sound": {
                    "type": "boolean",
                    "default": false,
                    "description": "AI sound effects (ambient and foley, not voiceover or music). 10 credits."
                  },
                  "metadata": {
                    "type": "object",
                    "maxProperties": 20,
                    "additionalProperties": {
                      "type": "string",
                      "maxLength": 500
                    },
                    "description": "Your own references, returned unchanged: up to 20 keys (letters, digits, - or _, up to 40 characters), values up to 500 characters. metadata.sku (or reference) is shown on the result in My Generations."
                  },
                  "webhook_url": {
                    "type": "string",
                    "format": "uri",
                    "pattern": "^https://",
                    "maxLength": 2048,
                    "description": "An https address we call once when this generation ends: succeeded, failed or canceled. The call carries only its id, type and status, not the result, and isn't signed, so read the result with GET /v1/generations/{id}. See Webhooks."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The generation an earlier request with the same Idempotency-Key made.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Generation"
                }
              }
            }
          },
          "202": {
            "description": "Accepted and queued.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Generation"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request or invalid_image; param names the field.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked API key (invalid_api_key).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "insufficient_credits or spending_cap_reached",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The plan does not include the API or this option (api_not_in_plan, not_in_plan, storage_full).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown model, location or upload.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "idempotency_conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests (rate_limited) or generations (concurrency_limit). See Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/generations": {
      "get": {
        "operationId": "listGenerations",
        "summary": "List generations",
        "tags": [
          "Generations"
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "queued",
                "running",
                "succeeded",
                "failed",
                "canceled"
              ]
            }
          },
          {
            "name": "type",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "image",
                "video",
                "model",
                "location"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Newest first.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "properties": {
                    "object": {
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Generation"
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked API key (invalid_api_key).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The plan does not include the API or this option (api_not_in_plan, not_in_plan, storage_full).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests (rate_limited) or generations (concurrency_limit). See Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/generations/{id}": {
      "get": {
        "operationId": "getGeneration",
        "summary": "Get a generation",
        "tags": [
          "Generations"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "gen_…"
          }
        ],
        "responses": {
          "200": {
            "description": "The generation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Generation"
                },
                "example": {
                  "id": "gen_7Hq2Mz9TkQ4x1bVnR8sL",
                  "object": "generation",
                  "type": "image",
                  "status": "succeeded",
                  "created_at": "2026-11-04T17:02:11.000Z",
                  "started_at": "2026-11-04T17:02:13.000Z",
                  "completed_at": "2026-11-04T17:03:02.000Z",
                  "input": {
                    "model_id": "mdl_lib_DM5rQvl3KtlR7nqumd6I",
                    "product_images": [
                      {
                        "url": "https://cdn.mystore.com/p/tshirt-red-front.jpg"
                      }
                    ],
                    "location_id": null,
                    "prompt": "full body, plain light grey background, soft studio light, front view",
                    "aspect_ratio": "3:4",
                    "tier": "default",
                    "quality": "2k"
                  },
                  "output": {
                    "file_id": "file_3f9c2a7b1e0d4c6a8b2f5e1d",
                    "url": "https://api.fittins.ai/v1/files/file_3f9c2a7b1e0d4c6a8b2f5e1d/content?expires=1793905382&sig=Jk2v…",
                    "url_expires_at": "2026-11-05T17:03:02.000Z",
                    "format": "png",
                    "width": 1536,
                    "height": 2048,
                    "quality": "2k",
                    "title": "Red cotton T-shirt on a model, studio front view",
                    "alt_text": "Model wearing a red crew-neck cotton T-shirt, light grey studio background"
                  },
                  "credits": {
                    "estimated": 50,
                    "charged": 50
                  },
                  "project_id": "proj_img_1793816582113_k2p9x4",
                  "metadata": {
                    "sku": "TSHIRT-RED-M"
                  },
                  "error": null,
                  "livemode": true
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked API key (invalid_api_key).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The plan does not include the API or this option (api_not_in_plan, not_in_plan, storage_full).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not on this account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests (rate_limited) or generations (concurrency_limit). See Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteGeneration",
        "summary": "Cancel a queued generation, or delete a finished one with its files",
        "tags": [
          "Generations"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "gen_…"
          }
        ],
        "responses": {
          "200": {
            "description": "The canceled generation, or { id, object, deleted: true }.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/Generation"
                    },
                    {
                      "$ref": "#/components/schemas/Deleted"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked API key (invalid_api_key).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The plan does not include the API or this option (api_not_in_plan, not_in_plan, storage_full).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not on this account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "generation_running",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests (rate_limited) or generations (concurrency_limit). See Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/uploads": {
      "post": {
        "operationId": "createUpload",
        "summary": "Upload a product photo",
        "tags": [
          "Uploads"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "file"
                ],
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary",
                    "description": "PNG, JPEG, WebP or HEIC, up to 10 MB."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Saved to the image library.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Upload"
                },
                "example": {
                  "id": "upl_1793816500123_5Tn8Rr2W",
                  "object": "upload",
                  "filename": "tshirt-red-front.jpg",
                  "content_type": "image/jpeg",
                  "size_bytes": 842113,
                  "width": 1024,
                  "height": 1024,
                  "created_at": "2026-11-04T17:01:40.000Z"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request or invalid_image.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked API key (invalid_api_key).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The plan does not include the API or this option (api_not_in_plan, not_in_plan, storage_full).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests (rate_limited) or generations (concurrency_limit). See Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/files/{file_id}/content": {
      "get": {
        "operationId": "downloadFile",
        "summary": "Download a file",
        "tags": [
          "Files"
        ],
        "description": "Full-quality file. Works with the API key, or with the signed expires and sig of output.url (24 hours) and no key.",
        "security": [
          {
            "bearerAuth": []
          },
          {}
        ],
        "parameters": [
          {
            "name": "file_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "file_…"
          },
          {
            "name": "expires",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "sig",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The file.",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "video/mp4": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "Expired or invalid signed link.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such file on this account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/models": {
      "post": {
        "operationId": "createModel",
        "summary": "Create a custom model",
        "tags": [
          "Models and locations"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{8,64}$"
            },
            "description": "Retry safely: the same key and body return the same generation for 24 hours."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "description": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 1500,
                    "description": "3 to 1500 characters describing the model or place. Needed unless you send reference_image."
                  },
                  "reference_image": {
                    "$ref": "#/components/schemas/ImageRef"
                  },
                  "name": {
                    "type": "string",
                    "maxLength": 60,
                    "description": "Up to 60 characters. Without one, we name it."
                  },
                  "metadata": {
                    "type": "object",
                    "maxProperties": 20,
                    "additionalProperties": {
                      "type": "string",
                      "maxLength": 500
                    },
                    "description": "Your own references, returned unchanged: up to 20 keys (letters, digits, - or _, up to 40 characters), values up to 500 characters. metadata.sku (or reference) is shown on the result in My Generations."
                  },
                  "webhook_url": {
                    "type": "string",
                    "format": "uri",
                    "pattern": "^https://",
                    "maxLength": 2048,
                    "description": "An https address we call once when this generation ends: succeeded, failed or canceled. The call carries only its id, type and status, not the result, and isn't signed, so read the result with GET /v1/generations/{id}. See Webhooks."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted and queued.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Generation"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request or invalid_image; param names the field.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked API key (invalid_api_key).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "insufficient_credits or spending_cap_reached",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The plan does not include the API or this option (api_not_in_plan, not_in_plan, storage_full).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests (rate_limited) or generations (concurrency_limit). See Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listModels",
        "summary": "List models",
        "tags": [
          "Models and locations"
        ],
        "parameters": [
          {
            "name": "source",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "library",
                "custom"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Library and custom models.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "properties": {
                    "object": {
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Model"
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked API key (invalid_api_key).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The plan does not include the API or this option (api_not_in_plan, not_in_plan, storage_full).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests (rate_limited) or generations (concurrency_limit). See Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/models/{id}": {
      "get": {
        "operationId": "getModel",
        "summary": "Get a model",
        "tags": [
          "Models and locations"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "mdl_lib_… or mdl_own_…"
          }
        ],
        "responses": {
          "200": {
            "description": "One model.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Model"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked API key (invalid_api_key).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The plan does not include the API or this option (api_not_in_plan, not_in_plan, storage_full).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not in our library or this account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests (rate_limited) or generations (concurrency_limit). See Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteModel",
        "summary": "Delete a custom model",
        "tags": [
          "Models and locations"
        ],
        "description": "One of your own (mdl_own_…), with its files, the same as on fittins.ai. Test keys check the id and delete nothing.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "mdl_own_…"
          }
        ],
        "responses": {
          "200": {
            "description": "{ id, object, deleted: true }",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: library models can't be deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked API key (invalid_api_key).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The plan does not include the API or this option (api_not_in_plan, not_in_plan, storage_full).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not in our library or this account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "generation_running: a queued or running generation uses this model.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests (rate_limited) or generations (concurrency_limit). See Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/locations": {
      "post": {
        "operationId": "createLocation",
        "summary": "Create a custom location",
        "tags": [
          "Models and locations"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{8,64}$"
            },
            "description": "Retry safely: the same key and body return the same generation for 24 hours."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "description": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 1500,
                    "description": "3 to 1500 characters describing the model or place. Needed unless you send reference_image."
                  },
                  "reference_image": {
                    "$ref": "#/components/schemas/ImageRef"
                  },
                  "name": {
                    "type": "string",
                    "maxLength": 60,
                    "description": "Up to 60 characters. Without one, we name it."
                  },
                  "metadata": {
                    "type": "object",
                    "maxProperties": 20,
                    "additionalProperties": {
                      "type": "string",
                      "maxLength": 500
                    },
                    "description": "Your own references, returned unchanged: up to 20 keys (letters, digits, - or _, up to 40 characters), values up to 500 characters. metadata.sku (or reference) is shown on the result in My Generations."
                  },
                  "webhook_url": {
                    "type": "string",
                    "format": "uri",
                    "pattern": "^https://",
                    "maxLength": 2048,
                    "description": "An https address we call once when this generation ends: succeeded, failed or canceled. The call carries only its id, type and status, not the result, and isn't signed, so read the result with GET /v1/generations/{id}. See Webhooks."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted and queued.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Generation"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request or invalid_image; param names the field.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked API key (invalid_api_key).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "insufficient_credits or spending_cap_reached",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The plan does not include the API or this option (api_not_in_plan, not_in_plan, storage_full).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests (rate_limited) or generations (concurrency_limit). See Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listLocations",
        "summary": "List locations",
        "tags": [
          "Models and locations"
        ],
        "parameters": [
          {
            "name": "source",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "library",
                "custom"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Library and custom locations.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "properties": {
                    "object": {
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Location"
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked API key (invalid_api_key).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The plan does not include the API or this option (api_not_in_plan, not_in_plan, storage_full).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests (rate_limited) or generations (concurrency_limit). See Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/locations/{id}": {
      "get": {
        "operationId": "getLocation",
        "summary": "Get a location",
        "tags": [
          "Models and locations"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "loc_lib_… or loc_own_…"
          }
        ],
        "responses": {
          "200": {
            "description": "One location.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Location"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked API key (invalid_api_key).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The plan does not include the API or this option (api_not_in_plan, not_in_plan, storage_full).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not in our library or this account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests (rate_limited) or generations (concurrency_limit). See Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteLocation",
        "summary": "Delete a custom location",
        "tags": [
          "Models and locations"
        ],
        "description": "One of your own (loc_own_…), with its files, the same as on fittins.ai. Test keys check the id and delete nothing.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "loc_own_…"
          }
        ],
        "responses": {
          "200": {
            "description": "{ id, object, deleted: true }",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request: library locations can't be deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked API key (invalid_api_key).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The plan does not include the API or this option (api_not_in_plan, not_in_plan, storage_full).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not in our library or this account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "generation_running: a queued or running generation uses this location.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests (rate_limited) or generations (concurrency_limit). See Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/webhook_endpoints": {
      "post": {
        "operationId": "createWebhookEndpoint",
        "summary": "Create a webhook endpoint",
        "tags": [
          "Webhooks"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "url"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "pattern": "^https://"
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "generation.succeeded",
                        "generation.failed"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The endpoint with its signing secret, shown once.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpoint"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request; param names the field.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked API key (invalid_api_key).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The plan does not include the API or this option (api_not_in_plan, not_in_plan, storage_full).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests (rate_limited) or generations (concurrency_limit). See Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listWebhookEndpoints",
        "summary": "List webhook endpoints",
        "tags": [
          "Webhooks"
        ],
        "responses": {
          "200": {
            "description": "The endpoints with their last delivery.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "properties": {
                    "object": {
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookEndpoint"
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked API key (invalid_api_key).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The plan does not include the API or this option (api_not_in_plan, not_in_plan, storage_full).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests (rate_limited) or generations (concurrency_limit). See Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/webhook_endpoints/{id}": {
      "delete": {
        "operationId": "deleteWebhookEndpoint",
        "summary": "Delete a webhook endpoint",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "we_…"
          }
        ],
        "responses": {
          "200": {
            "description": "{ id, object, deleted: true }",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked API key (invalid_api_key).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The plan does not include the API or this option (api_not_in_plan, not_in_plan, storage_full).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not on this account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests (rate_limited) or generations (concurrency_limit). See Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/webhook_endpoints/{id}/rotate_secret": {
      "post": {
        "operationId": "rotateWebhookSecret",
        "summary": "Rotate the signing secret",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "we_…"
          }
        ],
        "responses": {
          "200": {
            "description": "The endpoint with its new secret, shown once. The old one keeps signing for 24 hours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpoint"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked API key (invalid_api_key).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The plan does not include the API or this option (api_not_in_plan, not_in_plan, storage_full).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not on this account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests (rate_limited) or generations (concurrency_limit). See Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/usage": {
      "get": {
        "operationId": "getUsage",
        "summary": "Calls, credits and failures per day and key",
        "tags": [
          "Account"
        ],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Usage, newest day first.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Usage"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked API key (invalid_api_key).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The plan does not include the API or this option (api_not_in_plan, not_in_plan, storage_full).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests (rate_limited) or generations (concurrency_limit). See Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/account": {
      "get": {
        "operationId": "getAccount",
        "summary": "Get the account",
        "tags": [
          "Account"
        ],
        "responses": {
          "200": {
            "description": "Plan, credits, features, limits and storage.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Account"
                },
                "example": {
                  "object": "account",
                  "plan": {
                    "id": "creator_pro",
                    "name": "Pro",
                    "billing_cycle": "monthly",
                    "renews_at": "2026-12-01T00:00:00.000Z"
                  },
                  "credits": {
                    "balance": 2860,
                    "reserved": 110,
                    "available": 2750
                  },
                  "features": {
                    "image_tiers": [
                      "default",
                      "turbo",
                      "premium"
                    ],
                    "image_qualities": [
                      "1k",
                      "2k",
                      "4k",
                      "8k"
                    ],
                    "video_tiers": [
                      "default",
                      "turbo",
                      "premium"
                    ],
                    "video_qualities": [
                      "1k",
                      "2k",
                      "4k"
                    ],
                    "custom_models_max": 50,
                    "custom_locations_max": 50
                  },
                  "limits": {
                    "concurrent_generations": 5,
                    "requests_per_minute": 60,
                    "creates_per_minute": 20
                  },
                  "storage": {
                    "used_bytes": 812649113,
                    "limit_bytes": 5368709120
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked API key (invalid_api_key).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The plan does not include the API or this option (api_not_in_plan, not_in_plan, storage_full).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests (rate_limited) or generations (concurrency_limit). See Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "fit_live_… key from Profile → API keys."
      }
    },
    "schemas": {
      "Generation": {
        "type": "object",
        "required": [
          "id",
          "object",
          "type",
          "status",
          "created_at",
          "started_at",
          "completed_at",
          "input",
          "output",
          "credits",
          "project_id",
          "metadata",
          "error",
          "livemode"
        ],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^gen_"
          },
          "object": {
            "const": "generation"
          },
          "type": {
            "type": "string",
            "enum": [
              "image",
              "video",
              "model",
              "location"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "running",
              "succeeded",
              "failed",
              "canceled"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "started_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "completed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "input": {
            "type": "object"
          },
          "output": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "type": "object",
                "properties": {
                  "file_id": {
                    "type": "string"
                  },
                  "url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "url_expires_at": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "format": {
                    "type": "string",
                    "enum": [
                      "png",
                      "mp4"
                    ]
                  },
                  "width": {
                    "type": [
                      "integer",
                      "null"
                    ]
                  },
                  "height": {
                    "type": [
                      "integer",
                      "null"
                    ]
                  },
                  "quality": {
                    "type": "string",
                    "enum": [
                      "1k",
                      "2k",
                      "4k",
                      "8k"
                    ]
                  },
                  "title": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "alt_text": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "duration_seconds": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "description": "Videos."
                  },
                  "has_sound": {
                    "type": "boolean",
                    "description": "Videos."
                  },
                  "id": {
                    "type": "string",
                    "description": "Custom models and locations: the new mdl_own_… or loc_own_… id, ready to use as model_id or location_id."
                  },
                  "object": {
                    "type": "string",
                    "enum": [
                      "model",
                      "location"
                    ],
                    "description": "Custom models and locations."
                  },
                  "source": {
                    "const": "custom",
                    "description": "Custom models and locations."
                  },
                  "name": {
                    "type": "string",
                    "description": "Custom models and locations."
                  },
                  "image_url": {
                    "type": "string",
                    "format": "uri",
                    "description": "Custom models and locations: a signed link to the image, valid for 24 hours."
                  },
                  "created_at": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "Custom models and locations."
                  }
                }
              }
            ]
          },
          "credits": {
            "type": "object",
            "properties": {
              "estimated": {
                "type": "integer"
              },
              "charged": {
                "type": "integer"
              }
            }
          },
          "project_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "error": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "type": "object",
                "properties": {
                  "code": {
                    "type": "string",
                    "enum": [
                      "invalid_request",
                      "invalid_image",
                      "invalid_api_key",
                      "insufficient_credits",
                      "spending_cap_reached",
                      "api_not_in_plan",
                      "not_in_plan",
                      "custom_limit_reached",
                      "storage_full",
                      "not_found",
                      "method_not_allowed",
                      "idempotency_conflict",
                      "generation_running",
                      "content_flagged",
                      "protected_content",
                      "rate_limited",
                      "concurrency_limit",
                      "generation_failed",
                      "internal_error"
                    ]
                  },
                  "message": {
                    "type": "string"
                  }
                }
              }
            ]
          },
          "livemode": {
            "type": "boolean"
          }
        }
      },
      "ImageFromUrl": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "url"
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "pattern": "^https://",
            "maxLength": 2048
          }
        }
      },
      "ImageFromUpload": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "upload_id"
        ],
        "properties": {
          "upload_id": {
            "type": "string",
            "pattern": "^upl_"
          }
        }
      },
      "ImageRef": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/ImageFromUrl"
          },
          {
            "$ref": "#/components/schemas/ImageFromUpload"
          }
        ]
      },
      "Model": {
        "type": "object",
        "required": [
          "id",
          "object",
          "source",
          "name",
          "image_url",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "const": "model"
          },
          "source": {
            "type": "string",
            "enum": [
              "library",
              "custom"
            ]
          },
          "name": {
            "type": "string"
          },
          "image_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "example": {
          "id": "mdl_lib_DM5rQvl3KtlR7nqumd6I",
          "object": "model",
          "source": "library",
          "name": "Layla Noor",
          "image_url": "https://api.fittins.ai/v1/files/file_8a1d0c3e5f7b9d2c4e6a8b0d/content?expires=1793905382&sig=Qa9…",
          "created_at": null
        }
      },
      "Location": {
        "type": "object",
        "required": [
          "id",
          "object",
          "source",
          "name",
          "image_url",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "const": "location"
          },
          "source": {
            "type": "string",
            "enum": [
              "library",
              "custom"
            ]
          },
          "name": {
            "type": "string"
          },
          "image_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "Upload": {
        "type": "object",
        "required": [
          "id",
          "object",
          "filename",
          "content_type",
          "size_bytes",
          "width",
          "height",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^upl_"
          },
          "object": {
            "const": "upload"
          },
          "filename": {
            "type": "string"
          },
          "content_type": {
            "type": "string"
          },
          "size_bytes": {
            "type": "integer"
          },
          "width": {
            "type": [
              "integer",
              "null"
            ]
          },
          "height": {
            "type": [
              "integer",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Account": {
        "type": "object",
        "required": [
          "object",
          "plan",
          "credits",
          "features",
          "limits",
          "storage"
        ],
        "properties": {
          "object": {
            "const": "account"
          },
          "plan": {
            "type": "object",
            "required": [
              "id",
              "name",
              "billing_cycle",
              "renews_at"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "billing_cycle": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "monthly",
                  "annual",
                  null
                ]
              },
              "renews_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            }
          },
          "credits": {
            "type": "object",
            "required": [
              "balance",
              "reserved",
              "available"
            ],
            "properties": {
              "balance": {
                "type": "integer"
              },
              "reserved": {
                "type": "integer",
                "description": "Held by running and queued generations."
              },
              "available": {
                "type": "integer"
              }
            }
          },
          "features": {
            "type": "object",
            "required": [
              "image_tiers",
              "image_qualities",
              "video_tiers",
              "video_qualities",
              "custom_models_max",
              "custom_locations_max"
            ],
            "properties": {
              "image_tiers": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "image_qualities": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "video_tiers": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "video_qualities": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "custom_models_max": {
                "type": "integer"
              },
              "custom_locations_max": {
                "type": "integer"
              }
            }
          },
          "limits": {
            "type": "object",
            "required": [
              "concurrent_generations",
              "queue_max",
              "requests_per_minute",
              "creates_per_minute"
            ],
            "properties": {
              "concurrent_generations": {
                "type": "integer"
              },
              "queue_max": {
                "type": "integer"
              },
              "requests_per_minute": {
                "type": "integer"
              },
              "creates_per_minute": {
                "type": "integer"
              }
            }
          },
          "storage": {
            "type": "object",
            "required": [
              "used_bytes",
              "limit_bytes"
            ],
            "properties": {
              "used_bytes": {
                "type": "integer"
              },
              "limit_bytes": {
                "type": "integer"
              }
            }
          }
        }
      },
      "UsageTotals": {
        "type": "object",
        "required": [
          "requests",
          "generations",
          "credits",
          "failures"
        ],
        "properties": {
          "requests": {
            "type": "integer"
          },
          "generations": {
            "type": "integer"
          },
          "credits": {
            "type": "integer"
          },
          "failures": {
            "type": "integer"
          }
        }
      },
      "UsageKey": {
        "type": "object",
        "required": [
          "name",
          "last4",
          "mode",
          "requests",
          "generations",
          "credits",
          "failures"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "last4": {
            "type": [
              "string",
              "null"
            ]
          },
          "mode": {
            "type": [
              "string",
              "null"
            ]
          },
          "requests": {
            "type": "integer"
          },
          "generations": {
            "type": "integer"
          },
          "credits": {
            "type": "integer"
          },
          "failures": {
            "type": "integer"
          }
        }
      },
      "UsageDay": {
        "type": "object",
        "required": [
          "date",
          "keys",
          "requests",
          "generations",
          "credits",
          "failures"
        ],
        "properties": {
          "date": {
            "type": "string",
            "format": "date"
          },
          "requests": {
            "type": "integer"
          },
          "generations": {
            "type": "integer"
          },
          "credits": {
            "type": "integer"
          },
          "failures": {
            "type": "integer"
          },
          "keys": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/UsageKey"
            }
          }
        }
      },
      "Usage": {
        "type": "object",
        "required": [
          "object",
          "from",
          "to",
          "totals",
          "days"
        ],
        "properties": {
          "object": {
            "const": "usage"
          },
          "from": {
            "type": "string",
            "format": "date"
          },
          "to": {
            "type": "string",
            "format": "date"
          },
          "totals": {
            "$ref": "#/components/schemas/UsageTotals"
          },
          "days": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/UsageDay"
            }
          }
        }
      },
      "Deleted": {
        "type": "object",
        "required": [
          "id",
          "object",
          "deleted"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "type": "string"
          },
          "deleted": {
            "const": true
          }
        }
      },
      "WebhookEndpoint": {
        "type": "object",
        "required": [
          "id",
          "object",
          "url",
          "events",
          "status",
          "livemode",
          "created_at",
          "last_delivery"
        ],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^we_"
          },
          "object": {
            "const": "webhook_endpoint"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "generation.succeeded",
                "generation.failed"
              ]
            }
          },
          "status": {
            "type": "string",
            "enum": [
              "enabled",
              "paused"
            ]
          },
          "livemode": {
            "type": "boolean"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "last_delivery": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "type": "object",
                "required": [
                  "at",
                  "status",
                  "http_status"
                ],
                "properties": {
                  "at": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time"
                  },
                  "status": {
                    "type": "string"
                  },
                  "http_status": {
                    "type": [
                      "integer",
                      "null"
                    ]
                  }
                }
              }
            ]
          },
          "secret": {
            "type": "string",
            "description": "Only when created or rotated."
          }
        }
      },
      "WebhookEvent": {
        "type": "object",
        "required": [
          "id",
          "object",
          "type",
          "created_at",
          "livemode",
          "data"
        ],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^evt_"
          },
          "object": {
            "const": "event"
          },
          "type": {
            "type": "string",
            "enum": [
              "generation.succeeded",
              "generation.failed"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "livemode": {
            "type": "boolean"
          },
          "data": {
            "type": "object",
            "required": [
              "object"
            ],
            "properties": {
              "object": {
                "$ref": "#/components/schemas/Generation"
              }
            }
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "type",
              "code",
              "message",
              "request_id"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "invalid_request_error",
                  "authentication_error",
                  "credits_error",
                  "permission_error",
                  "not_found_error",
                  "idempotency_error",
                  "conflict_error",
                  "content_error",
                  "rate_limit_error",
                  "generation_error",
                  "api_error"
                ]
              },
              "code": {
                "type": "string",
                "enum": [
                  "invalid_request",
                  "invalid_image",
                  "invalid_api_key",
                  "insufficient_credits",
                  "spending_cap_reached",
                  "api_not_in_plan",
                  "not_in_plan",
                  "custom_limit_reached",
                  "storage_full",
                  "not_found",
                  "method_not_allowed",
                  "idempotency_conflict",
                  "generation_running",
                  "content_flagged",
                  "protected_content",
                  "rate_limited",
                  "concurrency_limit",
                  "generation_failed",
                  "internal_error"
                ]
              },
              "message": {
                "type": "string"
              },
              "param": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "request_id": {
                "type": "string"
              },
              "doc_url": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        },
        "example": {
          "error": {
            "type": "credits_error",
            "code": "insufficient_credits",
            "message": "This photo needs 60 credits and 38 are available. Buy a credit pack or upgrade your plan.",
            "param": null,
            "request_id": "req_6RkP2wQ9mT3xLc8B",
            "doc_url": "https://fittins.ai/docs/api/errors#insufficient_credits"
          }
        }
      }
    }
  }
}