{
  "openapi": "3.1.0",
  "info": {
    "title": "Kyma API",
    "description": "LLM API gateway. One endpoint, 106 active models across language, image and audio. Multi-provider redundancy. OpenAI and Anthropic SDK compatible. Image generation via async POST /v1/images/generations + GET /v1/jobs/{id} (gpt-image-2 + FLUX.2 Pro + Recraft V4 family + MiniMax Image-01). Audio: POST /v1/audio/{transcriptions, understand, speech, music, sfx, voice-clone, voice-design}.",
    "version": "1.0.0",
    "contact": {
      "name": "Kyma API",
      "url": "https://kymaapi.com",
      "email": "support@kymaapi.com"
    },
    "termsOfService": "https://kymaapi.com/terms",
    "license": {
      "name": "Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://kymaapi.com/v1",
      "description": "Production"
    }
  ],
  "security": [
    {
      "BearerAuth": []
    }
  ],
  "paths": {
    "/chat/completions": {
      "post": {
        "operationId": "createChatCompletion",
        "summary": "Create chat completion",
        "description": "Generate a chat response from a model. OpenAI-compatible format. Supports streaming, tool calling, structured outputs, and prompt caching.",
        "tags": [
          "Chat"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChatCompletionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Chat completion response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChatCompletionResponse"
                }
              },
              "text/event-stream": {
                "description": "Server-sent events stream (when stream=true)"
              }
            },
            "headers": {
              "X-Kyma-Model": {
                "description": "Actual model used for this request",
                "schema": {
                  "type": "string"
                }
              },
              "X-Kyma-Alias": {
                "description": "Alias that was resolved (if alias was used)",
                "schema": {
                  "type": "string"
                }
              },
              "X-Kyma-Fallback": {
                "description": "Whether a fallback provider was used",
                "schema": {
                  "type": "boolean"
                }
              },
              "X-Kyma-Fallback-Layer": {
                "description": "Fallback layer used (1=same model different provider, 3=different model)",
                "schema": {
                  "type": "integer",
                  "enum": [
                    1,
                    2,
                    3
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/embeddings": {
      "post": {
        "summary": "Create embeddings",
        "description": "Turn text into vectors for retrieval. OpenAI-compatible, so an existing `client.embeddings.create()` call works by changing the base URL and the model id.\n\nBilled on input tokens only \u2014 an embedding response is a vector, so there is no completion side to charge for. `usage.cost` carries the exact price of the call.\n\nNo streaming: the vector arrives whole. Use `GET /v1/models?type=embedding` to list what is available.",
        "operationId": "createEmbedding",
        "tags": [
          "Embeddings"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "model",
                  "input"
                ],
                "properties": {
                  "model": {
                    "type": "string",
                    "example": "embeddinggemma-300m",
                    "description": "An embedding model id. A chat model here returns 400."
                  },
                  "input": {
                    "description": "A string, or an array of strings to embed in one call.",
                    "oneOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      }
                    ],
                    "example": [
                      "first document",
                      "second document"
                    ]
                  },
                  "dimensions": {
                    "type": "integer",
                    "description": "Requested vector size, when the model supports truncation."
                  },
                  "encoding_format": {
                    "type": "string",
                    "enum": [
                      "float",
                      "base64"
                    ],
                    "default": "float"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "One vector per input, in the order given.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "example": "list"
                    },
                    "model": {
                      "type": "string",
                      "example": "embeddinggemma-300m"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "type": "string",
                            "example": "embedding"
                          },
                          "index": {
                            "type": "integer"
                          },
                          "embedding": {
                            "type": "array",
                            "items": {
                              "type": "number"
                            }
                          }
                        }
                      }
                    },
                    "usage": {
                      "type": "object",
                      "properties": {
                        "prompt_tokens": {
                          "type": "integer"
                        },
                        "total_tokens": {
                          "type": "integer"
                        },
                        "cost": {
                          "type": "number",
                          "description": "USD charged for this call."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing `input`, or a model that is not an embedding model."
          },
          "401": {
            "description": "Missing or invalid API key."
          },
          "402": {
            "description": "Insufficient balance."
          },
          "404": {
            "description": "Unknown model."
          }
        }
      }
    },
    "/decisions": {
      "post": {
        "summary": "Make a decision",
        "description": "Ask a model to pick one option per question, with a confidence, instead of writing prose you have to parse back into a choice.\n\nSend the state and the questions; every question comes back with one of the options you supplied, a confidence between 0 and 1, and the probabilities across the options when the model reports them.\n\nBilled per input token at the model's published rate, rounded up to the nearest $0.0001 \u2014 the smallest amount the ledger holds \u2014 with output free. `usage.cost` is the amount taken from your balance, not a number rounded again later. Failures are not charged.",
        "operationId": "createDecision",
        "tags": [
          "Decisions"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "state",
                  "questions"
                ],
                "properties": {
                  "model": {
                    "type": "string",
                    "default": "jev",
                    "example": "jev",
                    "description": "The decisions model. `jev` is the only value today; any other returns 400."
                  },
                  "state": {
                    "type": "string",
                    "example": "Proposed shell command: `rm -rf ./build` in a CI job that has already published its artifacts.",
                    "description": "What the model is deciding about, in your own words."
                  },
                  "questions": {
                    "type": "object",
                    "description": "One or more questions keyed by an id you choose. Each must be a choice question: `{\"type\": \"choice\", \"instructions\": \"\u2026\", \"criteria\": {\"<option>\": \"<what it means>\"}}` with at least one option.",
                    "additionalProperties": {
                      "type": "object",
                      "required": [
                        "type",
                        "criteria"
                      ],
                      "properties": {
                        "type": {
                          "type": "string",
                          "enum": [
                            "choice"
                          ]
                        },
                        "instructions": {
                          "type": "string"
                        },
                        "criteria": {
                          "type": "object",
                          "additionalProperties": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "One answer per question asked",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "model": {
                      "type": "string",
                      "example": "jev"
                    },
                    "answers": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "object",
                        "properties": {
                          "choice": {
                            "type": "string",
                            "description": "Always one of the options supplied for that question."
                          },
                          "confidence": {
                            "type": "number",
                            "minimum": 0,
                            "maximum": 1
                          },
                          "probabilities": {
                            "type": "object",
                            "additionalProperties": {
                              "type": "number"
                            }
                          }
                        }
                      }
                    },
                    "usage": {
                      "type": "object",
                      "properties": {
                        "input_tokens": {
                          "type": "integer"
                        },
                        "output_tokens": {
                          "type": "integer"
                        },
                        "cost": {
                          "type": "number",
                          "description": "Dollars charged for this call."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing `state` or `questions`, a question that is not a choice question, or a `model` other than `jev`."
          },
          "401": {
            "description": "Missing or invalid API key."
          },
          "402": {
            "description": "Balance does not cover the call."
          }
        }
      }
    },
    "/completions": {
      "post": {
        "summary": "Create a completion (legacy)",
        "description": "OpenAI's deprecated text-completion shape, served for compatibility with older SDK pins and scripts. Prefer `POST /v1/chat/completions` for anything new.\n\nTakes `prompt` instead of `messages` and returns `choices[].text` instead of `choices[].message.content`. Everything else \u2014 models, pricing, streaming, failover \u2014 is identical, because this is an adapter over the chat endpoint rather than a separate path.\n\nNot supported: `suffix` (fill-in-the-middle), a multi-element `prompt` array, and `echo` together with `stream`. Each returns 400 naming the alternative rather than silently returning something that looks right.",
        "operationId": "createCompletion",
        "deprecated": true,
        "tags": [
          "Completions"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "model",
                  "prompt"
                ],
                "properties": {
                  "model": {
                    "type": "string",
                    "example": "qwen3.7-flash"
                  },
                  "prompt": {
                    "type": "string",
                    "description": "The text to complete. A single-element array is accepted; more than one is refused.",
                    "example": "Write a haiku about routing"
                  },
                  "max_tokens": {
                    "type": "integer"
                  },
                  "temperature": {
                    "type": "number"
                  },
                  "stream": {
                    "type": "boolean",
                    "default": false
                  },
                  "echo": {
                    "type": "boolean",
                    "default": false,
                    "description": "Prepend the prompt to the completion. Cannot be combined with `stream`."
                  },
                  "stop": {
                    "description": "Up to 4 stop sequences.",
                    "oneOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A legacy `text_completion` object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "object": {
                      "type": "string",
                      "example": "text_completion"
                    },
                    "created": {
                      "type": "integer"
                    },
                    "model": {
                      "type": "string"
                    },
                    "choices": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "text": {
                            "type": "string"
                          },
                          "index": {
                            "type": "integer"
                          },
                          "logprobs": {
                            "type": "null"
                          },
                          "finish_reason": {
                            "type": "string",
                            "example": "stop"
                          }
                        }
                      }
                    },
                    "usage": {
                      "type": "object",
                      "description": "Identical to the chat endpoint, including `usage.cost`."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing `prompt`, a multi-prompt array, `suffix`, or `echo` with `stream`."
          },
          "401": {
            "description": "Missing or invalid API key."
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "Unknown model."
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/messages": {
      "post": {
        "operationId": "createMessage",
        "summary": "Create message (Anthropic format)",
        "description": "Generate a response using the Anthropic Messages API format. Same models and pricing as /chat/completions.",
        "tags": [
          "Chat"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AnthropicMessageRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Message response in Anthropic format"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/images/generations": {
      "post": {
        "operationId": "createImageGeneration",
        "summary": "Create image generation (async)",
        "description": "Generate or edit images. Asynchronous \u2014 returns 202 with a job_id immediately; poll GET /v1/jobs/{id} for the result. Models: see GET /v1/models for the live image catalogue. Billed per image; failures are refunded in full.",
        "tags": [
          "Images"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "model",
                  "prompt"
                ],
                "properties": {
                  "model": {
                    "type": "string",
                    "description": "Image model ID. Pick by task: gpt-image-2 = best text-in-image (multilingual, logos, posters); gpt-image-2.5-flare = consistent characters from reference images, exact text-in-image; flux-2-pro = photoreal + multi-reference blend (up to 10 source images); recraft-v4-pro = print-ready 4MP design; recraft-v4-vector = native SVG output with editable paths; ideogram-v3 = typography specialist; recraft-v4 = #1 HF Arena daily default; flux-kontext-pro = image edit/inpaint (REQUIRES image_url); minimax-image-01 = sub-cent budget tier.",
                    "enum": [
                      "gpt-image-2",
                      "gpt-image-2.5-flare",
                      "flux-2-pro",
                      "recraft-v4",
                      "recraft-v4-pro",
                      "recraft-v4-vector",
                      "ideogram-v3",
                      "flux-kontext-pro",
                      "minimax-image-01"
                    ]
                  },
                  "prompt": {
                    "type": "string",
                    "maxLength": 4000,
                    "description": "Natural-language description of the image. For text-in-image with gpt-image-2, quote the literal text you want rendered (e.g., 'a poster reading \"Open Late Friday\" in bold serif'). Server normalizes to NFC before length check so stacked-diacritic scripts (Vietnamese, Hindi, Arabic) measure correctly."
                  },
                  "n": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 10,
                    "default": 1,
                    "description": "Number of images to generate. Billed per output image. gpt-image-2 supports up to 10; other models cap at 4. A request with n=4 books and bills 4\u00d7 the per-image price."
                  },
                  "size": {
                    "type": "string",
                    "description": "Output dimensions as WIDTHxHEIGHT (e.g., 1024x1024, 1024x1536, 1536x1024, 2048x2048) or 'auto'. gpt-image-2 supports 1024x1024 / 1024x1536 / 1536x1024 / 2048x2048; values outside that enum snap to 1024x1024. gpt-image-2.5-flare supports 1024x1024 / 1024x1536 / 1536x1024 / auto; a side above 1536 returns 400 invalid_parameter. Recraft V4 and FLUX.2 Pro accept fal-style aspect enums (square_hd, landscape_16_9, portrait_4_3, etc.) which the gateway maps for you. For per-MP pricing models (flux-2-pro), bigger sizes cost more."
                  },
                  "quality": {
                    "type": "string",
                    "enum": [
                      "low",
                      "medium",
                      "high",
                      "auto"
                    ],
                    "default": "medium",
                    "description": "Consumed by gpt-image-2 and gpt-image-2.5-flare (ignored elsewhere). Sets the OpenAI quality tier and the per-image price: gpt-image-2 low=$0.009, medium=$0.072, high=$0.285; gpt-image-2.5-flare low=$0.009, medium=$0.019, high=$0.285, plus $0.012 per reference image (image_url / image_urls) once per request. The hold books the full amount up front. 'auto' or omitted bills medium."
                  },
                  "image_url": {
                    "type": "string",
                    "description": "HTTPS URL of a source image. REQUIRED for flux-kontext-pro (image edit). Optional for gpt-image-2 and gpt-image-2.5-flare, which edit from it as a reference (on gpt-image-2.5-flare each reference image adds $0.012)."
                  },
                  "image_urls": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "maxItems": 16,
                    "description": "Multi-reference input. gpt-image-2 and gpt-image-2.5-flare accept up to 16 HTTPS URLs (gpt-image-2.5-flare adds $0.012 per reference, once per request); flux-2-pro accepts up to 10 and blends them; other models up to 10. More than the model's cap returns 400 too_many_references. When both image_url and image_urls are present, image_urls wins."
                  },
                  "idempotency_key": {
                    "type": "string",
                    "maxLength": 128,
                    "description": "Deduplication key. Resending the same request body with the same key within the retention window returns the existing job (200 OK with the original ImageJob), not a new charge. Safe to retry 5xx responses."
                  },
                  "extra": {
                    "type": "object",
                    "description": "Pass-through to the underlying model. Validated upstream \u2014 invalid keys return 400 from the provider, not 500."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Idempotent replay \u2014 same idempotency_key returns the existing job",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImageJob"
                }
              }
            }
          },
          "202": {
            "description": "Job accepted; poll GET /v1/jobs/{id} for status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImageJob"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/videos/generations": {
      "post": {
        "operationId": "createVideoGeneration",
        "summary": "Create video generation (async)",
        "description": "Generate video from a text prompt, optionally conditioned on a starting frame (image-to-video). Asynchronous - returns 202 with a job_id immediately; poll GET /v1/jobs/{id} for the result. Billed per generation; failures are refunded in full.",
        "tags": [
          "Video"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "model",
                  "prompt"
                ],
                "properties": {
                  "model": {
                    "type": "string",
                    "description": "Video model ID (output modality includes video). See GET /v1/models for the live catalogue; a model that is not being served returns 404 model_not_found."
                  },
                  "prompt": {
                    "type": "string",
                    "description": "Natural-language description of the video to generate."
                  },
                  "duration_s": {
                    "type": "integer",
                    "description": "Requested clip length in seconds. Allowed values are model-dependent; out-of-range values snap to the nearest supported duration. For kling-avatar-v2-pro it is required and is the length of your audio, rounded up (5 to 60): the clip follows the audio, you are charged for the clip's real length, and duration_s caps that charge. Audio longer than duration_s is cut at duration_s."
                  },
                  "aspect_ratio": {
                    "type": "string",
                    "description": "Output aspect ratio (e.g. 16:9, 9:16, 1:1). Model-dependent; unsupported values fall back to the model default."
                  },
                  "image_url": {
                    "type": "string",
                    "description": "Optional HTTPS URL of a starting frame for image-to-video models. Omit for pure text-to-video. Required by kling-avatar-v2-pro, where it is the face to animate."
                  },
                  "audio_url": {
                    "type": "string",
                    "description": "kling-avatar-v2-pro only: HTTPS URL of the speech or song to lip-sync, as an uncompressed PCM WAV file (WAV PCM only for now; MP3, M4A, AAC and OGG are refused), at least 5 s. The clip runs as long as this audio and plays it unchanged. Any other model refuses it with 400 invalid_parameter."
                  },
                  "idempotency_key": {
                    "type": "string",
                    "maxLength": 128,
                    "description": "Deduplication key. Resending the same body with the same key within the retention window returns the existing job (200 with the original VideoJob), not a new charge. Also accepted via the Idempotency-Key header."
                  },
                  "extra": {
                    "type": "object",
                    "description": "Pass-through to the underlying model. Validated upstream. Never changes a priced field; ignored by kling-avatar-v2-pro."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Idempotent replay - same idempotency_key returns the existing job",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VideoJob"
                }
              }
            }
          },
          "202": {
            "description": "Job accepted; poll GET /v1/jobs/{id} for status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VideoJob"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/audio/transcriptions": {
      "post": {
        "operationId": "createAudioTranscription",
        "summary": "Create audio transcription (sync)",
        "description": "Speech-to-text. Multipart upload; sync response. OpenAI Whisper API compatible. Use alias `transcribe` (auto-tracks current best ASR) or pin `whisper-v3-turbo`. Billed per minute, rounded up.",
        "tags": [
          "Audio"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "file"
                ],
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary",
                    "description": "Audio file (mp3, wav, m4a, ogg, webm, flac). Max 25 MB."
                  },
                  "model": {
                    "type": "string",
                    "default": "transcribe",
                    "description": "Either the alias `transcribe` or a SKU like `whisper-v3-turbo`."
                  },
                  "language": {
                    "type": "string",
                    "description": "Optional ISO-639-1 code (e.g. `en`, `vi`). Whisper auto-detects when omitted."
                  },
                  "response_format": {
                    "type": "string",
                    "enum": [
                      "json",
                      "verbose_json",
                      "text",
                      "srt",
                      "vtt"
                    ],
                    "default": "verbose_json",
                    "description": "json / verbose_json return JSON; text returns plain text; srt and vtt return subtitle files. Billing details ride X-Kyma-* response headers when the body is text/srt/vtt; they live in the JSON body for json/verbose_json."
                  },
                  "temperature": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 1,
                    "default": 0
                  },
                  "prompt": {
                    "type": "string",
                    "description": "Optional priming text to nudge the model toward known proper nouns or domain vocabulary."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Transcript in the requested response_format. JSON formats embed a billing block; text/srt/vtt expose billing via X-Kyma-* response headers so the body remains a plain transcript or subtitle file.",
            "headers": {
              "X-Kyma-Model": {
                "schema": {
                  "type": "string"
                },
                "description": "The Kyma model SKU that served the request."
              },
              "X-Kyma-Duration-Sec": {
                "schema": {
                  "type": "number"
                },
                "description": "Detected audio duration in seconds."
              },
              "X-Kyma-Billable-Minutes": {
                "schema": {
                  "type": "integer"
                },
                "description": "Minutes charged. Always >= 1."
              },
              "X-Kyma-Cost-USD": {
                "schema": {
                  "type": "number"
                },
                "description": "Final cost charged for this request."
              },
              "X-Kyma-Balance-USD": {
                "schema": {
                  "type": "number"
                },
                "description": "Remaining account balance after this charge."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "description": "response_format=json",
                      "type": "object",
                      "properties": {
                        "text": {
                          "type": "string"
                        },
                        "model": {
                          "type": "string"
                        },
                        "billing": {
                          "$ref": "#/components/schemas/AudioBilling"
                        }
                      }
                    },
                    {
                      "description": "response_format=verbose_json (default)",
                      "type": "object",
                      "properties": {
                        "task": {
                          "type": "string"
                        },
                        "language": {
                          "type": "string"
                        },
                        "duration": {
                          "type": "number"
                        },
                        "text": {
                          "type": "string"
                        },
                        "segments": {
                          "type": "array",
                          "items": {
                            "type": "object"
                          }
                        },
                        "model": {
                          "type": "string"
                        },
                        "billing": {
                          "$ref": "#/components/schemas/AudioBilling"
                        }
                      }
                    }
                  ]
                }
              },
              "text/plain; charset=utf-8": {
                "schema": {
                  "type": "string",
                  "description": "response_format=text"
                }
              },
              "application/x-subrip; charset=utf-8": {
                "schema": {
                  "type": "string",
                  "description": "response_format=srt \u2014 SubRip subtitle file"
                }
              },
              "text/vtt; charset=utf-8": {
                "schema": {
                  "type": "string",
                  "description": "response_format=vtt \u2014 WebVTT subtitle file"
                }
              }
            }
          },
          "400": {
            "description": "Missing file, not multipart, or model not a transcription SKU"
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "404": {
            "description": "Audio gate not enabled on this account"
          },
          "413": {
            "description": "Audio file exceeds 25 MB"
          },
          "502": {
            "description": "Upstream transcription failed"
          }
        }
      }
    },
    "/audio/understand": {
      "post": {
        "operationId": "createAudioUnderstand",
        "summary": "Create audio understanding (sync)",
        "description": "Retired 2026-10-08: no model is served on this endpoint. Its only model, also the default, was retired and the `audio-understand` alias removed; every request returns 404 model_not_found and nothing is charged. Was: audio scene Q&A (tone, music, SFX, language, speaker emotion), billed per minute, rounded up.",
        "deprecated": true,
        "tags": [
          "Audio"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "file",
                  "question"
                ],
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary",
                    "description": "Audio file (mp3, wav, m4a, ogg, webm, flac). Max 25 MB inline."
                  },
                  "question": {
                    "type": "string",
                    "description": "Free-form question about the audio."
                  },
                  "model": {
                    "type": "string",
                    "description": "No model is served since 2026-10-08."
                  },
                  "duration_sec": {
                    "type": "integer",
                    "description": "Optional duration hint in seconds. When supplied, billing rounds up from this value. When omitted, Kyma estimates duration from file size."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Free-form answer plus a Kyma billing block",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "answer": {
                      "type": "string"
                    },
                    "model": {
                      "type": "string"
                    },
                    "billing": {
                      "$ref": "#/components/schemas/AudioBilling"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing file or question, or model not an audio-understanding SKU"
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "404": {
            "description": "Audio gate not enabled on this account"
          },
          "413": {
            "description": "Audio file exceeds 25 MB"
          },
          "502": {
            "description": "Upstream audio understanding failed"
          }
        }
      }
    },
    "/audio/speech": {
      "post": {
        "operationId": "createSpeech",
        "summary": "Text-to-speech (sync)",
        "description": "Synthesize speech from text. Synchronous - returns the audio bytes directly. OpenAI /audio/speech compatible (input + voice). Billed per character (max 5000 chars/request). Pick a voice_id from GET /v1/audio/voices, or omit voice to use a provider default.",
        "tags": [
          "Audio"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "input"
                ],
                "properties": {
                  "model": {
                    "type": "string",
                    "default": "eleven-multilingual-v2",
                    "description": "TTS model SKU (ElevenLabs or MiniMax family). Non-TTS models return 400 not_a_tts_model."
                  },
                  "input": {
                    "type": "string",
                    "maxLength": 5000,
                    "description": "Text to speak. Max 5000 characters (NFC-normalized) per request - split longer text client-side. Alias: text."
                  },
                  "voice": {
                    "type": "string",
                    "description": "Voice id. OpenAI-style voice or provider voice_id both accepted. Defaults to a known-good voice per provider when omitted. List options via GET /v1/audio/voices."
                  },
                  "response_format": {
                    "type": "string",
                    "default": "mp3_44100_128",
                    "description": "Output audio format. ElevenLabs uses names like mp3_44100_128; MiniMax accepts mp3/wav/flac/pcm. The first segment is used, so an OpenAI-style mp3_44100_128 maps to mp3 on MiniMax."
                  },
                  "speed": {
                    "type": "number",
                    "description": "MiniMax only. Playback speed multiplier."
                  },
                  "voice_settings": {
                    "type": "object",
                    "description": "ElevenLabs only. Passed through (stability, similarity_boost, style, etc.)."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Audio bytes in the requested format. Billing rides X-Kyma-* response headers. Append ?save_to_blob=1 to instead receive a JSON body with a hosted url (used by the Kyma canvas).",
            "headers": {
              "X-Kyma-Model": {
                "schema": {
                  "type": "string"
                },
                "description": "The Kyma model SKU that served the request."
              },
              "X-Kyma-Chars-Billed": {
                "schema": {
                  "type": "integer"
                },
                "description": "Characters billed for this request."
              },
              "X-Kyma-Cost-USD": {
                "schema": {
                  "type": "number"
                },
                "description": "Final cost charged for this request."
              },
              "X-Kyma-Balance-USD": {
                "schema": {
                  "type": "number"
                },
                "description": "Remaining account balance after this charge."
              }
            },
            "content": {
              "audio/mpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "audio/wav": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/audio/music": {
      "post": {
        "operationId": "createMusic",
        "summary": "Generate music (sync)",
        "description": "Generate a music track from a text description (ElevenLabs prompt) or lyrics (MiniMax lyrics, with optional [verse]/[chorus] tags; pass [Instrumental] for vocal-less tracks). Synchronous - returns audio bytes. Billed per track.",
        "tags": [
          "Audio"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "model": {
                    "type": "string",
                    "description": "Music model SKU (ElevenLabs or MiniMax). Non-music models return 400 not_a_music_model. This lane is paused: every model is switched off, so a request returns 404 model_not_found."
                  },
                  "prompt": {
                    "type": "string",
                    "description": "Text description of the music. Required for ElevenLabs models. A per-model character cap applies."
                  },
                  "lyrics": {
                    "type": "string",
                    "description": "Lyrics for MiniMax models, with optional [verse]/[chorus] tags. Pass [Instrumental] for vocal-less tracks. Falls back to prompt when omitted."
                  },
                  "music_length_ms": {
                    "type": "integer",
                    "default": 30000,
                    "description": "Requested track length in milliseconds. Alias: duration_ms. Model-dependent caps apply."
                  },
                  "response_format": {
                    "type": "string",
                    "description": "Output audio format (provider-dependent; e.g. mp3, wav, flac)."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Audio bytes. Billing rides X-Kyma-* response headers. Append ?save_to_blob=1 for a JSON body with a hosted url.",
            "headers": {
              "X-Kyma-Model": {
                "schema": {
                  "type": "string"
                },
                "description": "Model SKU that served the request."
              },
              "X-Kyma-Cost-USD": {
                "schema": {
                  "type": "number"
                },
                "description": "Final cost charged for this request."
              },
              "X-Kyma-Balance-USD": {
                "schema": {
                  "type": "number"
                },
                "description": "Remaining account balance after this charge."
              }
            },
            "content": {
              "audio/mpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/audio/sfx": {
      "post": {
        "operationId": "createSoundEffect",
        "summary": "Generate sound effect (sync)",
        "description": "Generate a short sound effect from a text prompt (ElevenLabs). Synchronous - returns audio bytes. Billed per generation.",
        "tags": [
          "Audio"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "prompt"
                ],
                "properties": {
                  "model": {
                    "type": "string",
                    "description": "SFX model SKU. Non-SFX models return 400 not_an_sfx_model. This lane is paused: every model is switched off, so a request returns 404 model_not_found."
                  },
                  "prompt": {
                    "type": "string",
                    "description": "Description of the sound effect. Alias: text."
                  },
                  "duration_seconds": {
                    "type": "number",
                    "description": "Optional target length in seconds. Omit to let the model choose."
                  },
                  "response_format": {
                    "type": "string",
                    "default": "mp3_44100_128",
                    "description": "Output audio format (ElevenLabs naming, e.g. mp3_44100_128)."
                  },
                  "prompt_influence": {
                    "type": "number",
                    "description": "How strictly the output follows the prompt (0-1)."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Audio bytes. Billing rides X-Kyma-* response headers. Append ?save_to_blob=1 for a JSON body with a hosted url.",
            "headers": {
              "X-Kyma-Model": {
                "schema": {
                  "type": "string"
                },
                "description": "Model SKU that served the request."
              },
              "X-Kyma-Cost-USD": {
                "schema": {
                  "type": "number"
                },
                "description": "Final cost charged for this request."
              },
              "X-Kyma-Balance-USD": {
                "schema": {
                  "type": "number"
                },
                "description": "Remaining account balance after this charge."
              }
            },
            "content": {
              "audio/mpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/jobs/{id}": {
      "get": {
        "operationId": "getJob",
        "summary": "Get job status",
        "description": "Fetch the current state of an async job (image generation, etc.). Same response shape as POST /v1/images/generations.",
        "tags": [
          "Images"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Job status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImageJob"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Job not found or not owned by this API key"
          }
        }
      }
    },
    "/models": {
      "get": {
        "operationId": "listModels",
        "summary": "List all models",
        "description": "Returns all available models with pricing, capabilities, context windows, and recommendations. No authentication required.",
        "tags": [
          "Models"
        ],
        "security": [],
        "parameters": [
          {
            "name": "type",
            "in": "query",
            "description": "Filter by model type (comma-separated = OR, since a model has exactly one type). Values: language, image, video, embedding, reranking, transcription, realtime, speech",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tags",
            "in": "query",
            "description": "Filter by capability tag (comma-separated = AND). Values: tool-use, reasoning, vision, implicit-caching, explicit-caching, file-input, web-search, image-generation, video-generation, websocket-realtime, websocket-transcription, fast",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "use_cases",
            "in": "query",
            "description": "Filter by use case (comma-separated = AND). Values: write-code, build-agents, chat, write-content, translate, research-web, analyse-documents, solve-math, generate-images, edit-images, generate-video, transcribe-audio, generate-speech",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "recommended_for",
            "in": "query",
            "description": "DEPRECATED \u2014 alias of use_cases, kept for existing callers. Accepts the pre-2026-07-27 vocabulary (coding, agent, general, image, video, transcribe, \u2026) and resolves it to the use_cases equivalent. Prefer use_cases for new integrations.",
            "schema": {
              "type": "string"
            },
            "deprecated": true
          },
          {
            "name": "tools",
            "in": "query",
            "description": "Filter to models supporting tool calling",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "vision",
            "in": "query",
            "description": "Filter to models supporting image input",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "reasoning",
            "in": "query",
            "description": "Filter to models with reasoning capabilities",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "structured_outputs",
            "in": "query",
            "description": "Filter to models supporting structured outputs / JSON mode",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "latency_tier",
            "in": "query",
            "description": "Filter by latency tier",
            "schema": {
              "type": "string",
              "enum": [
                "fast",
                "medium",
                "slow"
              ]
            }
          },
          {
            "name": "cost_tier",
            "in": "query",
            "description": "Filter by cost tier",
            "schema": {
              "type": "string",
              "enum": [
                "cheap",
                "balanced",
                "premium"
              ]
            }
          },
          {
            "name": "quality_tier",
            "in": "query",
            "description": "Filter by quality tier",
            "schema": {
              "type": "string",
              "enum": [
                "efficient",
                "strong",
                "frontier-open"
              ]
            }
          },
          {
            "name": "min_context_window",
            "in": "query",
            "description": "Minimum context window size in tokens",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "max_input_price",
            "in": "query",
            "description": "Maximum input price per 1M tokens",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of models",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ModelList"
                }
              }
            }
          }
        }
      }
    },
    "/models/recommend": {
      "get": {
        "operationId": "recommendModel",
        "summary": "Get model recommendation",
        "description": "Get a model recommendation by use case or specific agent. Returns config examples. No authentication required.",
        "tags": [
          "Models"
        ],
        "security": [],
        "parameters": [
          {
            "name": "agent",
            "in": "query",
            "description": "Agent name for specific config. Supported: cline, roo-code, openclaw, claude-code, aider, opencode, cursor, kilo-code",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "usecase",
            "in": "query",
            "description": "Use case for recommendation. Values: coding, reasoning, general, agent, vision, long-context, cheap, fast",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "for",
            "in": "query",
            "description": "Alias for usecase parameter",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Model recommendation with config example"
          }
        }
      }
    },
    "/config": {
      "get": {
        "operationId": "getConfig",
        "summary": "Agent auto-configuration",
        "description": "Returns full auto-configuration for AI agents: base_url, format, streaming, default model, recommended models, full model list, endpoints, docs/MCP/dashboard links. No authentication required.",
        "tags": [
          "Discovery"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Agent configuration"
          }
        }
      }
    },
    "/capabilities": {
      "get": {
        "operationId": "getCapabilities",
        "summary": "Gateway capabilities",
        "description": "Returns AI-readable summary of gateway capabilities: limits, model count, reliability info, compatibility flags, pricing model. No authentication required.",
        "tags": [
          "Discovery"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Capabilities summary"
          }
        }
      }
    },
    "/credits/pricing": {
      "get": {
        "operationId": "getPricing",
        "summary": "Model pricing table",
        "description": "Returns per-model token pricing. `input_per_1m` / `output_per_1m` are what the model costs TODAY \u2014 the promotional rate while a promotion is running, the list rate otherwise. `list_input_per_1m` / `list_output_per_1m` are the stable rates a promotion returns to and are always present, equal to the first pair when nothing is on offer. `avg_cost_per_request` is a 1,000-in / 500-out estimate at the same rate. No authentication required.",
        "tags": [
          "Discovery"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Pricing table"
          }
        }
      }
    },
    "/credits/balance": {
      "get": {
        "operationId": "getBalance",
        "summary": "Check credit balance",
        "description": "Returns current credit balance for the authenticated user.",
        "tags": [
          "Credits"
        ],
        "responses": {
          "200": {
            "description": "Balance info"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/models/uptime": {
      "get": {
        "operationId": "getUptime",
        "summary": "Model uptime statistics",
        "description": "Returns 7-day per-model uptime percentages. No authentication required.",
        "tags": [
          "Discovery"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Uptime data"
          }
        }
      }
    },
    "/status": {
      "get": {
        "operationId": "getStatus",
        "summary": "Service status",
        "description": "Returns current service status. No authentication required.",
        "tags": [
          "Discovery"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Status info"
          }
        }
      }
    },
    "/auth/register": {
      "post": {
        "operationId": "register",
        "summary": "Create account",
        "description": "Create a new account and get an API key. Returns user_id, api_key (ky-), and session_token (ks-).",
        "tags": [
          "Auth"
        ],
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email",
                  "password"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "password": {
                    "type": "string",
                    "minLength": 6
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Account created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "user_id": {
                      "type": "string"
                    },
                    "api_key": {
                      "type": "string",
                      "description": "Starts with kyma-"
                    },
                    "session_token": {
                      "type": "string",
                      "description": "Starts with ks-"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/auth/login": {
      "post": {
        "operationId": "login",
        "summary": "Login",
        "description": "Sign in and get a session token.",
        "tags": [
          "Auth"
        ],
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email",
                  "password"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "password": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Login successful"
          }
        }
      }
    },
    "/auth/me": {
      "get": {
        "operationId": "getMe",
        "summary": "Get current user",
        "description": "Account identity for the authenticated caller (user_id, email, display_name, email_verified, created_at). API keys and per-key spend are on GET /auth/keys.",
        "tags": [
          "Auth"
        ],
        "responses": {
          "200": {
            "description": "User info"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/auth/keys": {
      "get": {
        "operationId": "listKeys",
        "summary": "List API keys",
        "description": "List all API keys for the authenticated user, each with lifetime usage_cost and usage_requests. Secrets are masked unless the caller is a session.",
        "tags": [
          "Auth"
        ],
        "responses": {
          "200": {
            "description": "API keys list"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/auth/limits": {
      "get": {
        "operationId": "getLimits",
        "summary": "Check rate limits",
        "description": "Check your current tier, rate limits, and usage counters.",
        "tags": [
          "Auth"
        ],
        "responses": {
          "200": {
            "description": "Rate limit info"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Kyma API key (starts with ky-) or session token (starts with ks-)"
      }
    },
    "schemas": {
      "ImageJob": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "type": "string",
            "enum": [
              "image.job"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "processing",
              "succeeded",
              "failed",
              "refunded",
              "expired"
            ]
          },
          "model": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "completed_at": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "output": {
            "type": "object",
            "nullable": true,
            "properties": {
              "url": {
                "type": "string",
                "description": "Vercel Blob URL of the generated image"
              },
              "metadata": {
                "type": "object",
                "properties": {}
              }
            }
          },
          "error": {
            "type": "object",
            "nullable": true,
            "properties": {
              "message": {
                "type": "string"
              },
              "code": {
                "type": "string"
              }
            }
          },
          "estimated_cost": {
            "type": "number",
            "nullable": true,
            "description": "Hold amount placed at submit time (USD), as the ledger holds it. `null` while the job is queued and nothing is held yet."
          },
          "charged_amount": {
            "type": "number",
            "nullable": true,
            "description": "Final billed amount (USD) once the hold is released: what a successful job cost, `0` for a failed or refunded one. `null` until then."
          },
          "refunded_amount": {
            "type": "number",
            "nullable": true,
            "description": "The part of the hold returned to your balance (USD) once it is released. `null` until then."
          }
        }
      },
      "VideoJob": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "type": "string",
            "enum": [
              "video.job"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "processing",
              "succeeded",
              "failed",
              "refunded",
              "expired"
            ]
          },
          "model": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "completed_at": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "output": {
            "type": "object",
            "nullable": true,
            "properties": {
              "url": {
                "type": "string",
                "description": "Vercel Blob URL of the generated video"
              },
              "metadata": {
                "type": "object",
                "properties": {}
              }
            }
          },
          "error": {
            "type": "object",
            "nullable": true,
            "properties": {
              "message": {
                "type": "string"
              },
              "code": {
                "type": "string"
              }
            }
          },
          "estimated_cost": {
            "type": "number",
            "nullable": true,
            "description": "Hold amount placed at submit time (USD), as the ledger holds it. `null` while the job is queued and nothing is held yet."
          },
          "charged_amount": {
            "type": "number",
            "nullable": true,
            "description": "Final billed amount (USD) once the hold is released: what a successful job cost, `0` for a failed or refunded one. `null` until then."
          },
          "refunded_amount": {
            "type": "number",
            "nullable": true,
            "description": "The part of the hold returned to your balance (USD) once it is released. `null` until then."
          }
        }
      },
      "ChatCompletionRequest": {
        "type": "object",
        "properties": {
          "model": {
            "type": "string",
            "description": "Model ID or alias. Aliases: best, fast, code, cheap, long-context, vision, reasoning, agent, balanced",
            "examples": [
              "qwen-3.6-plus",
              "best",
              "code"
            ]
          },
          "messages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Message"
            },
            "description": "Array of messages in the conversation"
          },
          "temperature": {
            "type": "number",
            "minimum": 0,
            "maximum": 2,
            "default": 1,
            "description": "Sampling temperature. Lower = more focused, higher = more creative"
          },
          "max_tokens": {
            "type": "integer",
            "description": "Maximum tokens to generate. Default 4096. Forwarded directly to model with no gateway cap"
          },
          "stream": {
            "type": "boolean",
            "default": false,
            "description": "Stream response as server-sent events"
          },
          "top_p": {
            "type": "number",
            "minimum": 0,
            "maximum": 1,
            "default": 1,
            "description": "Nucleus sampling parameter"
          },
          "tools": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {}
            },
            "description": "List of tools/functions the model can call. Supported on 15/16 models"
          },
          "response_format": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "text",
                  "json_object"
                ]
              }
            },
            "required": [
              "type"
            ],
            "description": "Force output format. Use json_object for structured outputs"
          }
        },
        "required": [
          "model",
          "messages"
        ]
      },
      "Message": {
        "type": "object",
        "properties": {
          "role": {
            "type": "string",
            "enum": [
              "system",
              "user",
              "assistant",
              "tool"
            ]
          },
          "content": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {}
                },
                "description": "Multimodal content (text + images)"
              }
            ]
          },
          "tool_calls": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {}
            },
            "description": "Tool calls made by the assistant"
          },
          "tool_call_id": {
            "type": "string",
            "description": "ID of the tool call this message is responding to"
          }
        },
        "required": [
          "role",
          "content"
        ]
      },
      "ChatCompletionResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "type": "string",
            "enum": [
              "chat.completion"
            ]
          },
          "created": {
            "type": "integer"
          },
          "model": {
            "type": "string",
            "description": "Actual model used"
          },
          "choices": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "index": {
                  "type": "integer"
                },
                "message": {
                  "$ref": "#/components/schemas/Message"
                },
                "finish_reason": {
                  "type": "string",
                  "enum": [
                    "stop",
                    "length",
                    "tool_calls"
                  ]
                }
              },
              "required": [
                "index",
                "message",
                "finish_reason"
              ]
            }
          },
          "usage": {
            "type": "object",
            "properties": {
              "prompt_tokens": {
                "type": "integer"
              },
              "completion_tokens": {
                "type": "integer"
              },
              "total_tokens": {
                "type": "integer"
              },
              "cached_tokens": {
                "type": "integer",
                "description": "Number of prompt tokens served from cache"
              },
              "cost": {
                "type": "number",
                "description": "Cost in USD for this request"
              },
              "cache_discount": {
                "type": "number",
                "description": "Amount saved from prompt caching in USD"
              }
            },
            "required": [
              "prompt_tokens",
              "completion_tokens",
              "total_tokens"
            ]
          }
        },
        "required": [
          "id",
          "object",
          "created",
          "model",
          "choices",
          "usage"
        ]
      },
      "AnthropicMessageRequest": {
        "type": "object",
        "properties": {
          "model": {
            "type": "string"
          },
          "messages": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {}
            }
          },
          "max_tokens": {
            "type": "integer"
          },
          "system": {
            "type": "string"
          },
          "stream": {
            "type": "boolean"
          },
          "tools": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {}
            }
          }
        },
        "required": [
          "model",
          "messages",
          "max_tokens"
        ]
      },
      "ModelList": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "list"
            ]
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Model"
            }
          },
          "aliases": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Map of alias name to resolved model ID"
          }
        }
      },
      "Model": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "context_window": {
            "type": "integer"
          },
          "max_output_tokens": {
            "type": "integer"
          },
          "best_for": {
            "type": "string"
          },
          "speed": {
            "type": "string"
          },
          "recommended": {
            "type": "boolean"
          },
          "hot": {
            "type": "boolean"
          },
          "input_modalities": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "text",
                "image",
                "audio",
                "video",
                "file"
              ]
            }
          },
          "output_modalities": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "text",
                "audio",
                "image"
              ]
            }
          },
          "supported_parameters": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "supports_tools": {
            "type": "boolean"
          },
          "supports_vision": {
            "type": "boolean"
          },
          "supports_reasoning": {
            "type": "boolean"
          },
          "supports_structured_outputs": {
            "type": "boolean"
          },
          "latency_tier": {
            "type": "string",
            "enum": [
              "fast",
              "medium",
              "slow"
            ]
          },
          "cost_tier": {
            "type": "string",
            "enum": [
              "cheap",
              "balanced",
              "premium"
            ]
          },
          "quality_tier": {
            "type": "string",
            "enum": [
              "efficient",
              "strong",
              "frontier-open"
            ]
          },
          "free_tier": {
            "type": "boolean",
            "description": "Whether an account that has never deposited may call this model. `cost_tier` and `tier` are editorial labels; this is the rule the API enforces \u2014 a request for a model with `free_tier: false` from a never-funded key is refused with 402 `model_requires_paid`. Derived from the published price (see the free-tier section of https://docs.kymaapi.com/pricing), so it moves with the catalogue rather than from a hand-kept list.",
            "example": true
          },
          "release_stage": {
            "type": "string",
            "enum": [
              "stable",
              "preview",
              "limited"
            ]
          },
          "release_date": {
            "type": "string",
            "nullable": true,
            "description": "Day the creator publicly released this model, `YYYY-MM-DD`. Null when the creator never stated one. Not to be confused with `created`, which timestamps this response.",
            "example": "2026-07-28"
          },
          "type": {
            "type": "string",
            "enum": [
              "language",
              "image",
              "video",
              "embedding",
              "reranking",
              "transcription",
              "audio-understanding",
              "realtime",
              "speech",
              "decisions"
            ]
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "tool-use",
                "reasoning",
                "vision",
                "implicit-caching",
                "explicit-caching",
                "file-input",
                "web-search",
                "image-generation",
                "video-generation",
                "websocket-realtime",
                "websocket-transcription",
                "fast"
              ]
            }
          },
          "use_cases": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "recommended_for": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Deprecated alias of use_cases."
          },
          "pricing": {
            "type": "object",
            "properties": {
              "mode": {
                "type": "string"
              },
              "input": {
                "type": "number"
              },
              "output": {
                "type": "number"
              },
              "per_image_usd": {
                "type": "number"
              },
              "per_second_usd": {
                "type": "number"
              },
              "per_video_usd": {
                "type": "number"
              },
              "per_minute_usd": {
                "type": "number"
              },
              "per_kchar_usd": {
                "type": "number"
              },
              "per_song_usd": {
                "type": "number"
              },
              "per_call_usd": {
                "type": "number"
              }
            },
            "description": "What this model costs TODAY \u2014 the promotional rate while a promotion is running, the list rate otherwise. Token rates are USD per 1M tokens."
          },
          "list_price": {
            "type": "object",
            "properties": {
              "mode": {
                "type": "string"
              },
              "input": {
                "type": "number"
              },
              "output": {
                "type": "number"
              },
              "per_image_usd": {
                "type": "number"
              },
              "per_second_usd": {
                "type": "number"
              },
              "per_video_usd": {
                "type": "number"
              },
              "per_minute_usd": {
                "type": "number"
              },
              "per_kchar_usd": {
                "type": "number"
              },
              "per_song_usd": {
                "type": "number"
              },
              "per_call_usd": {
                "type": "number"
              }
            },
            "description": "The stable rate a promotion returns to. Always present, and equal to `pricing` when no promotion is running, so a client can read one field unconditionally."
          },
          "promotion": {
            "type": "object",
            "nullable": true,
            "properties": {
              "input": {
                "type": "number"
              },
              "output": {
                "type": "number"
              },
              "list_input": {
                "type": "number"
              },
              "list_output": {
                "type": "number"
              },
              "percent_off": {
                "type": "integer"
              },
              "ends": {
                "type": "string"
              }
            },
            "required": [
              "input",
              "output",
              "list_input",
              "list_output",
              "percent_off",
              "ends"
            ],
            "description": "The promotion in force, or null. `input`/`output` repeat `pricing`; `list_input`/`list_output` repeat `list_price`; `ends` is the inclusive `YYYY-MM-DD` date the promotional rate is promised through."
          },
          "gateway_output_limit": {
            "type": "null",
            "description": "Always null. Kyma does not impose output limits"
          },
          "max_tokens_passthrough": {
            "type": "boolean",
            "enum": [
              true
            ],
            "description": "Always true. max_tokens is forwarded directly to the model"
          }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "message": {
                "type": "string",
                "description": "One sentence: what happened and what to do next."
              },
              "type": {
                "type": "string",
                "enum": [
                  "invalid_request_error",
                  "authentication_error",
                  "billing_error",
                  "permission_error",
                  "not_found_error",
                  "request_too_large",
                  "rate_limit_error",
                  "timeout_error",
                  "upstream_error",
                  "api_error"
                ],
                "description": "The category. On /v1/messages, Anthropic's error type for the same condition."
              },
              "code": {
                "type": "string",
                "enum": [
                  "missing_api_key",
                  "invalid_api_key",
                  "invalid_login",
                  "invalid_google_token",
                  "permission_denied",
                  "voice_not_owned",
                  "session_required",
                  "csrf_failed",
                  "route_refused",
                  "content_refused",
                  "invalid_json",
                  "missing_parameter",
                  "invalid_parameter",
                  "wrong_endpoint",
                  "unsupported_content",
                  "unsupported_media_type",
                  "request_rejected",
                  "no_speech_detected",
                  "segments_unsupported",
                  "method_not_allowed",
                  "captcha_failed",
                  "invalid_signature",
                  "account_exists",
                  "request_too_large",
                  "request_exceeds_tier_limit",
                  "endpoint_not_found",
                  "endpoint_retired",
                  "model_not_found",
                  "model_retired",
                  "job_not_found",
                  "model_requires_paid",
                  "insufficient_credits",
                  "tier_required",
                  "payment_required",
                  "rate_limit_exceeded",
                  "concurrency_limit_exceeded",
                  "media_rate_exceeded",
                  "queue_full",
                  "too_many_sessions",
                  "too_many_attempts",
                  "signup_paused",
                  "upstream_rate_limited",
                  "provider_unavailable",
                  "model_unavailable",
                  "upstream_invalid_response",
                  "upstream_timeout",
                  "stream_interrupted",
                  "upload_timeout",
                  "service_unavailable",
                  "internal_error",
                  "signup_failed",
                  "settle_failed"
                ],
                "description": "Stable machine code: added, never renamed or removed. Each has an entry at https://docs.kymaapi.com/api-reference/errors"
              },
              "param": {
                "type": "string",
                "nullable": true,
                "description": "The request field at fault, or null."
              },
              "retryable": {
                "type": "boolean",
                "description": "Whether the same request can succeed if sent again (after `Retry-After`). Also sent as the `x-should-retry` header."
              },
              "request_id": {
                "type": "string",
                "description": "Same value as the `x-request-id` header. Quote it to support.",
                "example": "req_7f3c2a9e0b1d4c6f8a2e5b7d9c1f3a5e"
              },
              "doc_url": {
                "type": "string",
                "description": "This code's entry on the errors page.",
                "example": "https://docs.kymaapi.com/api-reference/errors#insufficient_credits"
              }
            },
            "required": [
              "message",
              "type",
              "code"
            ]
          }
        },
        "required": [
          "error"
        ],
        "description": "Every error body. On /v1/messages the same object sits in Anthropic's envelope: `type: \"error\"` on top, an Anthropic `error.type`, and `request_id` also at the top level."
      },
      "AudioBilling": {
        "type": "object",
        "properties": {
          "duration_sec": {
            "type": "number",
            "description": "Audio duration in seconds."
          },
          "billable_minutes": {
            "type": "integer",
            "description": "Minutes charged. Audio is billed in 1-minute increments, rounded up."
          },
          "cost_usd": {
            "type": "number",
            "description": "Final cost charged for this request."
          },
          "balance_usd": {
            "type": "number",
            "description": "Remaining account balance after this charge."
          },
          "duration_source": {
            "type": "string",
            "enum": [
              "upstream_usage",
              "file_bound"
            ],
            "description": "Only present on /audio/understand responses. `upstream_usage`: billed seconds are the input the model consumed (audio and question). `file_bound`: the model reported no usage, so the file's own length bound was billed."
          }
        },
        "description": "Per-request billing breakdown for audio endpoints (per-minute billing)."
      },
      "PaymentRequired": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "message": {
                "type": "string"
              },
              "type": {
                "type": "string",
                "enum": [
                  "billing_error"
                ],
                "description": "Always `billing_error`, on every surface."
              },
              "code": {
                "type": "string",
                "enum": [
                  "model_requires_paid",
                  "insufficient_credits"
                ],
                "description": "The rule that refused."
              },
              "param": {
                "type": "string",
                "nullable": true
              },
              "retryable": {
                "type": "boolean"
              },
              "request_id": {
                "type": "string"
              },
              "doc_url": {
                "type": "string"
              }
            }
          },
          "type": {
            "type": "string",
            "enum": [
              "error"
            ],
            "description": "Anthropic-compat envelope marker. Only on /v1/messages."
          },
          "topup": {
            "type": "string",
            "description": "Machine top-up endpoint. An agent with a wallet and no human can pay here; it is a hint in the body, never a payment challenge.",
            "example": "https://api.kymaapi.com/v1/topup"
          },
          "need_usd": {
            "type": "number",
            "description": "Worst-case cost of this request, USD. `insufficient_credits` only."
          },
          "have_usd": {
            "type": "number",
            "description": "Spendable credit at the moment of the refusal, USD. `insufficient_credits` only."
          },
          "balance": {
            "type": "number",
            "description": "Mirror of `details.balance`."
          },
          "required": {
            "type": "number",
            "description": "Mirror of `details.required`. Zero on `model_requires_paid`: no top-up amount makes a premium model callable on signup credit."
          },
          "topup_url": {
            "type": "string",
            "description": "Billing page for a human. Mirror of `details.topup_url`.",
            "example": "https://kymaapi.com/billing"
          },
          "details": {
            "type": "object",
            "properties": {
              "balance": {
                "type": "number"
              },
              "required": {
                "type": "number"
              },
              "topup_url": {
                "type": "string"
              },
              "hint": {
                "type": "string"
              },
              "endpoint_id": {
                "type": "string",
                "description": "The model the caller asked for."
              }
            },
            "description": "The nested envelope the media, audio and Anthropic-compat surfaces emit. Read this first; the top-level mirrors exist for older parsers. (/v1/embeddings emits the same envelope for a low balance, but it has its own check rather than this gate, so it carries neither code.)"
          }
        },
        "description": "402 \u2014 the access gate refused. `model_requires_paid` (signup credit is a free tier, not the whole catalogue) or `insufficient_credits` (the balance does not cover the request)."
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Bad request",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing or invalid API key",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "PaymentRequired": {
        "description": "Payment required. One gate decides every refusal and `error.code` names the rule that fired: `model_requires_paid` (the account has never deposited and this model is outside the free tier, which `free_tier` on `GET /v1/models` states in advance) or `insufficient_credits` (the balance does not cover the request; `need_usd` and `have_usd` say by how much). `error.type` is `billing_error` on every surface, /v1/messages included. `topup` is the machine endpoint an agent can pay without a human; `topup_url` is the page for a human.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/PaymentRequired"
            },
            "examples": {
              "model_requires_paid": {
                "summary": "Never funded, premium model \u2014 /chat/completions, /completions",
                "value": {
                  "topup": "https://api.kymaapi.com/v1/topup",
                  "balance": 0.5,
                  "required": 0,
                  "topup_url": "https://kymaapi.com/billing",
                  "error": {
                    "message": "This model requires a funded balance. Signup credit covers lower-cost models. Top up at https://kymaapi.com/billing",
                    "type": "billing_error",
                    "code": "model_requires_paid",
                    "param": null,
                    "retryable": false,
                    "doc_url": "https://docs.kymaapi.com/api-reference/errors#model_requires_paid"
                  },
                  "details": {
                    "balance": 0.5,
                    "required": 0,
                    "topup_url": "https://kymaapi.com/billing",
                    "hint": "Top up at https://kymaapi.com/billing to continue, or POST https://api.kymaapi.com/v1/topup to pay without one",
                    "endpoint_id": "claude-fable-5.1"
                  }
                }
              },
              "insufficient_credits": {
                "summary": "Balance below the worst case \u2014 /chat/completions, /completions",
                "value": {
                  "need_usd": 0.012562,
                  "have_usd": 0.0004,
                  "topup": "https://api.kymaapi.com/v1/topup",
                  "balance": 0.0004,
                  "required": 0.012562,
                  "topup_url": "https://kymaapi.com/billing",
                  "error": {
                    "message": "This request needs about $0.01 of credit; you have $0.0004. Top up at https://kymaapi.com/billing or lower max_tokens.",
                    "type": "billing_error",
                    "code": "insufficient_credits",
                    "param": null,
                    "retryable": false,
                    "doc_url": "https://docs.kymaapi.com/api-reference/errors#insufficient_credits"
                  },
                  "details": {
                    "balance": 0.0004,
                    "required": 0.012562,
                    "topup_url": "https://kymaapi.com/billing",
                    "hint": "Top up at least $0.02 to run this model \u2014 a human can top up at https://kymaapi.com/billing, or POST https://api.kymaapi.com/v1/topup to pay without one",
                    "endpoint_id": "deepseek-v3"
                  }
                }
              },
              "model_requires_paid_messages": {
                "summary": "Never funded, premium model \u2014 /messages (Anthropic-compat envelope)",
                "value": {
                  "type": "error",
                  "topup": "https://api.kymaapi.com/v1/topup",
                  "balance": 0.5,
                  "required": 0,
                  "topup_url": "https://kymaapi.com/billing",
                  "error": {
                    "message": "This model requires a funded balance. Signup credit covers lower-cost models. Top up at https://kymaapi.com/billing",
                    "type": "billing_error",
                    "code": "model_requires_paid",
                    "param": null,
                    "retryable": false,
                    "doc_url": "https://docs.kymaapi.com/api-reference/errors#model_requires_paid"
                  },
                  "details": {
                    "balance": 0.5,
                    "required": 0,
                    "topup_url": "https://kymaapi.com/billing",
                    "hint": "Top up at https://kymaapi.com/billing to continue, or POST https://api.kymaapi.com/v1/topup to pay without one",
                    "endpoint_id": "claude-fable-5.1"
                  }
                }
              },
              "model_requires_paid_media": {
                "summary": "Never funded, premium SKU \u2014 media and audio surfaces (D3 envelope)",
                "value": {
                  "topup": "https://api.kymaapi.com/v1/topup",
                  "balance": 0.5,
                  "required": 0,
                  "topup_url": "https://kymaapi.com/billing",
                  "error": {
                    "message": "gpt-image-2 is not in the free tier; add credits to use it. Free-tier media: gemini-3.5-transcribe, gpt-4o-mini-transcribe-2025-12-15, gpt-transcribe, minimax-image-01, whisper-v3-turbo.",
                    "type": "billing_error",
                    "code": "model_requires_paid",
                    "param": null,
                    "retryable": false,
                    "doc_url": "https://docs.kymaapi.com/api-reference/errors#model_requires_paid"
                  },
                  "details": {
                    "balance": 0.5,
                    "required": 0,
                    "topup_url": "https://kymaapi.com/billing",
                    "hint": "Top up at https://kymaapi.com/billing to continue, or POST https://api.kymaapi.com/v1/topup to pay without one",
                    "endpoint_id": "gpt-image-2"
                  }
                }
              },
              "insufficient_credits_media": {
                "summary": "Balance below the job estimate \u2014 media and audio surfaces (D3 envelope)",
                "value": {
                  "need_usd": 0.054,
                  "have_usd": 0.01,
                  "topup": "https://api.kymaapi.com/v1/topup",
                  "balance": 0.01,
                  "required": 0.054,
                  "topup_url": "https://kymaapi.com/billing",
                  "error": {
                    "message": "This request needs about $0.05 of credit; you have $0.01. Top up at https://kymaapi.com/billing.",
                    "type": "billing_error",
                    "code": "insufficient_credits",
                    "param": null,
                    "retryable": false,
                    "doc_url": "https://docs.kymaapi.com/api-reference/errors#insufficient_credits"
                  },
                  "details": {
                    "balance": 0.01,
                    "required": 0.054,
                    "topup_url": "https://kymaapi.com/billing",
                    "hint": "Top up at least $0.06 to run this model \u2014 a human can top up at https://kymaapi.com/billing, or POST https://api.kymaapi.com/v1/topup to pay without one",
                    "endpoint_id": "gpt-image-2"
                  }
                }
              }
            }
          }
        }
      },
      "RateLimited": {
        "description": "Rate limit exceeded",
        "headers": {
          "Retry-After": {
            "description": "Seconds until the rate limit resets",
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Forbidden": {
        "description": "Valid key, but this request is not allowed (for example `route_refused`: every route for the model refused the content).",
        "headers": {
          "x-request-id": {
            "description": "Request id, on every response. Quote it to support.",
            "schema": {
              "type": "string"
            }
          },
          "x-should-retry": {
            "description": "`true` when the same request can succeed if retried.",
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "Unknown model (`model_not_found`, `model_retired` with `did_you_mean`) or endpoint.",
        "headers": {
          "x-request-id": {
            "description": "Request id, on every response. Quote it to support.",
            "schema": {
              "type": "string"
            }
          },
          "x-should-retry": {
            "description": "`true` when the same request can succeed if retried.",
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "PayloadTooLarge": {
        "description": "Request body over the endpoint limit (`request_too_large`).",
        "headers": {
          "x-request-id": {
            "description": "Request id, on every response. Quote it to support.",
            "schema": {
              "type": "string"
            }
          },
          "x-should-retry": {
            "description": "`true` when the same request can succeed if retried.",
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "ServiceUnavailable": {
        "description": "The model or Kyma is unavailable right now (`provider_unavailable`, `model_unavailable`, `service_unavailable`). Retry after `Retry-After`.",
        "headers": {
          "x-request-id": {
            "description": "Request id, on every response. Quote it to support.",
            "schema": {
              "type": "string"
            }
          },
          "x-should-retry": {
            "description": "`true` when the same request can succeed if retried.",
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    }
  },
  "tags": [
    {
      "name": "Chat",
      "description": "Chat completion endpoints (OpenAI + Anthropic format)"
    },
    {
      "name": "Models",
      "description": "Model catalog, recommendations, and filtering"
    },
    {
      "name": "Discovery",
      "description": "Auto-configuration and capability discovery (no auth required)"
    },
    {
      "name": "Credits",
      "description": "Balance and pricing"
    },
    {
      "name": "Auth",
      "description": "Account management and API keys"
    }
  ]
}
