{
  "openapi": "3.1.0",
  "info": {
    "title": "Krater API",
    "version": "1.0.0",
    "summary": "OpenAI-compatible REST API for 500+ AI models",
    "description": "The Krater API gives you one key and one base URL for chat completions, image generation and editing, video generation, text-to-speech, transcription, music, sound effects, AI text detection, humanizing, plagiarism checks, summarization, web search, code generation, and document generation. Requests and responses follow OpenAI-compatible shapes wherever an OpenAI equivalent exists. Every request is billed in Krater credits from your subscription's shared credit pool. Full documentation with examples: https://krater.ai/developers",
    "termsOfService": "https://krater.ai/policies?tab=terms",
    "contact": {
      "name": "Krater Support",
      "email": "hey@krater.ai",
      "url": "https://krater.ai/help/contact"
    }
  },
  "servers": [
    {
      "url": "https://api.krater.ai/v1",
      "description": "Production"
    }
  ],
  "security": [
    {
      "apiKey": []
    }
  ],
  "tags": [
    { "name": "chat", "description": "Chat and code completions" },
    { "name": "images", "description": "Image generation, editing and upscaling" },
    { "name": "videos", "description": "Video generation" },
    { "name": "audio", "description": "Speech, transcription, music, sound effects, voice change and realtime voice" },
    { "name": "text", "description": "AI detection, humanizing, plagiarism and summarization" },
    { "name": "search", "description": "AI-powered web search" },
    { "name": "documents", "description": "Document generation" },
    { "name": "models", "description": "Model catalog" }
  ],
  "paths": {
    "/chat/completions": {
      "post": {
        "operationId": "createChatCompletion",
        "tags": ["chat"],
        "summary": "Create a chat completion",
        "description": "Generate a chat completion with any of Krater's 500+ chat models. OpenAI-compatible request and response format, including streaming via server-sent events when stream is true. Credits are charged dynamically based on the model and token usage.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/ChatCompletionRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Chat completion (JSON object, or a text/event-stream of chunks when stream is true).",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ChatCompletionResponse" }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "402": { "$ref": "#/components/responses/InsufficientCredits" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/images/generations": {
      "post": {
        "operationId": "createImage",
        "tags": ["images"],
        "summary": "Generate images from text",
        "description": "Generate one or more images from a text prompt. Supported models include flux-2 (and its pro, max, flex, flash, turbo and klein variants), gpt-image-2, grok-imagine, nano-banana, nano-banana-2, nano-banana-2-lite, recraft, ideogram, seedream, z-image-turbo and kling. Credits vary by model, from 2 to about 63 per image.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/ImageGenerationRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Generated image URLs.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ImageResponse" }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "402": { "$ref": "#/components/responses/InsufficientCredits" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/images/edits": {
      "post": {
        "operationId": "editImage",
        "tags": ["images"],
        "summary": "Edit an existing image",
        "description": "Transform an existing image with a text prompt. Pass the source image as a public URL in image_url (a single URL, or an array of URLs for models that accept multiple reference images). Credits vary by model, from about 6 to 70 per edit.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/ImageEditRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Edited image URLs.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ImageResponse" }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "402": { "$ref": "#/components/responses/InsufficientCredits" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/images/upscale": {
      "post": {
        "operationId": "upscaleImage",
        "tags": ["images"],
        "summary": "Upscale an image",
        "description": "Upscale an image with the Crystal upscaler. The scale factor is clamped to supported values (2x or 4x) and credits are charged based on the output size in megapixels.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/ImageUpscaleRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Upscaled image URL.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ImageResponse" }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "402": { "$ref": "#/components/responses/InsufficientCredits" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/videos/generations": {
      "post": {
        "operationId": "createVideo",
        "tags": ["videos"],
        "summary": "Generate a video from text",
        "description": "Create a video from a text prompt. Supported models include LTX, Wan, MiniMax, Kling, Seedance, Veo and Sora families. Credits are charged dynamically based on model, duration and resolution.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/VideoGenerationRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Generated video URL.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/VideoResponse" }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "402": { "$ref": "#/components/responses/InsufficientCredits" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/audio/speech": {
      "post": {
        "operationId": "createSpeech",
        "tags": ["audio"],
        "summary": "Text-to-speech",
        "description": "Convert text to spoken audio. Supports OpenAI voices (tts-1, tts-1-hd) and ElevenLabs voices. Returns binary audio.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/SpeechRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Binary audio data.",
            "content": {
              "audio/mpeg": {
                "schema": { "type": "string", "format": "binary" }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "402": { "$ref": "#/components/responses/InsufficientCredits" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/audio/transcriptions": {
      "post": {
        "operationId": "createTranscription",
        "tags": ["audio"],
        "summary": "Speech-to-text",
        "description": "Transcribe an audio file to text. Send the audio as multipart/form-data with a file field.",
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": ["file"],
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary",
                    "description": "The audio file to transcribe (for example mp3, wav, m4a)."
                  },
                  "model": {
                    "type": "string",
                    "description": "Transcription model identifier.",
                    "examples": ["whisper-large-v3"]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Transcription result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["text"],
                  "properties": {
                    "text": { "type": "string", "description": "The transcribed text." }
                  }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "402": { "$ref": "#/components/responses/InsufficientCredits" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/audio/music": {
      "post": {
        "operationId": "createMusic",
        "tags": ["audio"],
        "summary": "Generate music",
        "description": "Generate original music from a text description.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["prompt"],
                "properties": {
                  "prompt": { "type": "string", "description": "Description of the music to generate, including style, mood and tempo." },
                  "duration": { "type": "integer", "description": "Track length in seconds.", "examples": [30] }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Generated audio URL.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/MediaUrlResponse" }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "402": { "$ref": "#/components/responses/InsufficientCredits" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/audio/effects": {
      "post": {
        "operationId": "createSoundEffect",
        "tags": ["audio"],
        "summary": "Generate a sound effect",
        "description": "Generate a custom sound effect from a text description. Duration 1 to 30 seconds.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["prompt"],
                "properties": {
                  "prompt": { "type": "string", "description": "Description of the sound effect." },
                  "duration": { "type": "integer", "minimum": 1, "maximum": 30, "description": "Effect length in seconds." }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Generated audio URL.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/MediaUrlResponse" }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "402": { "$ref": "#/components/responses/InsufficientCredits" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/audio/voice-change": {
      "post": {
        "operationId": "changeVoice",
        "tags": ["audio"],
        "summary": "Change the voice of an audio file",
        "description": "Re-voice existing speech audio using an ElevenLabs voice. Returns binary audio.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["audio_url", "voice"],
                "properties": {
                  "audio_url": { "type": "string", "format": "uri", "description": "Public URL of the source audio file." },
                  "voice": { "type": "string", "description": "ElevenLabs voice ID to apply." }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Binary audio data.",
            "content": {
              "audio/mpeg": {
                "schema": { "type": "string", "format": "binary" }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "402": { "$ref": "#/components/responses/InsufficientCredits" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/audio/realtime/sessions": {
      "post": {
        "operationId": "createRealtimeSession",
        "tags": ["audio"],
        "summary": "Create a realtime voice session",
        "description": "Create an ephemeral realtime voice session. Returns a short-lived client secret for the WebRTC connection plus a reservation_id that must be settled with finalizeRealtimeSession when the call ends.",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "voice": {
                    "type": "string",
                    "enum": ["alloy", "ash", "coral", "echo", "shimmer", "verse"],
                    "default": "alloy",
                    "description": "Voice for the assistant's audio output."
                  },
                  "instructions": { "type": "string", "description": "System instructions for the voice assistant." }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Ephemeral session credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "client_secret": { "type": "string", "description": "Ephemeral key used as Bearer auth for the WebRTC SDP exchange." },
                    "reservation_id": { "type": "string", "description": "Credit reservation to settle via /audio/realtime/finalize when the session ends." },
                    "session_id": { "type": "string" },
                    "expires_at": { "type": "integer", "description": "Unix timestamp when the client secret expires." },
                    "created_at": { "type": "string", "format": "date-time" },
                    "voice": { "type": "string" },
                    "model": { "type": "string" },
                    "webrtc_url": { "type": "string", "format": "uri", "description": "WebRTC SDP exchange endpoint." }
                  }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "402": { "$ref": "#/components/responses/InsufficientCredits" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/audio/realtime/finalize": {
      "post": {
        "operationId": "finalizeRealtimeSession",
        "tags": ["audio"],
        "summary": "Finalize a realtime voice session",
        "description": "Settle the credit reservation for a finished realtime voice session based on its actual duration.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["reservation_id", "duration_seconds"],
                "properties": {
                  "reservation_id": { "type": "string", "description": "The reservation_id returned by createRealtimeSession." },
                  "duration_seconds": { "type": "number", "description": "Actual session duration in seconds." }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Reservation settled.",
            "content": {
              "application/json": {
                "schema": { "type": "object", "additionalProperties": true }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/text/detect": {
      "post": {
        "operationId": "detectAiText",
        "tags": ["text"],
        "summary": "Detect AI-written text",
        "description": "Estimate whether a text was written by AI or a human.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/TextRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Detection result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ai_probability": { "type": "number", "minimum": 0, "maximum": 1 },
                    "human_probability": { "type": "number", "minimum": 0, "maximum": 1 },
                    "verdict": { "type": "string", "description": "Overall verdict, for example ai or human." }
                  }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "402": { "$ref": "#/components/responses/InsufficientCredits" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/text/humanize": {
      "post": {
        "operationId": "humanizeText",
        "tags": ["text"],
        "summary": "Humanize AI-generated text",
        "description": "Rewrite AI-generated text so it reads naturally.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/TextRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Rewritten text.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["text"],
                  "properties": {
                    "text": { "type": "string", "description": "The humanized text." }
                  }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "402": { "$ref": "#/components/responses/InsufficientCredits" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/text/plagiarism": {
      "post": {
        "operationId": "checkPlagiarism",
        "tags": ["text"],
        "summary": "Check text for plagiarism",
        "description": "Check a text against web sources for plagiarism.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/TextRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Plagiarism result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "score": { "type": "number", "minimum": 0, "maximum": 1, "description": "Overall similarity score." },
                    "sources": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "url": { "type": "string", "format": "uri" },
                          "similarity": { "type": "number", "minimum": 0, "maximum": 1 }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "402": { "$ref": "#/components/responses/InsufficientCredits" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/text/summarize": {
      "post": {
        "operationId": "summarize",
        "tags": ["text"],
        "summary": "Summarize a URL or text",
        "description": "Summarize the content of a web page (pass url) or a raw text (pass text). Provide exactly one of the two.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": { "type": "string", "format": "uri", "description": "URL of the page to summarize." },
                  "text": { "type": "string", "description": "Raw text to summarize." }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Summary.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "summary": { "type": "string" },
                    "source": { "type": "string", "description": "The summarized URL, when a url was provided." }
                  }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "402": { "$ref": "#/components/responses/InsufficientCredits" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/search": {
      "post": {
        "operationId": "webSearch",
        "tags": ["search"],
        "summary": "AI-powered web search",
        "description": "Search the web and get an AI-summarized answer in an OpenAI chat-completion shape.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["query"],
                "properties": {
                  "query": { "type": "string", "description": "The search query." }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Summarized search answer.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ChatCompletionResponse" }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "402": { "$ref": "#/components/responses/InsufficientCredits" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/code/completions": {
      "post": {
        "operationId": "createCodeCompletion",
        "tags": ["chat"],
        "summary": "Generate or explain code",
        "description": "Generate, complete or explain code with top coding models. Accepts either a prompt string or an OpenAI-style messages array. Also available at /code/chat/completions.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "prompt": { "type": "string", "description": "Instruction or code to complete. Alternative to messages." },
                  "messages": {
                    "type": "array",
                    "items": { "$ref": "#/components/schemas/ChatMessage" },
                    "description": "OpenAI-style conversation. Alternative to prompt."
                  },
                  "model": { "type": "string", "description": "Model identifier.", "examples": ["anthropic/claude-sonnet-4"] },
                  "language": { "type": "string", "description": "Programming language hint.", "examples": ["python"] }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Code completion in an OpenAI chat-completion shape.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ChatCompletionResponse" }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "402": { "$ref": "#/components/responses/InsufficientCredits" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/documents/generations": {
      "post": {
        "operationId": "createDocument",
        "tags": ["documents"],
        "summary": "Generate a document",
        "description": "Generate a professional document, essay or report from a prompt.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["prompt"],
                "properties": {
                  "prompt": { "type": "string", "description": "What the document should contain." },
                  "format": { "type": "string", "description": "Output format.", "examples": ["markdown"] },
                  "model": { "type": "string", "description": "Model identifier.", "examples": ["openai/gpt-4o"] }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Generated document in an OpenAI chat-completion shape.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ChatCompletionResponse" }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "402": { "$ref": "#/components/responses/InsufficientCredits" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/models": {
      "get": {
        "operationId": "listModels",
        "tags": ["models"],
        "summary": "List available models",
        "description": "Retrieve the catalog of available models across chat, image, video and audio. Free to call.",
        "responses": {
          "200": {
            "description": "Model list.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["object", "data"],
                  "properties": {
                    "object": { "type": "string", "const": "list" },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": ["id", "object"],
                        "properties": {
                          "id": { "type": "string", "examples": ["openai/gpt-4o"] },
                          "object": { "type": "string", "const": "model" },
                          "owned_by": { "type": "string", "examples": ["openai"] }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "kr_live_...",
        "description": "Krater API key. Create one in Settings -> API on an Ultra or Max plan. Keys start with kr_live_ followed by 40 hex characters. Pass it as: Authorization: Bearer kr_live_..."
      }
    },
    "schemas": {
      "ChatMessage": {
        "type": "object",
        "required": ["role", "content"],
        "properties": {
          "role": { "type": "string", "enum": ["system", "user", "assistant", "tool"] },
          "content": { "type": "string", "description": "Message text." }
        }
      },
      "ChatCompletionRequest": {
        "type": "object",
        "required": ["model", "messages"],
        "properties": {
          "model": { "type": "string", "description": "Model identifier, for example openai/gpt-4o-mini. Call listModels for the full catalog.", "examples": ["openai/gpt-4o-mini"] },
          "messages": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/ChatMessage" },
            "description": "The conversation so far."
          },
          "stream": { "type": "boolean", "default": false, "description": "Stream the response as server-sent events." },
          "temperature": { "type": "number", "minimum": 0, "maximum": 2 },
          "max_tokens": { "type": "integer", "minimum": 1 },
          "top_p": { "type": "number", "minimum": 0, "maximum": 1 },
          "frequency_penalty": { "type": "number", "minimum": -2, "maximum": 2 },
          "presence_penalty": { "type": "number", "minimum": -2, "maximum": 2 },
          "stop": {
            "description": "Up to 4 sequences where generation stops.",
            "oneOf": [
              { "type": "string" },
              { "type": "array", "items": { "type": "string" }, "maxItems": 4 }
            ]
          },
          "tools": {
            "type": "array",
            "description": "OpenAI-style tool definitions for function calling.",
            "items": {
              "type": "object",
              "required": ["type", "function"],
              "properties": {
                "type": { "type": "string", "const": "function" },
                "function": {
                  "type": "object",
                  "required": ["name"],
                  "properties": {
                    "name": { "type": "string" },
                    "description": { "type": "string" },
                    "parameters": { "type": "object", "description": "JSON Schema for the function arguments." }
                  }
                }
              }
            }
          },
          "tool_choice": {
            "description": "Controls which tool the model may call.",
            "oneOf": [
              { "type": "string", "enum": ["none", "auto", "required"] },
              { "type": "object" }
            ]
          },
          "parallel_tool_calls": { "type": "boolean" }
        }
      },
      "ChatCompletionResponse": {
        "type": "object",
        "required": ["id", "object", "choices"],
        "properties": {
          "id": { "type": "string", "examples": ["chatcmpl-abc123"] },
          "object": { "type": "string", "const": "chat.completion" },
          "created": { "type": "integer", "description": "Unix timestamp." },
          "model": { "type": "string" },
          "choices": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "index": { "type": "integer" },
                "message": { "$ref": "#/components/schemas/ChatMessage" },
                "finish_reason": { "type": "string", "examples": ["stop"] }
              }
            }
          },
          "usage": {
            "type": "object",
            "properties": {
              "prompt_tokens": { "type": "integer" },
              "completion_tokens": { "type": "integer" },
              "total_tokens": { "type": "integer" }
            }
          }
        }
      },
      "ImageGenerationRequest": {
        "type": "object",
        "required": ["prompt"],
        "properties": {
          "prompt": { "type": "string", "description": "Text description of the image to generate." },
          "model": { "type": "string", "description": "Image model identifier.", "examples": ["flux-2"] },
          "size": { "type": "string", "description": "Output size or aspect ratio, model dependent.", "examples": ["1024x1024"] },
          "n": { "type": "integer", "minimum": 1, "description": "Number of images to generate.", "default": 1 },
          "resolution": { "type": "string", "description": "Output resolution for models that support it, for example 1K, 2K or 4K." },
          "quality": { "type": "string", "description": "Quality setting for models that support it, for example low, medium or high." },
          "rendering_speed": { "type": "string", "description": "Rendering speed for Ideogram models, for example TURBO." },
          "style": { "type": "string", "description": "Style preset for models that support it." },
          "version": { "type": "string", "description": "Specific model version to pin, when the model has multiple versions." }
        }
      },
      "ImageEditRequest": {
        "type": "object",
        "required": ["prompt", "image_url"],
        "properties": {
          "prompt": { "type": "string", "description": "How to transform the image." },
          "image_url": {
            "description": "Public URL of the source image, or an array of URLs for models that accept multiple references.",
            "oneOf": [
              { "type": "string", "format": "uri" },
              { "type": "array", "items": { "type": "string", "format": "uri" } }
            ]
          },
          "model": { "type": "string", "description": "Image model identifier.", "examples": ["flux-2-flex"] },
          "strength": { "type": "number", "minimum": 0, "maximum": 1, "description": "How strongly to transform the source image." },
          "size": { "type": "string", "description": "Output size or aspect ratio, model dependent." },
          "resolution": { "type": "string", "description": "Output resolution for models that support it." },
          "quality": { "type": "string", "description": "Quality setting for models that support it." },
          "style": { "type": "string", "description": "Style preset for models that support it." },
          "version": { "type": "string", "description": "Specific model version to pin." }
        }
      },
      "ImageUpscaleRequest": {
        "type": "object",
        "required": ["image_url"],
        "properties": {
          "image_url": { "type": "string", "format": "uri", "description": "Public URL of the image to upscale." },
          "scale": { "type": "number", "description": "Upscale factor, clamped to supported values (2 or 4).", "examples": [2] }
        }
      },
      "ImageResponse": {
        "type": "object",
        "required": ["created", "data"],
        "properties": {
          "created": { "type": "integer", "description": "Unix timestamp." },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "required": ["url"],
              "properties": {
                "url": { "type": "string", "format": "uri", "description": "URL of the generated image." }
              }
            }
          }
        }
      },
      "VideoGenerationRequest": {
        "type": "object",
        "required": ["prompt"],
        "properties": {
          "prompt": { "type": "string", "description": "Text description of the video to generate." },
          "model": { "type": "string", "description": "Video model identifier.", "examples": ["kling-2.6"] },
          "duration": { "type": "integer", "description": "Video length in seconds, model dependent.", "examples": [5] },
          "aspect_ratio": { "type": "string", "description": "Aspect ratio, for example 16:9 or 9:16.", "examples": ["16:9"] },
          "resolution": { "type": "string", "description": "Output resolution for models that support it, for example 720p or 1080p." },
          "pro": { "type": "boolean", "description": "Use the pro tier of the model, when available." },
          "generate_audio": { "type": "boolean", "description": "Generate native audio, for models that support it." },
          "version": { "type": "string", "description": "Specific model version to pin." }
        }
      },
      "VideoResponse": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "examples": ["vid_abc123"] },
          "status": { "type": "string", "examples": ["completed"] },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "required": ["url"],
              "properties": {
                "url": { "type": "string", "format": "uri", "description": "URL of the generated video." }
              }
            }
          }
        }
      },
      "SpeechRequest": {
        "type": "object",
        "required": ["input"],
        "properties": {
          "input": { "type": "string", "description": "The text to convert to speech." },
          "voice": { "type": "string", "description": "Voice name (OpenAI voices like alloy) or ElevenLabs voice ID.", "examples": ["alloy"] },
          "model": { "type": "string", "description": "TTS model.", "examples": ["tts-1"] },
          "speed": { "type": "number", "description": "Playback speed multiplier." }
        }
      },
      "TextRequest": {
        "type": "object",
        "required": ["text"],
        "properties": {
          "text": { "type": "string", "description": "The text to process." }
        }
      },
      "MediaUrlResponse": {
        "type": "object",
        "required": ["data"],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "required": ["url"],
              "properties": {
                "url": { "type": "string", "format": "uri" }
              }
            }
          }
        }
      },
      "Error": {
        "type": "object",
        "required": ["error"],
        "properties": {
          "error": {
            "type": "object",
            "required": ["message"],
            "properties": {
              "message": { "type": "string" },
              "type": { "type": "string", "examples": ["authentication_error", "rate_limit_error"] },
              "code": { "description": "Error code (string) or HTTP status (number)." }
            }
          }
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Invalid request body or parameters.",
        "content": {
          "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
        }
      },
      "Unauthorized": {
        "description": "Missing or invalid API key. Pass Authorization: Bearer kr_live_...",
        "content": {
          "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
        }
      },
      "InsufficientCredits": {
        "description": "Not enough credits, or the API key's daily credit cap is reached.",
        "content": {
          "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
        }
      },
      "RateLimited": {
        "description": "Rate limit exceeded (default 60 requests per minute per key). Includes a Retry-After header.",
        "headers": {
          "Retry-After": {
            "description": "Seconds to wait before retrying.",
            "schema": { "type": "integer" }
          }
        },
        "content": {
          "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
        }
      }
    }
  },
  "externalDocs": {
    "description": "Krater API documentation with examples",
    "url": "https://krater.ai/developers"
  }
}
