{"openapi":"3.1.0","info":{"title":"Djelia","description":"Welcome to the **Djelia API Documentation**! 🎉\n\nDjelia is your gateway to powerful linguistic models tailored for African languages. We are proud to currently support **Bambara**, one of the most widely spoken languages in Mali. As we grow, we aim to include support for many more African languages.\n\n### Getting Started\nGet an API key from the [Djelia Console](https://console.djelia.cloud), then point any OpenAI-compatible client at Djelia:\n\n```python\nfrom openai import OpenAI\n\nclient = OpenAI(\n    api_key=\"YOUR_DJELIA_API_KEY\",\n    base_url=\"https://api.djelia.cloud/openai/v1\",\n)\n```\n\nThis is the primary surface. The native `/v1` and `/v2` endpoints take the same key in the `x-api-key` header.\n\n### Current Features\n- **Transcription Models**: Effortlessly transcribe audio into text using our Bambara models, with support for real-time streaming ✨.\n- **Translation Models**: Seamlessly translate between Bambara, French, and English, unlocking cross-lingual communication.\n- **Text-to-Speech Models**: [Experimental] Bring Bambara text to life with human-like speech synthesis.\n\n### What's Next?\nWe’re constantly improving and expanding. Soon, you can expect:\n- Support for additional African languages.\n- Advanced features to enhance your applications.\n\nWe’re thrilled to have you on board. Let’s build something extraordinary together! 🚀","version":"0.1.0"},"paths":{"/openai/v1/models":{"get":{"tags":["OpenAI Compatibility"],"summary":"List Models","description":"List the models available to your account.\n\nMirrors `GET /v1/models`, so `client.models.list()` works unchanged.\n\n**Example Response:**\n```json\n{\n    \"object\": \"list\",\n    \"data\": [\n        {\"id\": \"sunjata-1\", \"object\": \"model\", \"created\": 1735689600, \"owned_by\": \"djelia\"},\n        {\"id\": \"jifili-1\", \"object\": \"model\", \"created\": 1735689600, \"owned_by\": \"djelia\"}\n    ]\n}\n```","operationId":"OpenAI Compatibility-List models","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModelList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAIError"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAIError"}}}},"402":{"description":"Insufficient balance","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAIError"}}}},"404":{"description":"Unknown model or endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAIError"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAIError"}}}}},"security":[{"Bearer token":[]},{"API Key":[]}]}},"/openai/v1/models/{model}":{"get":{"tags":["OpenAI Compatibility"],"summary":"Retrieve Model","description":"Retrieve a single model.\n\nMirrors `GET /v1/models/{model}`, so `client.models.retrieve(\"jifili-1\")`\nworks unchanged. OpenAI model names accepted as aliases resolve to the Djelia\nmodel they map onto, and the response reports that canonical id.","operationId":"OpenAI Compatibility-Retrieve model","security":[{"Bearer token":[]},{"API Key":[]}],"parameters":[{"name":"model","in":"path","required":true,"schema":{"type":"string","title":"Model"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModelObject"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAIError"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAIError"}}}},"402":{"description":"Insufficient balance","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAIError"}}}},"404":{"description":"Unknown model or endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAIError"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAIError"}}}}}}},"/openai/v1/audio/transcriptions":{"post":{"tags":["OpenAI Compatibility"],"summary":"Transcribe Audio","description":"Transcribe audio into Bambara text.\n\nMirrors `POST /v1/audio/transcriptions`, so `client.audio.transcriptions.create()`\nworks unchanged.\n\n**Parameters:**\n- `file`: the audio file to transcribe.\n- `model`: `sunjata-1` (default), `djelia-asr-v2` or `djelia-asr-v1`.\n- `response_format`: `json` (default), `text`, `verbose_json`, `srt`, `vtt`.\n  Djelia's ASR returns per-segment timestamps, so `verbose_json`, `srt` and `vtt`\n  all carry real timings.\n- `stream`: when true, emits `transcript.text.segment` and `transcript.text.delta`\n  events over SSE.\n\n`temperature` reaches `sunjata-1`, which decodes with it; the older models ignore\nit.\n\n**Ignored:** `language` (Djelia's ASR is Bambara-only), `prompt`,\n`timestamp_granularities` (segment timings are always returned in `verbose_json`).\n\n**Example Response (`response_format=\"json\"`):**\n```json\n{\"text\": \"Aw ni ce i ka kene wa.\"}\n```","operationId":"OpenAI Compatibility-Transcribe audio","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_OpenAI_Compatibility-Transcribe_audio"}}},"required":true},"responses":{"200":{"description":"The transcript, in the requested `response_format`. `stream=true` returns `transcript.text.delta` events instead.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/TranscriptionResponse"},{"$ref":"#/components/schemas/TranscriptionVerboseResponse"}],"title":"Response 200 Openai Compatibility-Transcribe Audio"}},"text/plain":{"schema":{"type":"string"}},"text/event-stream":{"schema":{"type":"string"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAIError"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAIError"}}}},"402":{"description":"Insufficient balance","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAIError"}}}},"404":{"description":"Unknown model or endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAIError"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAIError"}}}}},"security":[{"Bearer token":[]},{"API Key":[]}]}},"/openai/v1/audio/translations":{"post":{"tags":["OpenAI Compatibility"],"summary":"Transcribe And Translate Audio","description":"Transcribe Bambara audio and translate the result.\n\nMirrors `POST /v1/audio/translations`, so `client.audio.translations.create()`\nworks unchanged. OpenAI's endpoint always targets English; Djelia defaults to\nEnglish and additionally accepts `language=\"fra_Latn\"` for French, since French is\nthe pairing Bambara speakers most often want.\n\n**Billing:** this endpoint runs two models, so it is charged for two: the\ntranscription per second of audio, and the translation per character of the\ntranscript, each at its own rate. They appear as two usage records against the\nsame request. A translation that fails is not charged.\n\n`temperature` reaches `sunjata-1` only.\n\n**Ignored:** `prompt`.","operationId":"OpenAI Compatibility-Transcribe and translate audio","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_OpenAI_Compatibility-Transcribe_and_translate_audio"}}},"required":true},"responses":{"200":{"description":"The translated transcript.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranscriptionResponse"}},"text/plain":{"schema":{"type":"string"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAIError"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAIError"}}}},"402":{"description":"Insufficient balance","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAIError"}}}},"404":{"description":"Unknown model or endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAIError"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAIError"}}}}},"security":[{"Bearer token":[]},{"API Key":[]}]}},"/openai/v1/audio/speech":{"post":{"tags":["OpenAI Compatibility"],"summary":"Synthesise Speech","description":"Synthesise speech from Bambara text.\n\nMirrors `POST /v1/audio/speech`, so `client.audio.speech.create()` works unchanged.\n\n**Parameters:**\n- `input`: the text to synthesise.\n- `model`: `jifili-1` (default), `djelia-tts-v2` or `djelia-tts-v1`.\n- `voice`: `moussa`, `sekou` or `seydou`. OpenAI's voice names are accepted as\n  aliases. `jifili-1` serves `moussa` only, and answers 400 `unsupported_voice`\n  for the others.\n- `response_format`: `jifili-1` serves `mp3` (default), `wav`, `pcm`, `opus`,\n  `ulaw`, `alaw`, `l16_8000`, `l16_16000` and `fmp4` (AAC in fragmented MP4);\n  it answers 422 `invalid_request` for the legacy-only names `flac`, `aac`,\n  `wav_8k` and `ulaw_8k`. The older models serve\n  `mp3`, `opus`, `aac`, `flac`, `wav`, `pcm` and the telephony formats `wav_8k` and\n  `ulaw_8k`, and answer 400 for a format their encoder lacks.\n- `stream_format`: `audio` (default) for raw bytes, `sse` for\n  `speech.audio.delta` events.\n\n**Djelia extension.** TTS v2 is prompt-steerable, which the fixed OpenAI `voice`\nenum cannot express. Pass a free-text description to reach it:\n\n```python\nclient.audio.speech.create(\n    model=\"djelia-tts-v2\",\n    input=\"Aw ni ce, i ka kene wa?\",\n    voice=\"moussa\",\n    extra_body={\"djelia\": {\"description\": \"speaks slowly, warm and reassuring\"}},\n)\n```\n\n`jifili-1` selects a voice by name, so `djelia.description` does not reach it.\nIts sampling is steered by `djelia.temperature`, `djelia.top_p` and\n`djelia.repetition_penalty`; each one left out keeps the model's own default.\n\nA synthesis that fails once it is under way ends the stream where it stopped, since\nthe status line has already been sent.\n\n**Ignored:** `speed`, `instructions` (use `djelia.description` instead).","operationId":"OpenAI Compatibility-Synthesise speech","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpeechRequest"}}},"required":true},"responses":{"200":{"description":"The synthesised audio in the requested `response_format`. `stream_format=\"sse\"` returns `speech.audio.delta` events instead.","content":{"audio/mpeg":{"schema":{"type":"string","format":"binary"}},"audio/wav":{"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"}},"audio/pcm":{"schema":{"type":"string","format":"binary"}},"text/event-stream":{"schema":{"type":"string"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAIError"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAIError"}}}},"402":{"description":"Insufficient balance","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAIError"}}}},"404":{"description":"Unknown model or endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAIError"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAIError"}}}}},"security":[{"Bearer token":[]},{"API Key":[]}]}},"/openai/v1/chat/completions":{"post":{"tags":["OpenAI Compatibility"],"summary":"Translate Text","description":"Translate text between Bambara, French and English.\n\nText translation has no dedicated endpoint in the OpenAI shape, so Djelia's\ntranslation model is addressed as a chat model. The text to translate is the last\nuser message; the language pair comes from `extra_body`.\n\n```python\nclient.chat.completions.create(\n    model=\"banjugu-1\",\n    messages=[{\"role\": \"user\", \"content\": \"Bonjour\"}],\n    extra_body={\"djelia\": {\"source_language\": \"fra_Latn\", \"target_language\": \"bam_Latn\"}},\n)\n```\n\nLanguages use the same codes as the native API: `bam_Latn`, `fra_Latn`,\n`eng_Latn`.\n\n**Usage counts are characters, not tokens.** Djelia meters translation per\ncharacter, and `usage` reports what you are actually billed for.\n\n**Ignored:** `temperature`, `top_p`, `n`, `max_tokens`, `stop`, `presence_penalty`,\n`frequency_penalty`, `logit_bias`, `logprobs`, `top_logprobs`, `seed`, `user`,\n`response_format`, `tools`, `tool_choice`, `store`, `metadata`, `service_tier`.\nDjelia's translation model is not a general chat model and has no tool use.","operationId":"OpenAI Compatibility-Translate text","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatCompletionRequest"}}},"required":true},"responses":{"200":{"description":"The translation. `stream=true` returns `chat.completion.chunk` events instead.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatCompletion"}},"text/event-stream":{"schema":{"type":"string"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAIError"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAIError"}}}},"402":{"description":"Insufficient balance","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAIError"}}}},"404":{"description":"Unknown model or endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAIError"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAIError"}}}}},"security":[{"Bearer token":[]},{"API Key":[]}]}},"/v1/models/translate/supported-languages":{"get":{"tags":["Models","Translation"],"summary":"Get Supported Translation Languages","description":"Retrieve a list of supported languages for translation.\n\n**What does this endpoint do?**\n- Returns all languages supported by the Djelia translation API.\n- Each language is represented by:\n    - `code`: The language code (e.g., \"bam_Latn\" for Bambara).\n    - `name`: The human-readable name of the language (e.g., \"Bambara\").\n\n**How to use this endpoint?**\n- Call this endpoint to get the language codes needed for configuring `source` and `target` parameters in translation requests.\n\n**Example Response**:\n```json\n[\n    {\"code\": \"bam_Latn\", \"name\": \"Bambara\"},\n    {\"code\": \"fra_Latn\", \"name\": \"French\"},\n    {\"code\": \"eng_Latn\", \"name\": \"English\"}\n]\n```\n\nReturns:\n    List[SupportedLanguageSchema]: A list of supported languages.","operationId":"Models-translate_supported_languages","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/SupportedLanguageSchema"},"type":"array","title":"Response Models-Translate Supported Languages"}}}}},"security":[{"API Key":[]}],"x-codeSamples":[{"lang":"Python","label":"Python","source":"import requests\n\nurl = \"https://api.djelia.cloud/api/v1/models/translate/supported-languages\"\nheaders = {\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"Content-Type\": \"application/json\"\n}\nresponse = requests.get(url, headers=headers)\nif response.status_code == 200:\n    print(\"Supported Languages:\", response.json())\nelse:\n    print(\"Failed to fetch supported languages\")"},{"lang":"cURL","label":"cURL","source":"curl -X GET \"https://api.djelia.cloud/api/v1/models/translate/supported-languages\" \\\n-H \"x-api-key: YOUR_API_KEY\" \\\n-H \"accept: application/json\""},{"lang":"Dart","label":"Dart","source":"import 'dart:convert';\nimport 'package:http/http.dart' as http;\n\nvoid main() async {\n  final headers = {\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"Content-Type\": \"application/json\"\n  };\n  final url = Uri.parse('https://api.djelia.cloud/api/v1/models/translate/supported-languages');\n  final response = await http.get(url, headers: headers);\n\n  if (response.statusCode == 200) {\n    print('Supported Languages: ${jsonDecode(response.body)}');\n  } else {\n    print('Failed to fetch supported languages: ${response.reasonPhrase}');\n  }\n}"}]}},"/v1/models/translate":{"post":{"tags":["Models","Translation"],"summary":"Translation","description":"Translate text between supported languages.\n\n**What does this endpoint do?**\n- This endpoint translates text from a specified source language to a target language.\n- It supports Bambara, French, and English.\n\n**Request Requirements:**\n- The request body must include:\n    - `text` (str): The text to translate.\n    - `source` (str): The language code of the source text (e.g., \"fra_Latn\").\n    - `target` (str): The language code of the target language (e.g., \"bam_Latn\").\n\n**Headers:**\n- `x-api-key`: Your API key for authentication.\n- `Content-Type`: Must be set to `application/json`.\n\n**Example Request Body:**\n```json\n{\n    \"text\": \"Bonjour\",\n    \"source\": \"fra_Latn\",\n    \"target\": \"bam_Latn\"\n}\n```\n\n**Example Response:**\n```json\n{\n    \"text\": \"Aw ni ce\"\n}\n```\n\n**How to use this endpoint?**\n- Use the `/translate/supported-languages` endpoint to get a list of valid language codes.\n- Provide the `text`, `source`, and `target` fields in the request body.\n\nReturns:\n    TranslationResponse: A dictionary containing the translated text.","operationId":"Models-Translation","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranslationRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranslationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"API Key":[]}],"x-codeSamples":[{"lang":"Python","label":"Python","source":"import requests\n\nurl = \"https://api.djelia.cloud/api/v1/models/translate\"\nheaders = {\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"Content-Type\": \"application/json\"\n}\npayload = {\n    \"text\": \"Bonjour\",\n    \"source\": \"fra_Latn\",\n    \"target\": \"bam_Latn\"\n}\n\nresponse = requests.post(url, json=payload, headers=headers)\nif response.status_code == 200:\n    print(\"Translation:\", response.json())\nelse:\n    print(\"Failed to translate:\", response.status_code, response.text)"},{"lang":"cURL","label":"cURL","source":"curl -X POST \"https://api.djelia.cloud/api/v1/models/translate\" \\\n-H \"x-api-key: YOUR_API_KEY\" \\\n-H \"Content-Type: application/json\" \\\n-d '{\n    \"text\": \"Bonjour\",\n    \"source\": \"fra_Latn\",\n    \"target\": \"bam_Latn\"\n}' "},{"lang":"Dart","label":"Dart","source":"import 'dart:convert';\nimport 'package:http/http.dart' as http;\n\nvoid main() async {\n  final url = Uri.parse('https://api.djelia.cloud/api/v1/models/translate');\n  final headers = {\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"Content-Type\": \"application/json\"\n  };\n  final payload = {\n    \"text\": \"Bonjour\",\n    \"source\": \"fra_Latn\",\n    \"target\": \"bam_Latn\"\n  };\n\n  final response = await http.post(\n    url,\n    headers: headers,\n    body: jsonEncode(payload),\n  );\n\n  if (response.statusCode == 200) {\n    print(\"Translation: ${jsonDecode(response.body)}\");\n  } else {\n    print(\"Failed to translate: ${response.statusCode}, ${response.body}\");\n  }\n}"}]}},"/v1/models/transcribe/stream":{"post":{"tags":["Models","Transcription"],"summary":"Streaming Transcription","description":"Perform streaming transcription of an uploaded audio file, with optional French translation.\n\n**What does this endpoint do?**\n- Transcribes audio content into text in real-time using Bambara models.\n- Optionally translates the transcribed text into French if `translate_to_french` is set to `True`.\n\n**Behavior Notes:**\n- If `translate_to_french=False` (default):\n    - Each streamed response represents a **chunk** of the transcribed text.\n- If `translate_to_french=True`:\n    - Each streamed response represents the **entire transcription** up to that point, translated into French.\n    - This is because translation requires full context for accurate results.\n\n**Headers:**\n- `x-api-key`: Your API key for authentication.\n\n**Parameters:**\n- `file` (UploadFile): The audio file to transcribe.\n- `translate_to_french` (bool): Whether to translate the transcription into French. Defaults to `False`.\n\n**Example Response (Chunk Mode - translate_to_french=False):**\n```json\n{\"text\": \"Aw ni ce\", \"start\": 0.0, \"end\": 0.2}\n{\"text\": \"I ka kene wa?\", \"start\": 0.2, \"end\": 0.4}\n```\n\n**Example Response (Full Text Mode - translate_to_french=True):**\n```json\n{\"text\": \"Bonjour, comment ça va?\"}\n```\n\n**Caution:**\n- Translation introduces latency because it requires the full transcription context for accuracy. Expect longer delays when `translate_to_french=True`.\n\nReturns:\n    StreamingResponse: A streaming JSON response containing transcription and optional translation.","operationId":"Models-Streaming Transcription","security":[{"API Key":[]}],"parameters":[{"name":"translate_to_french","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Flag to translate transcriptions into French","default":false,"title":"Translate To French"},"description":"Flag to translate transcriptions into French"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_Models-Streaming_Transcription"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/FrenchTranscriptionResponse"},{"$ref":"#/components/schemas/TranscriptionSegment"}],"title":"Response Models-Streaming Transcription"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"x-codeSamples":[{"lang":"Python","label":"Python","source":"import requests\n\nurl = \"https://api.djelia.cloud/api/v1/models/transcribe/stream\"\nheaders = {\n    \"x-api-key\": \"YOUR_API_KEY\",\n}\nfiles = {\n    \"file\": open(\"audio_file.wav\", \"rb\")\n}\nparams = {\n    \"translate_to_french\": True\n}\n\nresponse = requests.post(url, headers=headers, files=files, params=params, stream=True)\nfor line in response.iter_lines():\n    if line:\n        print(\"Streamed Response:\", line.decode('utf-8'))"},{"lang":"cURL","label":"cURL","source":"curl -X POST \"https://api.djelia.cloud/api/v1/models/transcribe/stream\" \\\n-H \"x-api-key: YOUR_API_KEY\" \\\n-F \"file=@audio_file.wav\" \\\n-G --data-urlencode \"translate_to_french=true\""},{"lang":"Dart","label":"Dart","source":"import 'dart:convert';\nimport 'dart:io';\n\nvoid main() async {\n  final file = File('audio_file.wav');\n  final uri = Uri.parse('https://api.djelia.cloud/api/v1/models/transcribe/stream');\n  final request = HttpClientRequest();\n\n  final requestBody = await file.readAsBytes();\n  \n  final headers = {\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"Content-Type\": \"multipart/form-data\"\n  };\n\n  final queryParams = {'translate_to_french': 'true'};\n  final fullUri = uri.replace(queryParameters: queryParams);\n\n  final response = await HttpClient().postUrl(fullUri)\n    ..headers.addAll(headers)\n    ..add(requestBody);\n\n  final responseStream = await response.close();\n\n  await for (final data in responseStream.transform(utf8.decoder)) {\n    print('Streamed Response: $data');\n  }\n}"}]}},"/v1/models/transcribe":{"post":{"tags":["Models","Transcription"],"summary":"Transcription","description":"Perform audio transcription in a synchronous manner, with optional French translation.\n\n**What does this endpoint do?**\n- Transcribes the audio file content into text using Bambara models.\n- Optionally translates the transcribed text into French if `translate_to_french` is set to `True`.\n\n**Behavior Notes:**\n- If `translate_to_french=False` (default):\n    - The response contains a list of transcribed segment in Bambara.\n- If `translate_to_french=True`:\n    - The response contains the full transcription translated into French.\n\n**Headers:**\n- `x-api-key`: Your API key for authentication.\n- `Content-Type`: Must be set to `multipart/form-data`.\n\n**Parameters:**\n- `file` (UploadFile): The audio file to transcribe.\n- `translate_to_french` (bool): Whether to translate the transcription into French. Defaults to `False`.\n\n**Example Request Body:**\n```text\nfile: <binary file>\ntranslate_to_french: true\n```\n\n**Example Response (translate_to_french=False):**\n```json\n[\n    {\n        \"text\": \"Aw ni ce i ka kene wa.\",\n        \"start\": 0.0,\n        \"end\": 1.0,\n    }\n]\n```\n\n**Example Response (translate_to_french=True):**\n```json\n{\n    \"text\": \"Bonjour, comment ça va?\"\n}\n```\n\n**Caution:**\n- Translation introduces additional latency as it processes the full transcription for context.\n\nReturns:\n    FrenchTranscriptionResponse: A dictionary containing the transcribed (and optionally translated) text.","operationId":"Models-Transcription","security":[{"API Key":[]}],"parameters":[{"name":"translate_to_french","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Flag to translate transcriptions into French","default":false,"title":"Translate To French"},"description":"Flag to translate transcriptions into French"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_Models-Transcription"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/FrenchTranscriptionResponse"},{"type":"array","items":{"$ref":"#/components/schemas/TranscriptionSegment"}}],"title":"Response Models-Transcription"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"x-codeSamples":[{"lang":"Python","label":"Python","source":"import requests\n\nurl = \"https://api.djelia.cloud/api/v1/models/transcribe\"\nheaders = {\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"Content-Type\": \"multipart/form-data\"\n}\nfiles = {\n    \"file\": open(\"audio_file.wav\", \"rb\")\n}\nparams = {\n    \"translate_to_french\": True\n}\n\nresponse = requests.post(url, headers=headers, files=files, params=params)\nif response.status_code == 200:\n    print(\"Transcription:\", response.json())\nelse:\n    print(\"Failed to transcribe:\", response.status_code, response.text)"},{"lang":"cURL","label":"cURL","source":"curl -X POST \"https://api.djelia.cloud/api/v1/models/transcribe\" \\\n-H \"x-api-key: YOUR_API_KEY\" \\\n-F \"file=@audio_file.wav\" \\\n-G --data-urlencode \"translate_to_french=true\""},{"lang":"Dart","label":"Dart","source":"import 'dart:convert';\nimport 'dart:io';\nimport 'package:http/http.dart' as http;\n\nvoid main() async {\n  final url = Uri.parse('https://api.djelia.cloud/api/v1/models/transcribe');\n  final headers = {\n    \"x-api-key\": \"YOUR_API_KEY\",\n  };\n  final queryParams = {'translate_to_french': 'true'};\n  final file = http.MultipartFile.fromBytes(\n    'file',\n    File('audio_file.wav').readAsBytesSync(),\n    filename: 'audio_file.wav',\n  );\n\n  final request = http.MultipartRequest('POST', url..replace(queryParameters: queryParams))\n    ..headers.addAll(headers)\n    ..files.add(file);\n\n  final response = await request.send();\n\n  if (response.statusCode == 200) {\n    final body = await response.stream.bytesToString();\n    print('Transcription: ${jsonDecode(body)}');\n  } else {\n    print('Failed to transcribe: ${response.statusCode}');\n  }\n}"}]}},"/v1/models/tts":{"post":{"tags":["Models","Text-to-Speech"],"summary":"Text To Speech","description":"Generate speech audio from Bambara text.\n\n**What does this endpoint do?**\n- Converts text into speech audio using Bambara models.\n- Allows selecting different speaker profiles for synthesized speech.\n\n**Headers:**\n- `x-api-key`: Your API key for authentication.\n- `Content-Type`: Must be set to `application/json`.\n\n**Parameters:**\n- `text` (str): The input text to be synthesized into speech.\n- `speaker` (int): The ID of the speaker profile to use for speech synthesis.\n\n**Example Request Body:**\n```json\n{\n    \"text\": \"Aw ni ce\",\n    \"speaker\": 1\n}\n```\n\n**Response:**\n- Returns the synthesized audio in WAV format.\n\n**Example Response Usage:**\n- Save the response content as a `.wav` file to listen to the generated audio.\n\n**How to use this endpoint?**\n- Provide the text and speaker parameters in the request body.\n- Use the returned WAV file in your applications, or save it for playback.\n\n**Caution:**\n- The response is a binary stream (audio), so ensure your application can handle binary responses.\n\nReturns:\n    Response: The synthesized audio in WAV format.","operationId":"Models-Text To Speech","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TTSRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"API Key":[]}],"x-codeSamples":[{"lang":"Python","label":"Python","source":"import requests\n\nurl = \"https://api.djelia.cloud/api/v1/models/tts\"\nheaders = {\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"Content-Type\": \"application/json\"\n}\npayload = {\n    \"text\": \"Aw ni ce\",\n    \"speaker\": 1\n}\n\nresponse = requests.post(url, headers=headers, json=payload)\nif response.status_code == 200:\n    with open(\"output.wav\", \"wb\") as f:\n        f.write(response.content)\n    print(\"Audio saved as output.wav\")\nelse:\n    print(\"Failed to generate audio:\", response.status_code, response.text)"},{"lang":"cURL","label":"cURL","source":"curl -X POST \"https://api.djelia.cloud/api/v1/models/tts\" \\\n-H \"x-api-key: YOUR_API_KEY\" \\\n-H \"Content-Type: application/json\" \\\n-d '{\n    \"text\": \"Aw ni ce\",\n    \"speaker\": 1\n}' --output output.wav"},{"lang":"Dart","label":"Dart","source":"import 'dart:convert';\nimport 'dart:io';\nimport 'package:http/http.dart' as http;\n\nvoid main() async {\n  final url = Uri.parse('https://api.djelia.cloud/api/v1/models/tts');\n  final headers = {\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"Content-Type\": \"application/json\"\n  };\n  final payload = {\n    \"text\": \"Aw ni ce\",\n    \"speaker\": 1\n  };\n\n  final response = await http.post(\n    url,\n    headers: headers,\n    body: jsonEncode(payload),\n  );\n\n  if (response.statusCode == 200) {\n    final file = File('output.wav');\n    await file.writeAsBytes(response.bodyBytes);\n    print(\"Audio saved as output.wav\");\n  } else {\n    print(\"Failed to generate audio: ${response.statusCode}\");\n  }\n}"}]}},"/v2/models/transcribe/stream":{"post":{"tags":["Models","Transcription"],"summary":"Streaming Transcription V2","description":"Perform streaming transcription using the V2 model which perform better when audio are short and contains french words.\n\n**What does this endpoint do?**\n- Transcribes audio content into text in real-time using Bambara models.\n- Optionally translates the transcribed text into French if `translate_to_french` is set to `True`.\n\n**Behavior Notes:**\n- If `translate_to_french=False` (default):\n    - Each streamed response represents a **chunk** of the transcribed text.\n- If `translate_to_french=True`:\n    - Each streamed response represents the **entire transcription** up to that point, translated into French.\n    - This is because translation requires full context for accurate results.\n\n**Headers:**\n- `x-api-key`: Your API key for authentication.\n\n**Parameters:**\n- `file` (UploadFile): The audio file to transcribe.\n- `translate_to_french` (bool): Whether to translate the transcription into French. Defaults to `False`.\n\n**Example Response (Chunk Mode - translate_to_french=False):**\n```json\n{\"text\": \"Aw ni ce\", \"start\": 0.0, \"end\": 0.2}\n{\"text\": \"I ka kene wa?\", \"start\": 0.2, \"end\": 0.4}\n```\n\n**Example Response (Full Text Mode - translate_to_french=True):**\n```json\n{\"text\": \"Bonjour, comment ça va?\"}\n```\n\n**Caution:**\n- Translation introduces latency because it requires the full transcription context for accuracy. Expect longer delays when `translate_to_french=True`.\n\nReturns:\n    StreamingResponse: A streaming JSON response containing transcription and optional translation.","operationId":"Models-Streaming Transcription V2","security":[{"API Key":[]}],"parameters":[{"name":"translate_to_french","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Flag to translate transcriptions into French","default":false,"title":"Translate To French"},"description":"Flag to translate transcriptions into French"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_Models-Streaming_Transcription_V2"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/FrenchTranscriptionResponse"},{"$ref":"#/components/schemas/TranscriptionSegment"}],"title":"Response Models-Streaming Transcription V2"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"x-codeSamples":[{"lang":"Python","label":"Python","source":"import requests\n\nurl = \"https://api.djelia.cloud/api/v2/models/transcribe/stream\"\nheaders = {\n    \"x-api-key\": \"YOUR_API_KEY\",\n}\nfiles = {\n    \"file\": open(\"audio_file.wav\", \"rb\")\n}\nparams = {\n    \"translate_to_french\": True\n}\n\nresponse = requests.post(url, headers=headers, files=files, params=params, stream=True)\nfor line in response.iter_lines():\n    if line:\n        print(\"Streamed Response:\", line.decode('utf-8'))"},{"lang":"cURL","label":"cURL","source":"curl -X POST \"https://api.djelia.cloud/api/v2/models/transcribe/stream\" \\\n-H \"x-api-key: YOUR_API_KEY\" \\\n-F \"file=@audio_file.wav\" \\\n-G --data-urlencode \"translate_to_french=true\""},{"lang":"Dart","label":"Dart","source":"import 'dart:convert';\nimport 'dart:io';\n\nvoid main() async {\n  final file = File('audio_file.wav');\n  final uri = Uri.parse('https://api.djelia.cloud/api/v2/models/transcribe/stream');\n  final request = HttpClientRequest();\n\n  final requestBody = await file.readAsBytes();\n  \n  final headers = {\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"Content-Type\": \"multipart/form-data\"\n  };\n\n  final queryParams = {'translate_to_french': 'true'};\n  final fullUri = uri.replace(queryParameters: queryParams);\n\n  final response = await HttpClient().postUrl(fullUri)\n    ..headers.addAll(headers)\n    ..add(requestBody);\n\n  final responseStream = await response.close();\n\n  await for (final data in responseStream.transform(utf8.decoder)) {\n    print('Streamed Response: $data');\n  }\n}"}]}},"/v2/models/transcribe":{"post":{"tags":["Models","Transcription"],"summary":"Transcription V2","description":"Perform audio transcription in a synchronous manner, using the V2 model which perform better when audio are short and contains french words.\n\n**What does this endpoint do?**\n- Transcribes the audio file content into text using Bambara models.\n- Optionally translates the transcribed text into French if `translate_to_french` is set to `True`.\n\n**Behavior Notes:**\n- If `translate_to_french=False` (default):\n    - The response contains a list of transcribed segment in Bambara.\n- If `translate_to_french=True`:\n    - The response contains the full transcription translated into French.\n\n**Headers:**\n- `x-api-key`: Your API key for authentication.\n- `Content-Type`: Must be set to `multipart/form-data`.\n\n**Parameters:**\n- `file` (UploadFile): The audio file to transcribe.\n- `translate_to_french` (bool): Whether to translate the transcription into French. Defaults to `False`.\n\n**Example Request Body:**\n```text\nfile: <binary file>\ntranslate_to_french: true\n```\n\n**Example Response (translate_to_french=False):**\n```json\n[\n    {\n        \"text\": \"Aw ni ce i ka kene wa.\",\n        \"start\": 0.0,\n        \"end\": 1.0,\n    }\n]\n```\n\n**Example Response (translate_to_french=True):**\n```json\n{\n    \"text\": \"Bonjour, comment ça va?\"\n}\n```\n\n**Caution:**\n- Translation introduces additional latency as it processes the full transcription for context.\n\nReturns:\n    FrenchTranscriptionResponse: A dictionary containing the transcribed (and optionally translated) text.","operationId":"Models-Transcription V2","security":[{"API Key":[]}],"parameters":[{"name":"translate_to_french","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Flag to translate transcriptions into French","default":false,"title":"Translate To French"},"description":"Flag to translate transcriptions into French"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_Models-Transcription_V2"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/FrenchTranscriptionResponse"},{"type":"array","items":{"$ref":"#/components/schemas/TranscriptionSegment"}}],"title":"Response Models-Transcription V2"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"x-codeSamples":[{"lang":"Python","label":"Python","source":"import requests\n\nurl = \"https://api.djelia.cloud/api/v2/models/transcribe\"\nheaders = {\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"Content-Type\": \"multipart/form-data\"\n}\nfiles = {\n    \"file\": open(\"audio_file.wav\", \"rb\")\n}\nparams = {\n    \"translate_to_french\": True\n}\n\nresponse = requests.post(url, headers=headers, files=files, params=params)\nif response.status_code == 200:\n    print(\"Transcription:\", response.json())\nelse:\n    print(\"Failed to transcribe:\", response.status_code, response.text)"},{"lang":"cURL","label":"cURL","source":"curl -X POST \"https://api.djelia.cloud/api/v2/models/transcribe\" \\\n-H \"x-api-key: YOUR_API_KEY\" \\\n-F \"file=@audio_file.wav\" \\\n-G --data-urlencode \"translate_to_french=true\""},{"lang":"Dart","label":"Dart","source":"import 'dart:convert';\nimport 'dart:io';\nimport 'package:http/http.dart' as http;\n\nvoid main() async {\n  final url = Uri.parse('https://api.djelia.cloud/api/v2/models/transcribe');\n  final headers = {\n    \"x-api-key\": \"YOUR_API_KEY\",\n  };\n  final queryParams = {'translate_to_french': 'true'};\n  final file = http.MultipartFile.fromBytes(\n    'file',\n    File('audio_file.wav').readAsBytesSync(),\n    filename: 'audio_file.wav',\n  );\n\n  final request = http.MultipartRequest('POST', url..replace(queryParameters: queryParams))\n    ..headers.addAll(headers)\n    ..files.add(file);\n\n  final response = await request.send();\n\n  if (response.statusCode == 200) {\n    final body = await response.stream.bytesToString();\n    print('Transcription: ${jsonDecode(body)}');\n  } else {\n    print('Failed to transcribe: ${response.statusCode}');\n  }\n}"}]}},"/v2/models/tts/stream":{"post":{"tags":["Models","Text-to-Speech"],"summary":"Streaming Text-To-Speech V2","description":"Stream audio synthesis from text using the V2 TTS model.\n\n**What does this endpoint do?**\n- Converts text to speech in real-time using our advanced TTS model\n- Streams the audio back in chunks for faster playback start\n- Allows customization of voice characteristics through description\n- Supported speaker names: \"Moussa\", \"Sekou\", \"Seydou\"\n\n**Behavior Notes:**\n- Audio is streamed in chunks of specified duration\n- First chunk may take longer as the model initializes\n- Output format is controlled by the `format` field\n\n**Headers:**\n- `x-api-key`: Your API key for authentication\n\n**Parameters:**\n- `text` (str): The text to convert to speech\n- `description` (str): Description of desired voice characteristics\n- `chunk_size` (float): Size of audio chunks in seconds (default: 1.0)\n- `format` (str): Output format — `mp3` (default), `wav`, `wav_8k`, `ulaw_8k`\n\n**Example Request Body:**\n```json\n{\n    \"text\": \"Aw ni ce, i ka kene wa?\",\n    \"description\": \"Moussa speaks with a very clear voice and a friendly tone\",\n    \"chunk_size\": 1.0,\n    \"format\": \"mp3\"\n}\n```\n\nReturns:\n    StreamingResponse: A streaming response containing the encoded audio","operationId":"Models-Streaming Text-to-Speech V2","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TTSRequestV2Streaming"}}},"required":true},"responses":{"200":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"API Key":[]}],"x-codeSamples":[{"lang":"Python","label":"Python","source":"import requests\n\nurl = \"https://api.djelia.cloud/api/v2/models/tts/stream\"\nheaders = {\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"Content-Type\": \"application/json\"\n}\npayload = {\n    \"text\": \"Aw ni ce, i ka kene wa?\",\n    # Supported speaker names: \"Moussa\", \"Sekou\", \"Seydou\"\n    \"description\": \"Moussa speaks with a very clear voice and a friendly tone\",\n    \"chunk_size\": 0.5\n}\n\n# Stream the audio and save chunks\nwith open(\"output.wav\", \"wb\") as f:\n    response = requests.post(url, headers=headers, json=payload, stream=True)\n    if response.status_code == 200:\n        for chunk in response.iter_content(chunk_size=8192):\n            if chunk:\n                f.write(chunk)\n        print(\"Audio saved as output.wav\")\n    else:\n        print(\"Failed to generate audio:\", response.status_code, response.text)"},{"lang":"cURL","label":"cURL","source":"# Supported speaker names: \"Moussa\", \"Sekou\", \"Seydou\"\ncurl -X POST \"https://api.djelia.cloud/api/v2/models/tts/stream\" \\\n-H \"x-api-key: YOUR_API_KEY\" \\\n-H \"Content-Type: application/json\" \\\n-d '{\n    \"text\": \"Aw ni ce, i ka kene wa?\",\n    \"description\": \"Moussa speaks with a very clear voice and a friendly tone\",\n    \"chunk_size\": 0.5\n}' --output output.wav"},{"lang":"Dart","label":"Dart","source":"import 'dart:convert';\nimport 'dart:io';\nimport 'package:http/http.dart' as http;\n\nvoid main() async {\n  final url = Uri.parse('https://api.djelia.cloud/api/v2/models/tts/stream');\n  final headers = {\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"Content-Type\": \"application/json\"\n  };\n  // Supported speaker names: \"Moussa\", \"Sekou\", \"Seydou\"\n  final payload = {\n    \"text\": \"Aw ni ce, i ka kene wa?\",\n    \"description\": \"Moussa speaks with a very clear voice and a friendly tone\",\n    \"chunk_size\": 0.5\n  };\n\n  final client = http.Client();\n  final request = http.Request('POST', url)\n    ..headers.addAll(headers)\n    ..body = jsonEncode(payload);\n\n  final response = await client.send(request);\n\n  if (response.statusCode == 200) {\n    final file = File('output.wav');\n    final sink = file.openWrite();\n    \n    await for (final chunk in response.stream) {\n      sink.add(chunk);\n    }\n    \n    await sink.close();\n    print(\"Audio saved as output.wav\");\n  } else {\n    print(\"Failed to generate audio: ${response.statusCode}\");\n  }\n  \n  client.close();\n}"}]}},"/v2/models/tts":{"post":{"tags":["Models","Text-to-Speech"],"summary":"Text-To-Speech V2","description":"Convert text to speech using the V2 TTS model.\n\n**What does this endpoint do?**\n- Converts the provided text to natural-sounding speech\n- Allows customization of voice characteristics through description\n- Returns complete audio file in a single response\n- Supported speaker names: \"Moussa\", \"Sekou\", \"Seydou\"\n\n**Behavior Notes:**\n- Returns complete audio file (non-streaming)\n- May have higher latency than streaming version for long texts\n\n**Headers:**\n- `x-api-key`: Your API key for authentication\n\n**Parameters:**\n- `text` (str): The text to convert to speech\n- `description` (str): Description of desired voice characteristics\n- `format` (str): Output format — `mp3` (default), `wav`, `wav_8k`, `ulaw_8k`\n\n**Example Request Body:**\n```json\n{\n    \"text\": \"Aw ni ce, i ka kene wa?\",\n    \"description\": \"Moussa speaks with a very clear voice and a friendly tone\",\n    \"format\": \"mp3\"\n}\n```\n\nReturns:\n    Response: Complete audio file in the requested format","operationId":"Models-Text-to-Speech V2","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TTSRequestV2"}}},"required":true},"responses":{"200":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"API Key":[]}],"x-codeSamples":[{"lang":"Python","label":"Python","source":"import requests\n\nurl = \"https://api.djelia.cloud/api/v2/models/tts\"\nheaders = {\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"Content-Type\": \"application/json\"\n}\n# Supported speaker names: \"Moussa\", \"Sekou\", \"Seydou\"\npayload = {\n    \"text\": \"Aw ni ce, i ka kene wa?\",\n    \"description\": \"Seydou speaks with a warm and natural voice\"\n}\n\nresponse = requests.post(url, headers=headers, json=payload)\nif response.status_code == 200:\n    with open(\"output.wav\", \"wb\") as f:\n        f.write(response.content)\n    print(\"Audio saved as output.wav\")\nelse:\n    print(\"Failed to generate audio:\", response.status_code, response.text)"},{"lang":"cURL","label":"cURL","source":"# Supported speaker names: \"Moussa\", \"Sekou\", \"Seydou\"\ncurl -X POST \"https://api.djelia.cloud/api/v2/models/tts\" \\\n-H \"x-api-key: YOUR_API_KEY\" \\\n-H \"Content-Type: application/json\" \\\n-d '{\n    \"text\": \"Aw ni ce, i ka kene wa?\",\n    \"description\": \"Sekou speaks with a warm and natural voice\"\n}' --output output.wav"},{"lang":"Dart","label":"Dart","source":"import 'dart:convert';\nimport 'dart:io';\nimport 'package:http/http.dart' as http;\n\nvoid main() async {\n  final url = Uri.parse('https://api.djelia.cloud/api/v2/models/tts');\n  final headers = {\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"Content-Type\": \"application/json\"\n  };\n  // Supported speaker names: \"Moussa\", \"Sekou\", \"Seydou\"\n  final payload = {\n    \"text\": \"Aw ni ce, i ka kene wa?\",\n    \"description\": \"Sekou speaks with a warm and natural voice\"\n  };\n\n  final response = await http.post(\n    url,\n    headers: headers,\n    body: jsonEncode(payload),\n  );\n\n  if (response.statusCode == 200) {\n    final file = File('output.wav');\n    await file.writeAsBytes(response.bodyBytes);\n    print(\"Audio saved as output.wav\");\n  } else {\n    print(\"Failed to generate audio: ${response.statusCode}\");\n  }\n}"}]}}},"components":{"schemas":{"Body_Models-Streaming_Transcription":{"properties":{"file":{"type":"string","format":"binary","title":"File","description":"The uploaded audio file"}},"type":"object","required":["file"],"title":"Body_Models-Streaming Transcription"},"Body_Models-Streaming_Transcription_V2":{"properties":{"file":{"type":"string","format":"binary","title":"File","description":"The uploaded audio file"}},"type":"object","required":["file"],"title":"Body_Models-Streaming Transcription V2"},"Body_Models-Transcription":{"properties":{"file":{"type":"string","format":"binary","title":"File","description":"The uploaded audio file"}},"type":"object","required":["file"],"title":"Body_Models-Transcription"},"Body_Models-Transcription_V2":{"properties":{"file":{"type":"string","format":"binary","title":"File","description":"The uploaded audio file"}},"type":"object","required":["file"],"title":"Body_Models-Transcription V2"},"Body_OpenAI_Compatibility-Transcribe_and_translate_audio":{"properties":{"file":{"type":"string","format":"binary","title":"File","description":"The audio file to translate."},"model":{"type":"string","title":"Model","description":"Model id.","default":"sunjata-1"},"language":{"anyOf":[{"$ref":"#/components/schemas/TranslationLanguage"},{"type":"null"}]},"response_format":{"$ref":"#/components/schemas/TranscriptionFormat","default":"json"},"prompt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prompt"},"temperature":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Temperature"}},"type":"object","required":["file"],"title":"Body_OpenAI Compatibility-Transcribe and translate audio"},"Body_OpenAI_Compatibility-Transcribe_audio":{"properties":{"file":{"type":"string","format":"binary","title":"File","description":"The audio file to transcribe."},"model":{"type":"string","title":"Model","description":"Model id.","default":"sunjata-1"},"language":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Language"},"response_format":{"$ref":"#/components/schemas/TranscriptionFormat","default":"json"},"stream":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Stream","default":false},"prompt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prompt"},"temperature":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Temperature"},"timestamp_granularities":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Timestamp Granularities"}},"type":"object","required":["file"],"title":"Body_OpenAI Compatibility-Transcribe audio"},"ChatCompletion":{"properties":{"id":{"type":"string","title":"Id"},"object":{"type":"string","const":"chat.completion","title":"Object","default":"chat.completion"},"created":{"type":"integer","title":"Created"},"model":{"type":"string","title":"Model"},"choices":{"items":{"$ref":"#/components/schemas/ChatCompletionChoice"},"type":"array","title":"Choices"},"usage":{"$ref":"#/components/schemas/ChatCompletionUsage"}},"type":"object","required":["model","choices","usage"],"title":"ChatCompletion"},"ChatCompletionChoice":{"properties":{"index":{"type":"integer","title":"Index","default":0},"message":{"$ref":"#/components/schemas/ChatCompletionMessage"},"finish_reason":{"type":"string","const":"stop","title":"Finish Reason","default":"stop"},"logprobs":{"type":"null","title":"Logprobs"}},"type":"object","required":["message"],"title":"ChatCompletionChoice"},"ChatCompletionMessage":{"properties":{"role":{"type":"string","const":"assistant","title":"Role","default":"assistant"},"content":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content"}},"type":"object","title":"ChatCompletionMessage"},"ChatCompletionRequest":{"properties":{"model":{"type":"string","title":"Model","default":"banjugu-1"},"messages":{"items":{"$ref":"#/components/schemas/ChatMessage"},"type":"array","title":"Messages"},"stream":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Stream","default":false},"djelia":{"$ref":"#/components/schemas/DjeliaTranslationOptions","description":"The language pair. Required: translation needs one."},"temperature":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Temperature"},"top_p":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Top P"},"n":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"N"},"max_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Tokens"},"max_completion_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Completion Tokens"},"stop":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Stop"},"presence_penalty":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Presence Penalty"},"frequency_penalty":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Frequency Penalty"},"logit_bias":{"anyOf":[{"additionalProperties":{"type":"number"},"type":"object"},{"type":"null"}],"title":"Logit Bias"},"logprobs":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Logprobs"},"top_logprobs":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Top Logprobs"},"seed":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Seed"},"user":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User"},"response_format":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Response Format"},"tools":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Tools"},"tool_choice":{"anyOf":[{"type":"string"},{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Tool Choice"},"stream_options":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Stream Options"},"metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Metadata"},"store":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Store"},"service_tier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Service Tier"}},"type":"object","required":["messages","djelia"],"title":"ChatCompletionRequest","description":"Body of `POST /openai/v1/chat/completions`."},"ChatCompletionUsage":{"properties":{"prompt_tokens":{"type":"integer","title":"Prompt Tokens"},"completion_tokens":{"type":"integer","title":"Completion Tokens"},"total_tokens":{"type":"integer","title":"Total Tokens"}},"type":"object","required":["prompt_tokens","completion_tokens","total_tokens"],"title":"ChatCompletionUsage","description":"Token accounting.\n\nDjelia meters translation per character, not per token, so these counts are\ncharacter counts. Documented as such in docs/openai-compat.md."},"ChatMessage":{"properties":{"role":{"type":"string","title":"Role"},"content":{"anyOf":[{"type":"string"},{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Content"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"}},"type":"object","required":["role"],"title":"ChatMessage"},"DjeliaSpeechOptions":{"properties":{"description":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Description","description":"Free-text description of the desired voice. Overrides `voice` entirely. Djelia's TTS v2 is prompt-steerable, so this reaches capability the OpenAI `voice` enum cannot express.","examples":["Moussa speaks slowly with a calm, reassuring tone"]},"chunk_size":{"type":"number","maximum":2.0,"minimum":0.1,"title":"Chunk Size","description":"Audio chunk size in seconds when streaming.","default":1.0},"temperature":{"anyOf":[{"type":"number","maximum":2.0,"minimum":0.0},{"type":"null"}],"title":"Temperature","description":"Sampling temperature for `jifili-1`."},"top_p":{"anyOf":[{"type":"number","maximum":1.0,"exclusiveMinimum":0.0},{"type":"null"}],"title":"Top P","description":"Nucleus sampling threshold for `jifili-1`."},"repetition_penalty":{"anyOf":[{"type":"number","maximum":2.0,"exclusiveMinimum":0.0},{"type":"null"}],"title":"Repetition Penalty","description":"Penalty on repeated audio tokens for `jifili-1`."},"speaker":{"type":"integer","enum":[0,1,2,3,4],"title":"Speaker","description":"Speaker id for `djelia-tts-v1` only, which selects a voice by id rather than by name or description. Ignored by `djelia-tts-v2`, which uses `voice` or `djelia.description`.","default":1}},"type":"object","title":"DjeliaSpeechOptions","description":"Djelia-specific speech options, supplied via `extra_body={\"djelia\": {...}}`.\n\nThe defaults live here rather than in the handler, so the documented behaviour and\nthe OpenAPI schema are the behaviour."},"DjeliaTranslationOptions":{"properties":{"source_language":{"$ref":"#/components/schemas/TranslationLanguage","description":"Language of the text to translate.","examples":["fra_Latn"]},"target_language":{"$ref":"#/components/schemas/TranslationLanguage","description":"Language to translate into.","examples":["bam_Latn"]}},"type":"object","required":["source_language","target_language"],"title":"DjeliaTranslationOptions","description":"The language pair, supplied via `extra_body={\"djelia\": {...}}`.\n\nA chat request has nowhere to carry this, so it rides in the Djelia namespace."},"FrenchTranscriptionResponse":{"properties":{"text":{"type":"string","title":"Text","description":"The transcribed text"}},"type":"object","required":["text"],"title":"FrenchTranscriptionResponse"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ModelList":{"properties":{"object":{"type":"string","const":"list","title":"Object","default":"list"},"data":{"items":{"$ref":"#/components/schemas/ModelObject"},"type":"array","title":"Data"}},"type":"object","required":["data"],"title":"ModelList"},"ModelObject":{"properties":{"id":{"type":"string","title":"Id"},"object":{"type":"string","const":"model","title":"Object","default":"model"},"created":{"type":"integer","title":"Created","default":1735689600},"owned_by":{"type":"string","title":"Owned By","default":"djelia"}},"type":"object","required":["id"],"title":"ModelObject"},"OpenAIError":{"properties":{"error":{"$ref":"#/components/schemas/OpenAIErrorBody"}},"type":"object","required":["error"],"title":"OpenAIError","description":"Every failure on this surface, whatever the status."},"OpenAIErrorBody":{"properties":{"message":{"type":"string","title":"Message","description":"Human-readable description."},"type":{"type":"string","title":"Type","description":"Error class the SDKs branch on to pick an exception.","examples":["invalid_request_error"]},"param":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Param","description":"The offending field, when the error is about one."},"code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code","description":"Machine-readable code, when there is one."}},"type":"object","required":["message","type"],"title":"OpenAIErrorBody","description":"The body of an error, as the OpenAI SDKs parse it."},"OpenAIVoice":{"type":"string","enum":["alloy","echo","fable","onyx","nova","shimmer","ash","ballad","coral","sage","verse"],"title":"OpenAIVoice","description":"OpenAI's voice names, accepted so an existing integration works when repointed."},"SpeechFormat":{"type":"string","enum":["pcm","wav","mp3","opus","ulaw","alaw","l16_8000","l16_16000","fmp4","wav_8k","ulaw_8k","aac","flac"],"title":"SpeechFormat","description":"`response_format` on the speech endpoint, and the media type each name is served as.\n\nThe member value stays the plain name a caller sends, so a body parses straight into a\nmember; the media type rides along, which keeps the Content-Type off every call site."},"SpeechRequest":{"properties":{"model":{"type":"string","title":"Model","description":"Model id.","default":"jifili-1"},"input":{"type":"string","maxLength":1000,"title":"Input","description":"The text to synthesise.","examples":["Aw ni ce, i ka kene wa?"]},"voice":{"anyOf":[{"$ref":"#/components/schemas/Voice"},{"$ref":"#/components/schemas/OpenAIVoice"}],"title":"Voice","description":"Voice name. Djelia voices are `moussa`, `sekou` and `seydou`; the OpenAI voice names are accepted as aliases.","default":"moussa"},"response_format":{"$ref":"#/components/schemas/SpeechFormat","default":"mp3"},"stream_format":{"anyOf":[{"type":"string","enum":["audio","sse"]},{"type":"null"}],"title":"Stream Format","description":"`audio` (default) streams raw encoded bytes; `sse` streams base64 audio in `speech.audio.delta` events.","default":"audio"},"djelia":{"$ref":"#/components/schemas/DjeliaSpeechOptions","description":"Djelia-specific options with no OpenAI equivalent."},"speed":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Speed"},"instructions":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instructions"}},"type":"object","required":["input"],"title":"SpeechRequest","description":"Body of `POST /openai/v1/audio/speech`."},"SupportedLanguageSchema":{"properties":{"code":{"type":"string","title":"Code","description":"The language code."},"name":{"type":"string","title":"Name","description":"The name of the language."}},"type":"object","required":["code","name"],"title":"SupportedLanguageSchema"},"TTSRequest":{"properties":{"text":{"type":"string","title":"Text","description":"The bambara text to synthesize"},"speaker":{"anyOf":[{"type":"integer","enum":[0,1,2,3,4]},{"type":"null"}],"title":"Speaker","description":"The speaker ID to use","default":1}},"type":"object","required":["text"],"title":"TTSRequest"},"TTSRequestV2":{"properties":{"text":{"type":"string","maxLength":1000,"title":"Text","description":"The text to convert to speech","examples":["Aw ni ce, i ka kene wa?"]},"description":{"type":"string","title":"Description","description":"Description of the desired voice style/characteristics","examples":["A warm and friendly female voice speaking naturally"]},"format":{"type":"string","enum":["mp3","wav","wav_8k","ulaw_8k"],"title":"Format","description":"Output audio format. 'mp3' (default), 'wav', 'wav_8k' (PCM 8 kHz), 'ulaw_8k' (µ-law 8 kHz)","default":"mp3"}},"type":"object","required":["text","description"],"title":"TTSRequestV2"},"TTSRequestV2Streaming":{"properties":{"text":{"type":"string","maxLength":1000,"title":"Text","description":"The text to convert to speech","examples":["Aw ni ce, i ka kene wa?"]},"description":{"type":"string","title":"Description","description":"Description of the desired voice style/characteristics","examples":["A warm and friendly female voice speaking naturally"]},"format":{"type":"string","enum":["mp3","wav","wav_8k","ulaw_8k"],"title":"Format","description":"Output audio format. 'mp3' (default), 'wav', 'wav_8k' (PCM 8 kHz), 'ulaw_8k' (µ-law 8 kHz)","default":"mp3"},"chunk_size":{"type":"number","maximum":2.0,"minimum":0.1,"title":"Chunk Size","description":"The size of the audio chunks to use","default":1}},"type":"object","required":["text","description"],"title":"TTSRequestV2Streaming"},"TranscriptionFormat":{"type":"string","enum":["json","text","verbose_json","srt","vtt"],"title":"TranscriptionFormat","description":"`response_format` on the transcription endpoints."},"TranscriptionResponse":{"properties":{"text":{"type":"string","title":"Text"}},"type":"object","required":["text"],"title":"TranscriptionResponse","description":"`response_format=\"json\"`, the OpenAI default."},"TranscriptionSegment":{"properties":{"text":{"type":"string","title":"Text","description":"The transcribed text of the segment"},"start":{"type":"number","title":"Start","description":"The start of the segment"},"end":{"type":"number","title":"End","description":"The end of the segment"}},"type":"object","required":["text","start","end"],"title":"TranscriptionSegment"},"TranscriptionVerboseResponse":{"properties":{"task":{"type":"string","enum":["transcribe","translate"],"title":"Task","default":"transcribe"},"language":{"type":"string","title":"Language"},"duration":{"type":"number","title":"Duration"},"text":{"type":"string","title":"Text"},"segments":{"items":{"$ref":"#/components/schemas/TranscriptionVerboseSegment"},"type":"array","title":"Segments"}},"type":"object","required":["language","duration","text","segments"],"title":"TranscriptionVerboseResponse","description":"`response_format=\"verbose_json\"`."},"TranscriptionVerboseSegment":{"properties":{"id":{"type":"integer","title":"Id"},"seek":{"type":"integer","title":"Seek","default":0},"start":{"type":"number","title":"Start"},"end":{"type":"number","title":"End"},"text":{"type":"string","title":"Text"},"tokens":{"items":{"type":"integer"},"type":"array","title":"Tokens","default":[]},"temperature":{"type":"number","title":"Temperature","default":0.0},"avg_logprob":{"type":"number","title":"Avg Logprob","default":0.0},"compression_ratio":{"type":"number","title":"Compression Ratio","default":0.0},"no_speech_prob":{"type":"number","title":"No Speech Prob","default":0.0}},"type":"object","required":["id","start","end","text"],"title":"TranscriptionVerboseSegment"},"TranslationLanguage":{"type":"string","enum":["fra_Latn","eng_Latn","bam_Latn"],"title":"TranslationLanguage"},"TranslationRequest":{"properties":{"source":{"$ref":"#/components/schemas/TranslationLanguage","description":"The source language code (eg: eng_Latn)"},"target":{"$ref":"#/components/schemas/TranslationLanguage","description":"The target language code (eg: bm_Latn)"},"text":{"type":"string","title":"Text","description":"The text to translate from source language to target language"}},"type":"object","required":["source","target","text"],"title":"TranslationRequest"},"TranslationResponse":{"properties":{"text":{"type":"string","title":"Text","description":"The translated text"}},"type":"object","required":["text"],"title":"TranslationResponse"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"Voice":{"type":"string","enum":["moussa","sekou","seydou"],"title":"Voice","description":"Djelia's named voices."}},"securitySchemes":{"Bearer token":{"type":"http","description":"`Authorization: Bearer <your Djelia API key>`, which is what the OpenAI SDKs send without configuration.","scheme":"bearer"},"API Key":{"type":"apiKey","description":"Your Djelia API key in the `x-api-key` header. On the OpenAI-compatible surface, `Authorization: Bearer <key>` works too.","in":"header","name":"x-api-key"}}},"tags":[{"name":"OpenAI Compatibility","description":"### The primary way to call Djelia\nThese endpoints follow the OpenAI convention, so any OpenAI-compatible client reaches Djelia by changing only its base URL, key and model name:\n\n```python\nfrom openai import OpenAI\n\nclient = OpenAI(\n    api_key=\"YOUR_DJELIA_API_KEY\",\n    base_url=\"https://api.djelia.cloud/openai/v1\",\n)\n```\n\nCapabilities with no slot in the OpenAI shape — prompt-steerable TTS voices, telephony audio formats — ride in `extra_body={\"djelia\": {...}}`. Parameters we cannot honour are accepted and ignored rather than rejected; each one is listed in the compatibility reference."},{"name":"Models","description":"### Supported Models\nDjelia provides access to powerful linguistic models tailored for African languages. Below are the models currently available:\n\n- **Transcription**: Convert Bambara audio into text with real-time streaming capabilities.\n- **Translation**: Translate text seamlessly between Bambara, French, and English.\n- **Text-to-Speech (Experimental)**: Transform Bambara text into natural, human-like speech.\n\n"}]}