{
  "openapi": "3.1.0",
  "info": {
    "title": "ollalink Partner API",
    "version": "2026-11-04",
    "summary": "Speech APIs, text tools and models, one GPU API key.",
    "description": "ollalink exposes speech services, text translation and text tools, all authenticated with your **GPU API key** in the `X-NH-GPU-Key` header.\n\n- **Speech GPU** (`gpu-*.ollalink.com`) — batch speech-to-text for Hindi, Hinglish and other languages (`gpu-asrhq`), fast file transcription and speech detection (`gpu-transcribe`), realtime speech-to-text (`gpu-asr`), live captions (`gpu-live`) and text-to-speech with 34 voices in English, Spanish, French, German, Brazilian Portuguese and Hindi, plus voice design (`\"voice\": \"design\"` with an `instructions` description) in all 14 languages (`gpu-tts`, and `gpu-voice` with the same routes). Speech recognition and translation cover 14 languages; text translation also covers Tamil (`ta`).\n- **Translation and text tools** (`https://ai.ollalink.com`) — `POST /v1/translate` (text translation), `POST /v1/normalize` (spoken numbers to digits), `POST /v1/embeddings`, `POST /v1/classify` (classification) and `POST /v1/chat/completions` (`chat` and `coding`, always on; `vision`).\n- **Models** (`https://ai.ollalink.com`) — image generation and editing (`POST /v1/images/generations`, `POST /v1/images/edits`), sound effects and instrumental music (`POST /v1/audio/generations`), document OCR (`POST /v1/ocr`, a job) and songs with lyrics (`POST /v1/music/generations`, a job); jobs are read with `GET /v1/jobs/{id}`.\n\n**Paused:** the voice studio routes on gpu-voice (`/speakers`, `/voice_design`, `/custom_voice`, `/clone` answer 404), cloning from your own clip (`ref_audio` / `ref_text` on text-to-speech answer 400), and the realtime speech-to-speech service on `sound-stream.ollalink.com` (503). These operations are kept below, marked deprecated.\n\nNot every Speech GPU lane is OpenAI-shaped, and **no GPU host serves `/v1/models`** — each operation below states its own host. `POST /v1/audio/transcriptions` is documented for `gpu-asrhq`; the same path on `gpu-transcribe.ollalink.com` (fields `file`, `language` = en|es|fr|de|pt|ru|it|nl, `response_format` = json|verbose_json|text|srt|vtt, `normalize_numbers`) is described at https://ollalink.com/docs/speech-to-text/.\n\nThe WebSocket lanes (`wss://gpu-asr.ollalink.com/v1/audio/transcriptions/realtime` and `wss://gpu-live.ollalink.com/v1/translate/stream`) cannot be expressed in OpenAPI; they are documented at https://ollalink.com/docs/speech-to-text/ and https://ollalink.com/docs/live-translation/. Live captions arrive in the speaker's language (`target_lang` is ignored); for live translation send each final to `POST /v1/translate`. When the live lanes are full, a new session gets `busy` and close code 1013.",
    "contact": {
      "name": "ollalink",
      "url": "https://ollalink.com"
    }
  },
  "servers": [
    {
      "url": "https://ai.ollalink.com",
      "description": "Translation and text tools"
    }
  ],
  "security": [
    {
      "gpuKey": []
    }
  ],
  "tags": [
    {
      "name": "Languages",
      "description": "What each host serves: GET /v1/languages"
    },
    {
      "name": "Translation",
      "description": "Text translation on ai.ollalink.com"
    },
    {
      "name": "Speech-to-text",
      "description": "Batch transcription and speech detection"
    },
    {
      "name": "Text-to-speech",
      "description": "Speech synthesis"
    },
    {
      "name": "Voice studio",
      "description": "Paused — the preset-speaker, studio-design and clone routes on gpu-voice (use \"voice\": \"design\" on text-to-speech)"
    },
    {
      "name": "Service",
      "description": "Health"
    },
    {
      "name": "Text tools",
      "description": "Spoken numbers to digits, embeddings and classification on ai.ollalink.com"
    },
    {
      "name": "Chat and coding",
      "description": "Chat, coding and vision on ai.ollalink.com"
    },
    {
      "name": "Models",
      "description": "Image generation and editing, audio generation, document OCR, music and jobs on ai.ollalink.com"
    }
  ],
  "paths": {
    "/v1/translate": {
      "servers": [
        {
          "url": "https://ai.ollalink.com",
          "description": "Translation"
        }
      ],
      "post": {
        "tags": [
          "Translation"
        ],
        "summary": "Translate text",
        "description": "Host: `https://ai.ollalink.com`. Always on. Send the text and the target language; the service writes its own translation instructions, so the text is always treated as content to translate. Meaning (negation, commands, questions, conditions), numbers, names, protocol names, commands, IP addresses and placeholders (`{name}`, `%d`, `{{x}}`) are kept. Spoken numbers in the source are turned into digits first and placeholders are protected; after translating, the service checks that every number and placeholder survived and retries once if not. `numbers_verified` reports the result; it does not certify meaning or grammar. `pt` is Brazilian Portuguese; the languages are `en`, `hi`, `es`, `fr`, `zh`, `de`, `ar`, `pt`, `ru`, `ja`, `ko`, `it`, `nl`, `vi` and `ta` (Tamil, text translation only), any direction. Usage is counted in source characters (also in the `X-Translate-Chars` header). With `\"stream\": true` the translation is sent as Server-Sent Events while it is written (first words usually within a second; no automatic retry, `numbers_verified` in the final `done` event reports the check). No other fields are accepted.",
        "security": [
          {
            "gpuKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TranslateRequest"
              },
              "example": {
                "text": "Do not open port 443 before Friday.",
                "target": "es"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The translation (JSON), or with `\"stream\": true` a Server-Sent Events stream",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TranslateResponse"
                },
                "example": {
                  "translation": "No abras el puerto 443 antes del viernes.",
                  "source": null,
                  "target": "es",
                  "numbers_verified": true,
                  "characters": 35
                }
              },
              "text/event-stream": {
                "schema": {
                  "type": "string",
                  "description": "`data: <JSON>` events separated by blank lines: `{\"delta\"}` …, then `{\"done\": true, \"translation\", \"numbers_verified\", \"source\", \"target\", \"characters\"}` or `{\"error\": {\"code\", \"message\"}}`"
                },
                "example": "data: {\"delta\": \"VLAN 10 पर पोर्ट 443\"}\n\ndata: {\"delta\": \" खोलें\"}\n\ndata: {\"done\": true, \"translation\": \"VLAN 10 पर पोर्ट 443 खोलें\", \"source\": null, \"target\": \"hi\", \"numbers_verified\": true, \"characters\": 24}\n\n"
              }
            }
          },
          "400": {
            "description": "`bad_request` (missing text, unknown field, not JSON) or `unsupported_language`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TranslateError"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — unknown or revoked key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TranslateError"
                }
              }
            }
          },
          "403": {
            "description": "Missing key (blocked at the edge), `not_approved` or `forbidden` (key without GPU access)"
          },
          "413": {
            "description": "`too_long` — text over 5,000 characters; split it at sentence ends",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TranslateError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited — 600 requests / 60 s per key"
          },
          "503": {
            "description": "`translation_unavailable` — the translation provider did not answer; retry",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TranslateError"
                }
              }
            }
          }
        }
      }
    },
    "/health": {
      "servers": [
        {
          "url": "https://ai.ollalink.com",
          "description": "Text tools"
        }
      ],
      "get": {
        "tags": [
          "Service"
        ],
        "summary": "Text tools host health",
        "description": "Host: `https://ai.ollalink.com`. `200` with `\"status\":\"ok\"` proves the key and the path.",
        "security": [
          {
            "gpuKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Service is up"
          },
          "403": {
            "description": "Missing or wrong key"
          }
        }
      }
    },
    "/v1/audio/speech": {
      "servers": [
        {
          "url": "https://gpu-tts.ollalink.com",
          "description": "Speech GPU — text-to-speech"
        },
        {
          "url": "https://gpu-voice.ollalink.com",
          "description": "Speech GPU — same voices and routes"
        }
      ],
      "post": {
        "tags": [
          "Text-to-speech"
        ],
        "summary": "Text-to-speech (Speech GPU)",
        "description": "Host: `https://gpu-tts.ollalink.com` (or `https://gpu-voice.ollalink.com`). OpenAI-style request; returns the complete audio file, **mp3 by default**. 34 voices in 6 languages (en es fr de pt hi); the Hindi voices load on demand and take up to 600 characters per request. Works through an OpenAI SDK if you pass the key via `default_headers`. Voice design: send `\"voice\": \"design\"` with an `instructions` description (required, up to 400 characters) and up to 1,000 characters of text; each request invents a new speaker in any of the 14 languages (headers `X-TTS-Engine: design`, `X-TTS-Voice: design`). Style instructions on a ready-made voice and cloning are not available. There is no speed control (`speed` is accepted and ignored).",
        "security": [
          {
            "gpuKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "input"
                ],
                "properties": {
                  "input": {
                    "type": "string",
                    "maxLength": 4000,
                    "description": "The text to speak, up to 4,000 characters (Hindi voices 600, Indian English tutor voices and `design` 1,000); longer text answers 400 stating the limit. `text` is accepted for the same field."
                  },
                  "voice": {
                    "type": "string",
                    "enum": [
                      "delia",
                      "maeve",
                      "freya",
                      "easton",
                      "russell",
                      "edwin",
                      "lakshmi",
                      "nandini",
                      "divya",
                      "karthik",
                      "harpreet",
                      "mateo",
                      "elodie",
                      "antoine",
                      "anna",
                      "larissa",
                      "rafael",
                      "layla",
                      "yui",
                      "haruto",
                      "noa",
                      "marcos",
                      "noemie",
                      "augustin",
                      "nele",
                      "anton",
                      "manuela",
                      "davi",
                      "ahana",
                      "vaidehi",
                      "malini",
                      "charvi",
                      "jahnavi",
                      "nivedita",
                      "tanushree",
                      "ishwari",
                      "vrinda",
                      "kayal",
                      "anirban",
                      "nakul",
                      "siddhant",
                      "satvik",
                      "vasant",
                      "abhay",
                      "shaunak",
                      "akshat",
                      "ritvik",
                      "sreekar",
                      "default",
                      "design"
                    ],
                    "default": "default",
                    "description": "A voice id from GET /voices, or `default` for the language's default (en → `delia`, es → `noa`, fr → `noemie`, de → `nele`, pt → `manuela`). English: delia, maeve, freya (female), easton, russell, edwin (male); Indian English tutor voices: lakshmi, nandini, divya (female), karthik, harpreet (male), up to 1,000 characters; tutor voices in other languages: mateo (es), elodie, antoine (fr), anna (de), larissa, rafael (pt), layla (ar, default), yui (ja, default), haruto (ja); Spanish: noa, marcos; French: noemie, augustin; German: nele, anton; Brazilian Portuguese: manuela, davi. Each voice speaks its own language only. Older ids (`ryan`, `vivian`, `alba`, …) still answer with an English voice; `jason`, `aria`, `sofia`, `leo`, `john` and `design` answer 400. `design`: a voice invented from `instructions` (any of the 14 languages).",
                    "examples": [
                      "delia"
                    ]
                  },
                  "language": {
                    "type": "string",
                    "enum": [
                      "en",
                      "hi",
                      "es",
                      "fr",
                      "zh",
                      "de",
                      "ar",
                      "pt",
                      "ru",
                      "ja",
                      "ko",
                      "it",
                      "nl",
                      "vi"
                    ],
                    "description": "Language of the text. Ready-made voices: en, es, fr, de, pt (Brazilian Portuguese), ar, ja, hi. With `\"voice\": \"design\"`: any of en, hi, es, fr, zh, de, ar, pt, ru, ja, ko, it, nl, vi. A region suffix is ignored (`pt-BR` = `pt`). `\"voice\": \"default\"` in a language with no ready-made voice answers 400 pointing to `design`."
                  },
                  "instructions": {
                    "type": "string",
                    "maxLength": 400,
                    "description": "Required with `\"voice\": \"design\"`, up to 400 characters: one sentence of about 30–45 words in English describing accent, age, gender, pitch and texture, energy and pace, and the role or scenario (e.g. \"A young woman with a clear Indian English accent, bright and friendly, a tech YouTuber explaining networking to beginners\"). With a ready-made voice it answers 400."
                  },
                  "response_format": {
                    "type": "string",
                    "enum": [
                      "mp3",
                      "wav",
                      "pcm",
                      "opus",
                      "aac",
                      "flac"
                    ],
                    "default": "mp3",
                    "description": "Audio container. `pcm` = raw 16-bit mono samples."
                  },
                  "model": {
                    "type": "string",
                    "description": "Accepted and ignored (OpenAI SDK compatibility)."
                  },
                  "ref_audio": {
                    "type": "string",
                    "deprecated": true,
                    "description": "**Paused (400)**: cloning from your own clip is paused; any value answers 400."
                  },
                  "ref_text": {
                    "type": "string",
                    "deprecated": true,
                    "description": "**Paused (400)**: cloning from your own clip is paused; any value answers 400."
                  }
                }
              },
              "examples": {
                "basic": {
                  "value": {
                    "input": "BGP peers exchange routes over TCP port 179.",
                    "voice": "delia",
                    "language": "en"
                  }
                },
                "spanish": {
                  "value": {
                    "input": "No abras el puerto 443 antes del viernes.",
                    "voice": "noa",
                    "language": "es",
                    "response_format": "wav"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The audio file in the requested format",
            "headers": {
              "X-Audio-Seconds": {
                "description": "Length of the audio in seconds (counted for usage)",
                "schema": {
                  "type": "number"
                }
              },
              "X-TTS-Voice": {
                "description": "The voice actually used",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "audio/mpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "audio/wav": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "audio/L16": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "audio/ogg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "audio/aac": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "audio/flac": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "Empty or over-long input, an unknown or retired voice, a voice used with another language, a language with no voice, `design` without `instructions` or with `instructions` over 400 characters, `instructions` on a ready-made voice, `ref_audio` / `ref_text` (cloning paused), or an unknown `response_format`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "message": "no voice for language 'hi'; available languages: ['de', 'en', 'es', 'fr', 'pt']",
                    "type": "invalid_request_error"
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/GpuForbidden"
          },
          "503": {
            "description": "`service_unavailable` — busy or briefly unavailable; retry shortly (also when the voice-design engine is busy or down; retry)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "operationId": "createCatalogSpeech"
      }
    },
    "/voices": {
      "servers": [
        {
          "url": "https://gpu-tts.ollalink.com",
          "description": "Speech GPU — text-to-speech"
        },
        {
          "url": "https://gpu-voice.ollalink.com",
          "description": "Speech GPU — same voices and routes"
        }
      ],
      "get": {
        "tags": [
          "Text-to-speech"
        ],
        "summary": "The voice list and per-language defaults (authoritative)",
        "description": "Host: `https://gpu-tts.ollalink.com`. 34 voices in 6 languages (en es fr de pt hi), plus the entry `design` (languages: the 14, `max_characters` 1000, `max_instruction_characters` 400, `note`); each voice has a fixed style; the Hindi voices can also speak Indian-accented English. With `?language=` only the voices of that language are returned. Full table: https://ollalink.com/docs/voice-catalog/",
        "security": [
          {
            "gpuKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Voices",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "voices": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "enum": [
                              "delia",
                              "maeve",
                              "freya",
                              "easton",
                              "russell",
                              "edwin",
                              "lakshmi",
                              "nandini",
                              "divya",
                              "karthik",
                              "harpreet",
                              "mateo",
                              "elodie",
                              "antoine",
                              "anna",
                              "larissa",
                              "rafael",
                              "layla",
                              "yui",
                              "haruto",
                              "noa",
                              "marcos",
                              "noemie",
                              "augustin",
                              "nele",
                              "anton",
                              "manuela",
                              "davi",
                              "ahana",
                              "vaidehi",
                              "malini",
                              "charvi",
                              "jahnavi",
                              "nivedita",
                              "tanushree",
                              "ishwari",
                              "vrinda",
                              "kayal",
                              "anirban",
                              "nakul",
                              "siddhant",
                              "satvik",
                              "vasant",
                              "abhay",
                              "shaunak",
                              "akshat",
                              "ritvik",
                              "sreekar",
                              "design"
                            ]
                          },
                          "name": {
                            "type": "string",
                            "examples": [
                              "Delia"
                            ]
                          },
                          "gender": {
                            "type": "string",
                            "enum": [
                              "male",
                              "female"
                            ]
                          },
                          "languages": {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "enum": [
                                "en",
                                "hi",
                                "es",
                                "fr",
                                "zh",
                                "de",
                                "ar",
                                "pt",
                                "ru",
                                "ja",
                                "ko",
                                "it",
                                "nl",
                                "vi"
                              ]
                            }
                          },
                          "default_for": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "Languages for which this is the default voice."
                          },
                          "engine": {
                            "type": "string",
                            "description": "Which kind of voice it is (e.g. `fixed` for a ready-made voice)."
                          },
                          "note": {
                            "type": "string",
                            "description": "Accent note, where it applies (e.g. `Beijing accent in Chinese`)."
                          },
                          "max_characters": {
                            "type": "integer",
                            "description": "Longest `input` this voice accepts (e.g. 1000 for `design`)."
                          },
                          "max_instruction_characters": {
                            "type": "integer",
                            "description": "`design` only: longest `instructions` (400)."
                          }
                        }
                      }
                    },
                    "default": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "examples": [
                        "delia"
                      ],
                      "description": "The default voice for `?language=` (English when none was sent)."
                    },
                    "defaults": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "string"
                      },
                      "description": "Language code → the voice a request in that language gets when it names none.",
                      "examples": [
                        {
                          "en": "delia",
                          "es": "noa",
                          "fr": "noemie",
                          "de": "nele",
                          "pt": "manuela"
                        }
                      ]
                    },
                    "aliases": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "string"
                      },
                      "description": "Currently empty."
                    },
                    "languages": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "examples": [
                        [
                          "de",
                          "en",
                          "es",
                          "fr",
                          "it",
                          "ja",
                          "ko",
                          "pt",
                          "ru",
                          "zh"
                        ]
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/GpuForbidden"
          }
        },
        "operationId": "listVoices",
        "parameters": [
          {
            "name": "language",
            "in": "query",
            "required": false,
            "description": "Return only the voices that speak this language (`en`, `zh`, `ja`, `ko`, `de`, `fr`, `ru`, `pt`, `es`, `it`).",
            "schema": {
              "type": "string",
              "examples": [
                "ja"
              ]
            }
          }
        ]
      }
    },
    "/tts": {
      "servers": [
        {
          "url": "https://gpu-tts.ollalink.com",
          "description": "Speech GPU — text-to-speech"
        }
      ],
      "post": {
        "tags": [
          "Text-to-speech"
        ],
        "summary": "Text-to-speech, older route (WAV by default)",
        "description": "Host: `https://gpu-tts.ollalink.com` (or `https://gpu-voice.ollalink.com`). OpenAI-style request; returns the complete audio file, **mp3 by default**. 34 voices in 6 languages (en es fr de pt hi); the Hindi voices load on demand and take up to 600 characters per request. Works through an OpenAI SDK if you pass the key via `default_headers`. Voice design: send `\"voice\": \"design\"` with an `instructions` description (required, up to 400 characters) and up to 1,000 characters of text; each request invents a new speaker in any of the 14 languages (headers `X-TTS-Engine: design`, `X-TTS-Voice: design`). Style instructions on a ready-made voice and cloning are not available. There is no speed control (`speed` is accepted and ignored). This older route returns WAV by default; `text` aliases `input`.",
        "security": [
          {
            "gpuKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "text"
                ],
                "properties": {
                  "text": {
                    "type": "string",
                    "maxLength": 4000,
                    "description": "The text to speak, up to 4,000 characters (Hindi voices 600, Indian English tutor voices and `design` 1,000); longer text answers 400 stating the limit. `input` is accepted for the same field."
                  },
                  "voice": {
                    "type": "string",
                    "enum": [
                      "delia",
                      "maeve",
                      "freya",
                      "easton",
                      "russell",
                      "edwin",
                      "lakshmi",
                      "nandini",
                      "divya",
                      "karthik",
                      "harpreet",
                      "mateo",
                      "elodie",
                      "antoine",
                      "anna",
                      "larissa",
                      "rafael",
                      "layla",
                      "yui",
                      "haruto",
                      "noa",
                      "marcos",
                      "noemie",
                      "augustin",
                      "nele",
                      "anton",
                      "manuela",
                      "davi",
                      "ahana",
                      "vaidehi",
                      "malini",
                      "charvi",
                      "jahnavi",
                      "nivedita",
                      "tanushree",
                      "ishwari",
                      "vrinda",
                      "kayal",
                      "anirban",
                      "nakul",
                      "siddhant",
                      "satvik",
                      "vasant",
                      "abhay",
                      "shaunak",
                      "akshat",
                      "ritvik",
                      "sreekar",
                      "default",
                      "design"
                    ],
                    "default": "default",
                    "description": "A voice id from GET /voices, or `default` for the language's default (en → `delia`, es → `noa`, fr → `noemie`, de → `nele`, pt → `manuela`). English: delia, maeve, freya (female), easton, russell, edwin (male); Indian English tutor voices: lakshmi, nandini, divya (female), karthik, harpreet (male), up to 1,000 characters; tutor voices in other languages: mateo (es), elodie, antoine (fr), anna (de), larissa, rafael (pt), layla (ar, default), yui (ja, default), haruto (ja); Spanish: noa, marcos; French: noemie, augustin; German: nele, anton; Brazilian Portuguese: manuela, davi. Each voice speaks its own language only. Older ids (`ryan`, `vivian`, `alba`, …) still answer with an English voice; `jason`, `aria`, `sofia`, `leo`, `john` and `design` answer 400. `design`: a voice invented from `instructions` (any of the 14 languages).",
                    "examples": [
                      "delia"
                    ]
                  },
                  "language": {
                    "type": "string",
                    "enum": [
                      "en",
                      "hi",
                      "es",
                      "fr",
                      "zh",
                      "de",
                      "ar",
                      "pt",
                      "ru",
                      "ja",
                      "ko",
                      "it",
                      "nl",
                      "vi"
                    ],
                    "description": "Language of the text. Ready-made voices: en, es, fr, de, pt (Brazilian Portuguese), ar, ja, hi. With `\"voice\": \"design\"`: any of en, hi, es, fr, zh, de, ar, pt, ru, ja, ko, it, nl, vi. A region suffix is ignored (`pt-BR` = `pt`). `\"voice\": \"default\"` in a language with no ready-made voice answers 400 pointing to `design`."
                  },
                  "instructions": {
                    "type": "string",
                    "maxLength": 400,
                    "description": "Required with `\"voice\": \"design\"`, up to 400 characters: one sentence of about 30–45 words in English describing accent, age, gender, pitch and texture, energy and pace, and the role or scenario (e.g. \"A young woman with a clear Indian English accent, bright and friendly, a tech YouTuber explaining networking to beginners\"). With a ready-made voice it answers 400."
                  },
                  "response_format": {
                    "type": "string",
                    "enum": [
                      "mp3",
                      "wav",
                      "pcm",
                      "opus",
                      "aac",
                      "flac"
                    ],
                    "default": "wav",
                    "description": "Audio container. `pcm` = raw 16-bit mono samples."
                  },
                  "model": {
                    "type": "string",
                    "description": "Accepted and ignored (OpenAI SDK compatibility)."
                  },
                  "ref_audio": {
                    "type": "string",
                    "deprecated": true,
                    "description": "**Paused (400)**: cloning from your own clip is paused; any value answers 400."
                  },
                  "ref_text": {
                    "type": "string",
                    "deprecated": true,
                    "description": "**Paused (400)**: cloning from your own clip is paused; any value answers 400."
                  }
                }
              },
              "example": {
                "input": "BGP peers exchange routes over TCP port 179.",
                "voice": "delia",
                "language": "en"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The audio file in the requested format",
            "headers": {
              "X-Audio-Seconds": {
                "description": "Length of the audio in seconds (counted for usage)",
                "schema": {
                  "type": "number"
                }
              },
              "X-TTS-Voice": {
                "description": "The voice actually used",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "audio/mpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "audio/wav": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "audio/L16": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "audio/ogg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "audio/aac": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "audio/flac": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "Empty or over-long input, an unknown or retired voice, a voice used with another language, a language with no voice, `design` without `instructions` or with `instructions` over 400 characters, `instructions` on a ready-made voice, `ref_audio` / `ref_text` (cloning paused), or an unknown `response_format`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "message": "no voice for language 'hi'; available languages: ['de', 'en', 'es', 'fr', 'pt']",
                    "type": "invalid_request_error"
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/GpuForbidden"
          },
          "503": {
            "description": "`service_unavailable` — busy or briefly unavailable; retry shortly (also when the voice-design engine is busy or down; retry)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "operationId": "createSpeechWav"
      }
    },
    "/v1/audio/transcriptions": {
      "servers": [
        {
          "url": "https://gpu-asrhq.ollalink.com",
          "description": "Speech GPU — Hindi, Hinglish and other languages; speech → English"
        }
      ],
      "post": {
        "tags": [
          "Speech-to-text"
        ],
        "summary": "Batch transcription for Hindi, Hinglish and other languages (Speech GPU)",
        "description": "Use for Hindi and Hinglish recordings, for languages that fast file transcription (`gpu-transcribe`: en es fr de pt ru) does not cover, and for speech → English. Host: `https://gpu-asrhq.ollalink.com`. Returns `segments` **and** `duration` by default, and its segments carry an `id`. Add `task=translate` for speech → English text. Languages: `en`, `hi`, `es`, `fr`, `zh`, `de`, `ar`, `pt`, `ru` (auto-detected when omitted). Hindi (`language=hi`) comes back in Devanagari with English technical words in Latin script; Urdu is not offered — pin `hi` for Hindi, because Hindi speech can be auto-detected as Urdu. A 20-second clip typically returns in about 11–13 s. No vocabulary hint is applied by default, so `prompt_applied` is `false`; `initial_prompt` applies your own hint for that request.",
        "security": [
          {
            "gpuKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/TranscriptionForm"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "task": {
                        "type": "string",
                        "enum": [
                          "transcribe",
                          "translate"
                        ]
                      },
                      "initial_prompt": {
                        "type": "string",
                        "description": "Your own vocabulary hint for this request (none is applied by default)."
                      },
                      "no_prompt": {
                        "type": "string",
                        "enum": [
                          "true",
                          "false"
                        ],
                        "description": "Accepted for compatibility; no hint is applied by default."
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Transcript with segments",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Transcription"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "prompt_applied": {
                          "type": "boolean",
                          "description": "gpu-asrhq only — true when your `initial_prompt` was applied to this request (no hint is applied by default)."
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/GpuForbidden"
          },
          "400": {
            "description": "`bad_request` — empty file, or a file that cannot be decoded as audio or video",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TranslateError"
                }
              }
            }
          },
          "503": {
            "description": "`busy` — transcription capacity is full; retry after `Retry-After` (1 s)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TranslateError"
                }
              }
            }
          }
        },
        "operationId": "createHighAccuracyTranscription"
      }
    },
    "/speakers": {
      "servers": [
        {
          "url": "https://gpu-voice.ollalink.com",
          "description": "Speech GPU — voice studio"
        }
      ],
      "get": {
        "tags": [
          "Voice studio"
        ],
        "summary": "Example speaker descriptions and supported language codes",
        "security": [
          {
            "gpuKey": []
          }
        ],
        "responses": {
          "404": {
            "description": "Paused — the voice studio routes are not served"
          },
          "200": {
            "description": "Presets",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "speakers": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "languages": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                },
                "examples": {
                  "live": {
                    "value": {
                      "speakers": [
                        "a warm, measured female teacher in her forties, clear classroom diction",
                        "an older male professor, low pitch, unhurried and authoritative",
                        "a young adult female tutor with an Indian English accent, friendly and bright",
                        "an energetic young male presenter, fast paced and upbeat",
                        "a calm middle-aged male narrator, neutral accent, documentary style",
                        "a cheerful young female host, expressive and conversational"
                      ],
                      "languages": [
                        "ar",
                        "de",
                        "en",
                        "es",
                        "fr",
                        "hi",
                        "pt",
                        "ru",
                        "zh"
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/GpuForbidden"
          }
        },
        "operationId": "listSpeakers",
        "description": "**Paused (404)**: the voice studio is paused and this route on gpu-voice answers 404. Use `POST /v1/audio/speech` with a named voice, or `voice: \"design\"` with `instructions`. The shape below is kept for reference only.",
        "deprecated": true
      }
    },
    "/voice_design": {
      "servers": [
        {
          "url": "https://gpu-voice.ollalink.com",
          "description": "Speech GPU — voice studio"
        }
      ],
      "post": {
        "tags": [
          "Voice studio"
        ],
        "summary": "Build a voice from a plain-English description",
        "description": "**Paused (404)**: the voice studio is paused and this route on gpu-voice answers 404. Use `POST /v1/audio/speech` with a named voice, or `voice: \"design\"` with `instructions`. The shape below is kept for reference only.",
        "security": [
          {
            "gpuKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "text",
                  "instruct"
                ],
                "properties": {
                  "text": {
                    "type": "string"
                  },
                  "instruct": {
                    "type": "string",
                    "description": "Plain-English description of the voice",
                    "examples": [
                      "a warm, measured female teacher in her forties, clear classroom diction"
                    ]
                  },
                  "language": {
                    "type": "string",
                    "description": "A code from GET /speakers (`en`, `hi`, `es`, `fr`, `zh`, `de`, `ar`, `pt`, `ru`) or its English name; default `en`."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "404": {
            "description": "Paused — the voice studio routes are not served"
          },
          "200": {
            "description": "Base64 WAV plus what was applied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StudioAudio"
                }
              }
            }
          },
          "400": {
            "description": "Empty `instruct`, or an unsupported language"
          },
          "403": {
            "$ref": "#/components/responses/GpuForbidden"
          },
          "429": {
            "description": "Synthesis queue full on this lane — `Retry-After: 1`. Lane back-pressure, distinct from the per-key rate limit: wait a second and retry."
          }
        },
        "operationId": "designVoice",
        "deprecated": true
      }
    },
    "/custom_voice": {
      "servers": [
        {
          "url": "https://gpu-voice.ollalink.com",
          "description": "Speech GPU — voice studio"
        }
      ],
      "post": {
        "tags": [
          "Voice studio"
        ],
        "summary": "Speak as a described speaker",
        "security": [
          {
            "gpuKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "text",
                  "speaker"
                ],
                "properties": {
                  "text": {
                    "type": "string"
                  },
                  "speaker": {
                    "type": "string",
                    "description": "A description from GET /speakers, or any plain-English description of your own"
                  },
                  "language": {
                    "type": "string",
                    "description": "A code from GET /speakers (`en`, `hi`, `es`, `fr`, `zh`, `de`, `ar`, `pt`, `ru`) or its English name; default `en`."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "404": {
            "description": "Paused — the voice studio routes are not served"
          },
          "200": {
            "description": "Base64 WAV",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StudioAudio"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/GpuForbidden"
          },
          "429": {
            "description": "Synthesis queue full on this lane — `Retry-After: 1`. Lane back-pressure, distinct from the per-key rate limit: wait a second and retry."
          }
        },
        "operationId": "speakAsPresetVoice",
        "description": "**Paused (404)**: the voice studio is paused and this route on gpu-voice answers 404. Use `POST /v1/audio/speech` with a named voice, or `voice: \"design\"` with `instructions`. The shape below is kept for reference only.",
        "deprecated": true
      }
    },
    "/clone": {
      "servers": [
        {
          "url": "https://gpu-voice.ollalink.com",
          "description": "Speech GPU — voice studio"
        }
      ],
      "post": {
        "tags": [
          "Voice studio"
        ],
        "summary": "Clone a voice from a reference clip",
        "description": "**Paused (404)**: the voice studio is paused and this route on gpu-voice answers 404. Use `POST /v1/audio/speech` with a named voice, or `voice: \"design\"` with `instructions`. Cloning from your own clip is paused everywhere. The shape below is kept for reference only.",
        "security": [
          {
            "gpuKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "text",
                  "ref_audio"
                ],
                "properties": {
                  "text": {
                    "type": "string"
                  },
                  "ref_audio": {
                    "type": "string",
                    "description": "`data:audio/wav;base64,…` data URI (WAV/FLAC/OGG, 3–10 s clean single-speaker). A bare base64 string, URL or path is rejected with 400."
                  },
                  "ref_text": {
                    "type": "string",
                    "description": "Transcript of the reference clip — improves fidelity (`mode: ultimate` when supplied)"
                  },
                  "language": {
                    "type": "string",
                    "description": "Target language code or English name (same set as /speakers)"
                  },
                  "instruct": {
                    "type": "string",
                    "description": "Style nudge on top of the cloned timbre (free text)"
                  },
                  "speed": {
                    "type": "number",
                    "default": 1.0,
                    "description": "Pace by the pauses between sentences (words never stretched), 0.25–4.0, default 1.0"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "404": {
            "description": "Paused — the voice studio routes are not served"
          },
          "200": {
            "description": "Base64 WAV",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StudioAudio"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/GpuForbidden"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "description": "Synthesis queue full on this lane — `Retry-After: 1`. Lane back-pressure, distinct from the per-key rate limit: wait a second and retry."
          }
        },
        "operationId": "cloneVoice",
        "deprecated": true
      }
    },
    "/v1/normalize": {
      "servers": [
        {
          "url": "https://ai.ollalink.com",
          "description": "Text tools"
        }
      ],
      "post": {
        "tags": [
          "Text tools"
        ],
        "summary": "Spoken numbers to digits",
        "operationId": "normalizeNumbers",
        "security": [
          {
            "gpuKey": []
          }
        ],
        "description": "\"open port four forty three\" → \"open port 443\"; \"ten point zero dot zero dot one\" → \"10.0.0.1\"; a lone \"one\"/\"two\" stays a word. English (default) or Hindi: Hindi cardinal numbers (\"पोर्ट चार सौ तैंतालीस खोलो\" → \"पोर्ट 443 खोलो\") and English numbers spelled in Devanagari. Up to 5,000 characters. Usage counted in characters.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "text"
                ],
                "properties": {
                  "text": {
                    "type": "string",
                    "description": "Recogniser text",
                    "example": "open port four forty three"
                  },
                  "language": {
                    "type": "string",
                    "enum": [
                      "en",
                      "hi"
                    ],
                    "default": "en"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "text": {
                      "type": "string"
                    },
                    "normalized": {
                      "type": "string"
                    },
                    "changed": {
                      "type": "boolean"
                    },
                    "language": {
                      "type": "string"
                    },
                    "characters": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "bad_request / unsupported_language"
          },
          "413": {
            "description": "too_long"
          }
        }
      }
    },
    "/v1/embeddings": {
      "servers": [
        {
          "url": "https://ai.ollalink.com",
          "description": "Text tools"
        }
      ],
      "post": {
        "tags": [
          "Text tools"
        ],
        "summary": "Text embeddings",
        "operationId": "createEmbeddings",
        "security": [
          {
            "gpuKey": []
          }
        ],
        "description": "Unit-length vectors (dot product = cosine similarity). 1–256 texts, at most 5,000 characters each and 50,000 per request. When busy it answers 503 → retry. Usage counted in characters.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "input"
                ],
                "properties": {
                  "input": {
                    "oneOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "array",
                        "items": {
                          "type": "string"
                        },
                        "maxItems": 256
                      }
                    ]
                  },
                  "dimensions": {
                    "type": "integer",
                    "enum": [
                      1024
                    ],
                    "default": 1024,
                    "description": "1024 only since 2026-10-17; earlier 768-d vectors are not compatible"
                  },
                  "mode": {
                    "type": "string",
                    "enum": [
                      "document",
                      "query"
                    ],
                    "default": "document"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "example": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "index": {
                            "type": "integer"
                          },
                          "embedding": {
                            "type": "array",
                            "items": {
                              "type": "number"
                            }
                          }
                        }
                      }
                    },
                    "dimensions": {
                      "type": "integer"
                    },
                    "mode": {
                      "type": "string"
                    },
                    "characters": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "bad_request"
          },
          "413": {
            "description": "too_long"
          },
          "503": {
            "description": "embeddings_unavailable — retry shortly"
          }
        }
      }
    },
    "/v1/classify": {
      "servers": [
        {
          "url": "https://ai.ollalink.com",
          "description": "Text tools"
        }
      ],
      "post": {
        "tags": [
          "Text tools"
        ],
        "summary": "Classify a text (pick-one, yes/no, score)",
        "operationId": "classifyText",
        "security": [
          {
            "gpuKey": []
          }
        ],
        "description": "Up to 20 questions about one text. `choice` (pick one of 2–10 named options) is the reliable kind; its `confidence` is the probability of the chosen option. `yes_no` and `score` are experimental (their answers carry `experimental: true`) — for a yes/no decision ask a `choice` with two named options. Scores answer with the most likely level index, plus `level`, `confidence` and `probabilities`. Up to 5,000 characters; usage is counted in characters. Always on; when busy it answers 503 → retry.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "text",
                  "questions"
                ],
                "properties": {
                  "text": {
                    "type": "string"
                  },
                  "questions": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "object",
                      "required": [
                        "type",
                        "question"
                      ],
                      "properties": {
                        "type": {
                          "type": "string",
                          "enum": [
                            "choice",
                            "yes_no",
                            "score"
                          ]
                        },
                        "question": {
                          "type": "string"
                        },
                        "options": {
                          "type": "object",
                          "additionalProperties": {
                            "type": "string"
                          },
                          "description": "choice: name → short description (2–10)"
                        },
                        "levels": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "score: lowest first (2–10)"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "answers": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "object",
                        "properties": {
                          "type": {
                            "type": "string"
                          },
                          "answer": {},
                          "confidence": {
                            "type": "number"
                          },
                          "probabilities": {
                            "type": "object"
                          },
                          "level": {
                            "type": "string"
                          },
                          "probability_yes": {
                            "type": "number"
                          },
                          "experimental": {
                            "type": "boolean"
                          }
                        }
                      }
                    },
                    "characters": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "bad_request"
          },
          "413": {
            "description": "too_long"
          },
          "503": {
            "description": "classification_unavailable — retry shortly"
          }
        }
      }
    },
    "/v1/audio/segments": {
      "servers": [
        {
          "url": "https://gpu-transcribe.ollalink.com",
          "description": "Speech GPU — file transcription"
        }
      ],
      "post": {
        "tags": [
          "Speech-to-text"
        ],
        "summary": "Speech detection: where the speech is in a recording",
        "operationId": "speechSegments",
        "security": [
          {
            "gpuKey": []
          }
        ],
        "description": "Start/end seconds of each speech segment in an uploaded audio or video file; silences and music left out. Usage in seconds of audio (X-ASR-Audio-S).",
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "file"
                ],
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary"
                  },
                  "min_silence_ms": {
                    "type": "integer",
                    "default": 300,
                    "minimum": 100,
                    "maximum": 5000
                  },
                  "min_speech_ms": {
                    "type": "integer",
                    "default": 250,
                    "minimum": 50,
                    "maximum": 5000
                  },
                  "pad_ms": {
                    "type": "integer",
                    "default": 100,
                    "minimum": 0,
                    "maximum": 1000
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "duration": {
                      "type": "number"
                    },
                    "speech_seconds": {
                      "type": "number"
                    },
                    "count": {
                      "type": "integer"
                    },
                    "segments": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "start": {
                            "type": "number"
                          },
                          "end": {
                            "type": "number"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "bad_request / bad_audio"
          },
          "413": {
            "description": "too_large / too_long"
          }
        }
      }
    },
    "/v1/models": {
      "servers": [
        {
          "url": "https://ai.ollalink.com",
          "description": "On-demand models"
        }
      ],
      "get": {
        "tags": [
          "Models"
        ],
        "summary": "List the models",
        "operationId": "listModels",
        "security": [
          {
            "gpuKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "vision",
                      "object": "model",
                      "owned_by": "ollalink"
                    },
                    {
                      "id": "chat",
                      "object": "model",
                      "owned_by": "ollalink"
                    },
                    {
                      "id": "coding",
                      "object": "model",
                      "owned_by": "ollalink"
                    },
                    {
                      "id": "ocr",
                      "object": "model",
                      "owned_by": "ollalink"
                    },
                    {
                      "id": "music",
                      "object": "model",
                      "owned_by": "ollalink"
                    },
                    {
                      "id": "qwen-image-2.1-turbo",
                      "object": "model",
                      "owned_by": "ollalink"
                    },
                    {
                      "id": "flux2-klein-4b",
                      "object": "model",
                      "owned_by": "ollalink"
                    },
                    {
                      "id": "stable-audio-3-small-sfx",
                      "object": "model",
                      "owned_by": "ollalink"
                    },
                    {
                      "id": "stable-audio-3-small-music",
                      "object": "model",
                      "owned_by": "ollalink"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/v1/chat/completions": {
      "servers": [
        {
          "url": "https://ai.ollalink.com",
          "description": "On-demand models"
        }
      ],
      "post": {
        "tags": [
          "Chat and coding"
        ],
        "summary": "Chat, coding and vision (OpenAI-style)",
        "operationId": "chatCompletions",
        "security": [
          {
            "gpuKey": []
          }
        ],
        "description": "`chat` (everyday questions, explanations, instructions) and `coding` (code, bug fixes, agents) are always on and, since 7 November 2026, served by the same model with the same limits; replies name the lane you sent. Both answer directly; send `chat_template_kwargs: {\"enable_thinking\": true}` to think first (reasoning in `message.reasoning`, streaming `delta.reasoning`; it counts towards `max_tokens`). Defaults: temperature 0.6, top_p 0.9, top_k 64, min_p 0.05, repeat_penalty 1.1. Tools in the OpenAI format (`tools`, `tool_choice` auto/required/none/named), `response_format` json_object/json_schema, image parts (`image_url` with a `data:` URI). Vision and OCR: `\"model\": \"vision\"` (loads on first use; replies name the model `vision`). `stream: true` returns server-sent events; use it for long answers. Usage: tokens.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "model",
                  "messages"
                ],
                "properties": {
                  "model": {
                    "type": "string",
                    "enum": [
                      "chat",
                      "coding",
                      "vision"
                    ],
                    "examples": [
                      "chat",
                      "coding",
                      "vision"
                    ],
                    "description": "`chat`, `coding`, or `vision` (images and OCR)"
                  },
                  "messages": {
                    "type": "array",
                    "items": {
                      "type": "object"
                    }
                  },
                  "max_tokens": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 8192,
                    "default": 8192
                  },
                  "temperature": {
                    "type": "number"
                  },
                  "top_p": {
                    "type": "number"
                  },
                  "seed": {
                    "type": "integer"
                  },
                  "stream": {
                    "type": "boolean",
                    "default": false
                  },
                  "top_k": {
                    "type": "integer"
                  },
                  "repetition_penalty": {
                    "type": "number"
                  },
                  "tools": {
                    "type": "array",
                    "items": {
                      "type": "object"
                    }
                  },
                  "min_p": {
                    "type": "number"
                  },
                  "repeat_penalty": {
                    "type": "number"
                  },
                  "tool_choice": {
                    "description": "`auto` (default), `required`, `none`, or `{\"type\":\"function\",\"function\":{\"name\":\"…\"}}`"
                  },
                  "response_format": {
                    "type": "object",
                    "description": "`{\"type\":\"json_object\"}` or `{\"type\":\"json_schema\",\"json_schema\":{…}}`"
                  },
                  "chat_template_kwargs": {
                    "type": "object",
                    "description": "`{\"enable_thinking\": true}` to think before answering"
                  },
                  "max_completion_tokens": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 8192,
                    "description": "Same as `max_tokens` (the newer OpenAI name); the same 1–8,192 cap applies."
                  }
                }
              },
              "example": {
                "model": "chat",
                "messages": [
                  {
                    "role": "user",
                    "content": "Which port does HTTPS use? Answer with the number only."
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK (or text/event-stream when stream is true)",
            "content": {
              "application/json": {
                "example": {
                  "object": "chat.completion",
                  "model": "chat",
                  "choices": [
                    {
                      "index": 0,
                      "finish_reason": "stop",
                      "message": {
                        "role": "assistant",
                        "content": "443"
                      }
                    }
                  ],
                  "usage": {
                    "prompt_tokens": 22,
                    "completion_tokens": 60,
                    "total_tokens": 82
                  }
                }
              }
            }
          },
          "400": {
            "description": "bad request"
          },
          "401": {
            "description": "wrong key"
          },
          "403": {
            "description": "no key"
          },
          "503": {
            "description": "busy (retry after Retry-After) or unavailable"
          }
        }
      }
    },
    "/v1/images/generations": {
      "servers": [
        {
          "url": "https://ai.ollalink.com",
          "description": "Models"
        }
      ],
      "post": {
        "tags": [
          "Models"
        ],
        "summary": "Generate an image",
        "operationId": "imagesGenerations",
        "security": [
          {
            "gpuKey": []
          }
        ],
        "description": "Host: `https://ai.ollalink.com`. `qwen-image-2.1-turbo` (default) is always on; `flux2-klein-4b` loads per request and takes about 40 s, because the default image model is reloaded before it answers. Same prompt, size and seed give the same picture. Usage: 1 per picture. When busy the request gets 503; retry shortly.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "prompt"
                ],
                "additionalProperties": false,
                "properties": {
                  "model": {
                    "type": "string",
                    "enum": [
                      "qwen-image-2.1-turbo",
                      "flux2-klein-4b"
                    ],
                    "default": "qwen-image-2.1-turbo"
                  },
                  "prompt": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 2000
                  },
                  "size": {
                    "type": "string",
                    "default": "1024x1024",
                    "pattern": "^[0-9]+x[0-9]+$",
                    "description": "WIDTHxHEIGHT, each side 256–1024 and a multiple of 32"
                  },
                  "seed": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 2147483647,
                    "default": 42
                  },
                  "n": {
                    "type": "integer",
                    "enum": [
                      1
                    ],
                    "default": 1
                  }
                }
              },
              "example": {
                "prompt": "a network operations centre at night, wide shot",
                "size": "1024x576",
                "seed": 42
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The picture as base64 PNG",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "created": {
                      "type": "integer"
                    },
                    "model": {
                      "type": "string"
                    },
                    "size": {
                      "type": "string"
                    },
                    "seed": {
                      "type": "integer"
                    },
                    "seconds": {
                      "type": "number",
                      "description": "Time on our side"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "b64_json": {
                            "type": "string",
                            "description": "PNG, base64"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "bad request (unknown field or model, value out of range)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "wrong key"
          },
          "403": {
            "description": "no key"
          },
          "503": {
            "description": "busy (image and audio generation share capacity; a song also pauses image generation) or unavailable — retry shortly",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/images/edits": {
      "servers": [
        {
          "url": "https://ai.ollalink.com",
          "description": "Models"
        }
      ],
      "post": {
        "tags": [
          "Models"
        ],
        "summary": "Edit an image",
        "operationId": "imagesEdits",
        "security": [
          {
            "gpuKey": []
          }
        ],
        "description": "Host: `https://ai.ollalink.com`. Edits the uploaded picture as the prompt says; only `qwen-image-2.1-turbo` edits. Same JSON answer as image generation. Usage: 1 per picture.",
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "image",
                  "prompt"
                ],
                "properties": {
                  "image": {
                    "type": "string",
                    "format": "binary",
                    "description": "The picture to edit, up to 20 MB"
                  },
                  "prompt": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 2000
                  },
                  "size": {
                    "type": "string",
                    "default": "1024x1024",
                    "pattern": "^[0-9]+x[0-9]+$",
                    "description": "WIDTHxHEIGHT, each side 256–1024 and a multiple of 32"
                  },
                  "seed": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 2147483647,
                    "default": 42
                  },
                  "model": {
                    "type": "string",
                    "enum": [
                      "qwen-image-2.1-turbo"
                    ],
                    "default": "qwen-image-2.1-turbo"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The picture as base64 PNG",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "created": {
                      "type": "integer"
                    },
                    "model": {
                      "type": "string"
                    },
                    "size": {
                      "type": "string"
                    },
                    "seed": {
                      "type": "integer"
                    },
                    "seconds": {
                      "type": "number",
                      "description": "Time on our side"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "b64_json": {
                            "type": "string",
                            "description": "PNG, base64"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "bad request (unknown field or model, value out of range)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "wrong key"
          },
          "403": {
            "description": "no key"
          },
          "503": {
            "description": "busy (image and audio generation share capacity; a song also pauses image generation) or unavailable — retry shortly",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/diarization": {
      "servers": [
        {
          "url": "https://gpu-transcribe.ollalink.com",
          "description": "File transcription"
        }
      ],
      "post": {
        "tags": [
          "Speech-to-text"
        ],
        "summary": "Who spoke when (speaker diarization)",
        "operationId": "audioDiarization",
        "security": [
          {
            "gpuKey": []
          }
        ],
        "description": "Host: `https://gpu-transcribe.ollalink.com`. Who spoke when, up to 8 speakers, no transcript. Any audio or video up to 100 MB; the first call after a quiet period waits while the model loads. Combine with file transcription by time.",
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "file"
                ],
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary"
                  },
                  "response_format": {
                    "type": "string",
                    "enum": [
                      "json",
                      "rttm"
                    ],
                    "default": "json"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "duration": 60.0,
                  "speakers": [
                    "speaker_1",
                    "speaker_2",
                    "speaker_3"
                  ],
                  "segments": [
                    {
                      "start": 0.48,
                      "end": 3.12,
                      "speaker": "speaker_1"
                    }
                  ],
                  "seconds": 1.0
                }
              }
            }
          },
          "400": {
            "description": "bad request"
          },
          "401": {
            "description": "wrong key"
          },
          "403": {
            "description": "no key"
          },
          "503": {
            "description": "busy (another model request is running; retry after Retry-After) or unavailable"
          }
        }
      }
    },
    "/v1/languages": {
      "get": {
        "summary": "List the languages (and voices) this host serves",
        "tags": [
          "Languages"
        ],
        "description": "Answered by every host: `ai.ollalink.com` (translation, `normalize` flag), `gpu-asrhq` (batch speech-to-text, `accuracy_recognizer`, `numbers_to_digits`), `gpu-transcribe` (file transcription, `numbers_to_digits`), `gpu-live` (live captions, `locale`, `auto_detect`, `numbers_to_digits`), `gpu-asr` (realtime, `locale`, `auto_detect`, `accuracy_reread`, `numbers_to_digits`), `gpu-tts` / `gpu-voice` (speech languages with `default_voice` and `voices`). Requires the GPU API key; not counted as usage.",
        "responses": {
          "200": {
            "description": "The languages this host serves now",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "enum": [
                        "list"
                      ]
                    },
                    "route": {
                      "type": "string"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "code": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "locale": {
                            "type": "string"
                          },
                          "default_voice": {
                            "type": "string"
                          },
                          "voices": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        },
                        "required": [
                          "code",
                          "name"
                        ],
                        "additionalProperties": {
                          "type": "boolean"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "object": "list",
                  "route": "POST /v1/translate",
                  "directions": "any listed language to any other",
                  "data": [
                    {
                      "code": "en",
                      "name": "English",
                      "normalize": true
                    },
                    {
                      "code": "ja",
                      "name": "Japanese",
                      "normalize": false
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing or unknown key"
          }
        }
      }
    },
    "/v1/audio/generations": {
      "servers": [
        {
          "url": "https://ai.ollalink.com",
          "description": "Models"
        }
      ],
      "post": {
        "tags": [
          "Models"
        ],
        "summary": "Generate sound effects or instrumental music",
        "operationId": "audioGenerations",
        "security": [
          {
            "gpuKey": []
          }
        ],
        "description": "Host: `https://ai.ollalink.com`. Returns the audio file itself (`audio/wav`, 44.1 kHz stereo, 16-bit). `stable-audio-3-small-sfx` makes sound effects, `stable-audio-3-small-music` (default) instrumental music; both load per request. A request takes about 30–40 s whatever the duration, because the default image model is reloaded before it answers. Usage: seconds of audio. For songs with sung lyrics use `POST /v1/music/generations`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "prompt"
                ],
                "additionalProperties": false,
                "properties": {
                  "model": {
                    "type": "string",
                    "enum": [
                      "stable-audio-3-small-sfx",
                      "stable-audio-3-small-music"
                    ],
                    "default": "stable-audio-3-small-music"
                  },
                  "prompt": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 2000
                  },
                  "duration": {
                    "type": "number",
                    "minimum": 1,
                    "maximum": 120,
                    "default": 30,
                    "description": "Seconds of audio"
                  },
                  "seed": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 2147483647,
                    "default": 42
                  },
                  "response_format": {
                    "type": "string",
                    "enum": [
                      "wav"
                    ],
                    "default": "wav"
                  }
                }
              },
              "example": {
                "model": "stable-audio-3-small-sfx",
                "prompt": "footsteps on gravel",
                "duration": 5,
                "seed": 43
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The WAV file",
            "headers": {
              "X-Audio-Duration": {
                "schema": {
                  "type": "number"
                },
                "description": "Seconds of audio"
              },
              "X-Generation-Seconds": {
                "schema": {
                  "type": "number"
                },
                "description": "Time on our side (queue, generation, reloading); network time is extra"
              }
            },
            "content": {
              "audio/wav": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "bad request (unknown field or model, value out of range)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "wrong key"
          },
          "403": {
            "description": "no key"
          },
          "503": {
            "description": "busy (image and audio generation share capacity) or unavailable — retry shortly",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/ocr": {
      "servers": [
        {
          "url": "https://ai.ollalink.com",
          "description": "Models"
        }
      ],
      "post": {
        "tags": [
          "Models"
        ],
        "summary": "Document OCR: PDF or image to markdown (job)",
        "operationId": "ocr",
        "security": [
          {
            "gpuKey": []
          }
        ],
        "description": "Host: `https://ai.ollalink.com`. Always on. PDF, PNG, JPG, JPEG or WEBP up to 25 MB; up to 100 PDF pages per request. Runs as a job: poll `GET /v1/jobs/{id}` every 2 s; a done job carries `markdown` (each page starts with `<!-- page N -->`, tables as HTML `<table>`), `pages`, `grounding` and, with `grounding: true`, `blocks`: per page number a list of `{label, bbox: [x0, y0, x1, y1], text}` in 0–1000 page coordinates. Usage: pages, counted when the job finishes.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "file"
                ],
                "properties": {
                  "file": {
                    "type": "string",
                    "description": "The document as base64 or a data: URI"
                  },
                  "file_name": {
                    "type": "string",
                    "description": "With its extension, e.g. scan.pdf; guessed from the content when omitted"
                  },
                  "pages": {
                    "type": "string",
                    "description": "PDF pages, e.g. \"1,3-4\"; default all"
                  },
                  "grounding": {
                    "type": "boolean",
                    "default": false,
                    "description": "Also return each block with its position"
                  }
                }
              }
            },
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "file"
                ],
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary"
                  },
                  "pages": {
                    "type": "string"
                  },
                  "grounding": {
                    "type": "boolean",
                    "default": false
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted: the job id to poll",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "object": {
                      "type": "string",
                      "enum": [
                        "job"
                      ]
                    },
                    "model": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "queued"
                      ]
                    },
                    "poll": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "id": "job_…",
                  "object": "job",
                  "model": "ocr",
                  "status": "queued",
                  "poll": "/v1/jobs/job_…"
                }
              }
            }
          },
          "400": {
            "description": "bad request (unknown field or model, value out of range)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "wrong key"
          },
          "403": {
            "description": "no key"
          },
          "413": {
            "description": "file larger than 25 MB",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "busy (full queue) or unavailable — retry later",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/music/generations": {
      "servers": [
        {
          "url": "https://ai.ollalink.com",
          "description": "Models"
        }
      ],
      "post": {
        "tags": [
          "Models"
        ],
        "summary": "Song from a style and tagged lyrics (job)",
        "operationId": "musicGenerations",
        "security": [
          {
            "gpuKey": []
          }
        ],
        "description": "Host: `https://ai.ollalink.com`. On demand; runs as a job because a song takes longer than the 100-second request limit (a song of about a minute took about two minutes in our tests). Lyrics need section tags: `[Intro]` `[Verse]` `[Chorus]` `[Bridge]` `[Outro]`. Poll `GET /v1/jobs/{id}`; a done job carries `duration_s`, `seed`, `precision` and `audio` links to `/v1/jobs/{id}/content?format=m4a` or `?format=flac`. While a song is generating, image requests wait and may get 503 busy. **The song model's licence is non-commercial only.** Sending `\"model\": \"stable-audio-3-small-music\"` here returns an instrumental WAV straight away instead, with the request fields of `POST /v1/audio/generations`. Usage: seconds of audio.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "style",
                  "lyrics"
                ],
                "additionalProperties": false,
                "properties": {
                  "style": {
                    "type": "string",
                    "maxLength": 500,
                    "description": "e.g. \"upbeat electronic pop, female vocal\""
                  },
                  "lyrics": {
                    "type": "string",
                    "maxLength": 6000,
                    "description": "With section tags"
                  },
                  "seed": {
                    "type": "integer"
                  },
                  "precision": {
                    "type": "string",
                    "enum": [
                      "bf16",
                      "8bit"
                    ]
                  },
                  "model": {
                    "type": "string",
                    "enum": [
                      "music"
                    ],
                    "description": "Optional; `music` is the song model"
                  }
                }
              },
              "example": {
                "style": "upbeat electronic pop, female vocal",
                "lyrics": "[Verse]\nRouters hum along the line\n[Chorus]\nOpen wide",
                "seed": 42
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted: the job id to poll",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "object": {
                      "type": "string",
                      "enum": [
                        "job"
                      ]
                    },
                    "model": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "queued"
                      ]
                    },
                    "poll": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "id": "job_…",
                  "object": "job",
                  "model": "music",
                  "status": "queued",
                  "poll": "/v1/jobs/job_…"
                }
              }
            }
          },
          "400": {
            "description": "bad request (unknown field or model, value out of range)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "wrong key"
          },
          "403": {
            "description": "no key"
          },
          "503": {
            "description": "busy (full queue) or unavailable — retry later",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/jobs/{id}": {
      "servers": [
        {
          "url": "https://ai.ollalink.com",
          "description": "Models"
        }
      ],
      "get": {
        "tags": [
          "Models"
        ],
        "summary": "Job status and result",
        "operationId": "getJob",
        "security": [
          {
            "gpuKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The job id from the POST"
          }
        ],
        "description": "Status goes `queued` → `running` → `done` or `failed` (with `error`). Jobs are kept for 24 hours and only the key that created a job can read it. Not counted as usage.",
        "responses": {
          "200": {
            "description": "The job",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "object": {
                      "type": "string",
                      "enum": [
                        "job"
                      ]
                    },
                    "model": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "queued",
                        "running",
                        "done",
                        "failed"
                      ]
                    },
                    "created": {
                      "type": "integer"
                    },
                    "seconds": {
                      "type": "number"
                    },
                    "error": {
                      "type": "string"
                    },
                    "markdown": {
                      "type": "string",
                      "description": "OCR, when done"
                    },
                    "pages": {
                      "type": "string",
                      "description": "OCR: \"all\" or your range"
                    },
                    "grounding": {
                      "type": "boolean"
                    },
                    "blocks": {
                      "type": "object",
                      "description": "OCR with grounding: page number → list of {label, bbox, text}"
                    },
                    "audio": {
                      "type": "object",
                      "description": "Music: format → download path",
                      "additionalProperties": {
                        "type": "string"
                      }
                    },
                    "duration_s": {
                      "type": "number"
                    },
                    "seed": {
                      "type": "integer"
                    },
                    "precision": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "wrong key"
          },
          "403": {
            "description": "no key"
          },
          "404": {
            "description": "unknown or expired job, or a job made with a different key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "the job's machine is not answering; retry shortly",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/jobs/{id}/content": {
      "servers": [
        {
          "url": "https://ai.ollalink.com",
          "description": "Models"
        }
      ],
      "get": {
        "tags": [
          "Models"
        ],
        "summary": "Download a job's file (song audio)",
        "operationId": "getJobContent",
        "security": [
          {
            "gpuKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The job id from the POST"
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "m4a",
                "flac"
              ]
            },
            "description": "m4a (AAC, small; default) or flac (48 kHz stereo, lossless)"
          }
        ],
        "description": "Not counted as usage.",
        "responses": {
          "200": {
            "description": "The file",
            "content": {
              "audio/mp4": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "audio/flac": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "unknown format",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "wrong key"
          },
          "403": {
            "description": "no key"
          },
          "404": {
            "description": "unknown or expired job or file",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "the job is not done yet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "gpuKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-NH-GPU-Key",
        "description": "GPU API key from the dashboard (`sk_…`; a legacy shared key works until 3 November 2026) — the text tools on ai.ollalink.com and every gpu-* host. A missing key is blocked at the edge with 403; an unknown key returns 401. Note the edge rejects some automated clients: Python's stdlib `urllib` (`User-Agent: Python-urllib/3.x`) gets 403 even with a valid key."
      }
    },
    "schemas": {
      "TranscriptionForm": {
        "type": "object",
        "required": [
          "file"
        ],
        "properties": {
          "file": {
            "type": "string",
            "format": "binary"
          },
          "language": {
            "type": "string",
            "description": "One of `en`, `hi`, `es`, `fr`, `zh`, `de`, `ar`, `pt`, `ru`, `ja`, `ko`, `it`, `nl`, `vi`; omit to auto-detect. Pin `hi` for Hindi."
          },
          "word_timestamps": {
            "type": "boolean",
            "description": "Adds `words` (`start`, `end`, `word`) inside each segment"
          },
          "beam_size": {
            "type": "integer",
            "default": 5
          }
        }
      },
      "Transcription": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string"
          },
          "language": {
            "type": "string"
          },
          "language_probability": {
            "type": "number"
          },
          "duration": {
            "type": "number",
            "description": "gpu-asrhq only"
          },
          "segments": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "integer"
                },
                "start": {
                  "type": "number"
                },
                "end": {
                  "type": "number"
                },
                "text": {
                  "type": "string"
                },
                "words": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "start": {
                        "type": "number"
                      },
                      "end": {
                        "type": "number"
                      },
                      "word": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "StudioAudio": {
        "type": "object",
        "properties": {
          "audio_wav_b64": {
            "type": "string",
            "description": "Base64-encoded WAV"
          },
          "sr": {
            "type": "integer",
            "examples": [
              24000
            ]
          },
          "audio_s": {
            "type": "number"
          },
          "wall_s": {
            "type": "number"
          },
          "instruct_used": {
            "type": "string",
            "description": "The description the voice was built from, echoed back verbatim"
          },
          "mode": {
            "type": "string",
            "description": "/clone only — `ultimate` when `ref_text` was supplied, otherwise `standard`"
          }
        },
        "description": "Paused voice studio routes only (kept for reference)."
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "message": {
                "type": "string"
              },
              "type": {
                "type": "string"
              },
              "code": {
                "type": "string"
              }
            }
          }
        }
      },
      "TranslateRequest": {
        "type": "object",
        "required": [
          "text",
          "target"
        ],
        "additionalProperties": false,
        "properties": {
          "text": {
            "type": "string",
            "minLength": 1,
            "maxLength": 5000,
            "description": "The text to translate, up to 5,000 characters"
          },
          "target": {
            "type": "string",
            "enum": [
              "en",
              "hi",
              "es",
              "fr",
              "zh",
              "de",
              "ar",
              "pt",
              "ru",
              "ja",
              "ko",
              "it",
              "nl",
              "vi",
              "ta"
            ],
            "description": "Target language code (`pt` = Brazilian Portuguese; `ta` = Tamil, text translation only); any other code answers 400 `unsupported_language`"
          },
          "source": {
            "type": "string",
            "enum": [
              "en",
              "hi",
              "es",
              "fr",
              "zh",
              "de",
              "ar",
              "pt",
              "ru",
              "ja",
              "ko",
              "it",
              "nl",
              "vi",
              "ta"
            ],
            "description": "Source language code, when known; omit it to let the translator work it out (Tamil text is recognised by its script)"
          },
          "stream": {
            "type": "boolean",
            "default": false,
            "description": "true: the translation arrives as Server-Sent Events while it is written (`data: {\"delta\"}` pieces, then one `data: {\"done\": true, \"translation\", \"numbers_verified\", \"source\", \"target\", \"characters\"}`, or `data: {\"error\"}` if it stops part-way). No automatic retry in this mode; `numbers_verified` reports the check."
          }
        }
      },
      "TranslateResponse": {
        "type": "object",
        "properties": {
          "translation": {
            "type": "string"
          },
          "source": {
            "type": [
              "string",
              "null"
            ],
            "description": "Echo of the request"
          },
          "target": {
            "type": "string",
            "description": "Echo of the request"
          },
          "numbers_verified": {
            "type": "boolean",
            "description": "`true` when every number and placeholder in the source appears in the translation (after one automatic retry); `false` means review them"
          },
          "characters": {
            "type": "integer",
            "description": "Length of the source text (what is counted for usage)"
          }
        }
      },
      "TranslateError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              }
            }
          }
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Malformed request, an unknown field, or input over the limit",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "GpuForbidden": {
        "description": "Missing or wrong `X-NH-GPU-Key`, blocked at the edge. Can also indicate a rejected HTTP client User-Agent.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    }
  }
}
