{"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 — 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 — the smallest amount the ledger holds — 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\": \"…\", \"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 — models, pricing, streaming, failover — 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 — 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× 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 — invalid keys return 400 from the provider, not 500."}}}}}},"responses":{"200":{"description":"Idempotent replay — 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 — SubRip subtitle file"}},"text/vtt; charset=utf-8":{"schema":{"type":"string","description":"response_format=vtt — 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 — alias of use_cases, kept for existing callers. Accepts the pre-2026-07-27 vocabulary (coding, agent, general, image, video, transcribe, …) 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 — 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 — 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 — 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 — 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 — /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 — /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 — 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 — /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 — 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 — 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 — 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"}]}