API migration guide
On September 20, 2026, the native Djelia API and the djelia-*-v* model names were retired. The only public API is now the OpenAI-compatible API at https://api.djelia.cloud/openai/v1, with the models sunjata-1, jifili-1 and banjugu-1. You can call it with the official OpenAI SDKs.
What changed
- The native endpoints
/v1/models/*and/v2/models/*, and their/api/v1and/api/v2twins, were retired on September 20, 2026. - The model ids
djelia-asr-v1,djelia-asr-v2,djelia-asr-v3,djelia-tts-v1,djelia-tts-v2,djelia-tts-v3anddjelia-translate-v1were retired on the same date. See Model names. jifili-1ignoresdjelia.speaker,djelia.descriptionanddjelia.chunk_size, and returns 400 for the formatswav_8k,ulaw_8k,aacandflac.- API requests go to
https://api.djelia.cloud. The old hosthttps://djelia.cloudstill answers for now, withDeprecationand successorLinkheaders.
| If you use | Do this |
|---|---|
| Djelia Python SDK | Move to the official OpenAI Python SDK |
| Djelia JavaScript SDK | Move to the official OpenAI JavaScript SDK |
| A native curl request | Move it to https://api.djelia.cloud/openai/v1 |
A djelia-*-v* model | Replace it using Model names |
https://djelia.cloud | Change API requests to https://api.djelia.cloud |
What an old call gets now
A request that names a retired model returns HTTP 410 with code: "model_retired":
{
"error": {
"message": "The model `djelia-asr-v2` was retired on 2026-09-20. Use `sunjata-1` instead. Migration guide: https://docs.djelia.cloud/migration/",
"type": "invalid_request_error",
"param": "model",
"code": "model_retired"
}
}
A request to a native endpoint returns HTTP 410 with code: "endpoint_retired", whatever the method:
{
"error": {
"message": "The native endpoint `POST /v1/models/translate` was retired on 2026-09-20. Use the OpenAI-compatible API at https://api.djelia.cloud/openai/v1 with the model `banjugu-1`. Migration guide: https://docs.djelia.cloud/migration/",
"type": "invalid_request_error",
"param": null,
"code": "endpoint_retired"
}
}
Python
Set up the client
Before, with the Djelia SDK:
from djelia import Djelia
from djelia.models import Language, Versions
djelia = Djelia()
After, with the OpenAI SDK:
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["DJELIA_API_KEY"],
base_url="https://api.djelia.cloud/openai/v1",
)
Install the openai package with pip install openai. The Djelia Python SDK calls the retired native endpoints, so it no longer works.
Speech to text
Streaming
Before, with the Djelia SDK:
for segment in djelia.audio.transcriptions.create(
file="audio.mp3",
model=Versions.v2,
stream=True,
):
print(segment.start, segment.end, segment.text)
After, with the OpenAI SDK:
stream = client.audio.transcriptions.create(
file=open("audio.mp3", "rb"),
model="sunjata-1",
stream=True,
)
for event in stream:
if event.type == "transcript.text.delta":
print(event.delta)
- When using the new API, be sure to specify
model="sunjata-1"and make requests to the/audio/transcriptionsendpoint. - Previously, native streams provided objects of the form
{text, start, end}. In contrast, the OpenAI-compatible API streams responses via SSE events, specificallytranscript.text.segment,transcript.text.delta, andtranscript.text.done, followed by a[DONE]sentinel to indicate completion. - For speech translation, use
/audio/translationsandlanguage=fra_Latninstead oftranslate_to_french=true.
Without streaming
Before, with the Djelia SDK:
print(
" ".join(
segment.text
for segment in djelia.audio.transcriptions.create(
file="audio.mp3",
model=Versions.v2,
)
)
)
After, with the OpenAI SDK:
print(
client.audio.transcriptions.create(
file=open("audio.mp3", "rb"),
model="sunjata-1",
).text
)
- By default, non-streaming responses return an array of segments. To access timestamps, set
response_format=verbose_jsonand use the.segmentsfield; if you only need text, the defaultjsonformat lets you read from.text. temperaturetakes effect onsunjata-1.
Text to speech
Streaming
Before, with the Djelia SDK:
chunks = djelia.audio.speech.create(
input="Aw ni ce",
description="Moussa speaks clearly",
model=Versions.v2,
stream=True,
output_file="speech.mp3",
)
for chunk in chunks:
print(len(chunk))
After, with the OpenAI SDK:
with client.audio.speech.with_streaming_response.create(
model="jifili-1",
input="Aw ni ce",
voice="moussa",
response_format="mp3",
stream_format="audio",
) as response:
with open("speech.mp3", "wb") as audio:
for chunk in response.iter_bytes():
audio.write(chunk)
- Update your code by renaming the
textparameter toinput, replacing the numericspeakerordescriptionfields withvoice, and changingformattoresponse_format. - To receive raw audio chunks, simply add the argument
stream_format="audio".
Without streaming
Before, with the Djelia SDK:
djelia.audio.speech.create(
input="Aw ni ce",
description="Moussa speaks clearly",
model=Versions.v2,
output_file="speech.mp3",
)
After, with the OpenAI SDK:
client.audio.speech.create(
model="jifili-1",
input="Aw ni ce",
voice="moussa",
response_format="mp3",
).write_to_file("speech.mp3")
- Update your usage by renaming the
textparameter toinput, usingvoiceinstead of a numericspeakerordescription, and changingformattoresponse_format. - The
jifili-1model supports the followingresponse_formatoptions:mp3,wav,pcm,opus,ulaw,alaw,l16_8000,l16_16000, andfmp4. Any other value returns a 400 error withparam: "response_format".
Translation
Before, with the Djelia SDK:
print(
djelia.translations.create(
text="Bonjour",
source=Language.FRENCH,
target=Language.BAMBARA,
model=Versions.v1,
).text
)
After, with the OpenAI SDK:
print(
client.chat.completions.create(
model="banjugu-1",
messages=[{"role": "user", "content": "Bonjour"}],
extra_body={
"djelia": {
"source_language": "fra_Latn",
"target_language": "bam_Latn",
}
},
).choices[0].message.content
)
- Set the
source_languageandtarget_languagefields underdjeliain theextra_bodyparameter. Use codes such asbam_Latn,fra_Latn, andeng_Latn, making sure that the source and target languages are different. - Retrieve the translated text from
choices[0].message.contentin the response instead of using the top-leveltextfield.
JavaScript
Set up the client
Before, with the Djelia SDK:
const fs = require("node:fs");
const {
Djelia,
Language,
TranslationRequest,
TTSRequestV2,
Versions,
} = require("djelia");
const djelia = new Djelia(process.env.DJELIA_API_KEY);
After, with the OpenAI SDK:
import fs from "node:fs";
import OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.DJELIA_API_KEY,
baseURL: "https://api.djelia.cloud/openai/v1",
});
Install the OpenAI SDK with npm install openai (Node 18 or later). The Djelia JavaScript SDK is no longer maintained and calls the retired native endpoints.
Speech to text
Streaming
Before, with the Djelia SDK:
const stream = await djelia.transcription.transcribe(
"audio.mp3",
false,
true,
Versions.v2,
);
for await (const segment of stream) {
console.log(segment.start, segment.end, segment.text);
}
After, with the OpenAI SDK:
const stream = await client.audio.transcriptions.create({
file: fs.createReadStream("audio.mp3"),
model: "sunjata-1",
stream: true,
});
for await (const event of stream) {
if (event.type === "transcript.text.delta") console.log(event.delta);
}
- When using the OpenAI SDK, specify
model: "sunjata-1"and call the/audio/transcriptionsendpoint for transcriptions. - In the original Djelia SDK, streaming responses yield objects with
{text, start, end}. With the OpenAI SDK, streaming returns a sequence of Server-Sent Events (SSE):transcript.text.segment,transcript.text.delta, andtranscript.text.done, concluding with a[DONE]message. - To perform speech translation, use the
/audio/translationsendpoint and setlanguage: "fra_Latn"(for French), replacing the previoustranslateToFrenchmethod.
Without streaming
Before, with the Djelia SDK:
const segments = await djelia.transcription.transcribe(
"audio.mp3",
false,
false,
Versions.v2,
);
console.log(segments.map(segment => segment.text).join(" "));
After, with the OpenAI SDK:
const transcript = await client.audio.transcriptions.create({
file: fs.createReadStream("audio.mp3"),
model: "sunjata-1",
});
console.log(transcript.text);
- By default, non-streaming responses return an array of segments. If you need detailed segment timestamps, set
response_format: "verbose_json"and access the.segmentsfield. For simple transcripts, you can use the defaultjsonformat and read.text. temperaturetakes effect onsunjata-1.
Text to speech
Streaming
Before, with the Djelia SDK:
const stream = await djelia.tts.textToSpeech(
new TTSRequestV2("Aw ni ce", "Moussa speaks clearly"),
"speech.mp3",
true,
Versions.v2,
);
for await (const chunk of stream) {
console.log(chunk.length);
}
After, with the OpenAI SDK:
const speech = await client.audio.speech.create({
model: "jifili-1",
input: "Aw ni ce",
voice: "moussa",
response_format: "mp3",
stream_format: "audio",
});
const output = fs.createWriteStream("speech.mp3");
for await (const chunk of speech.body) {
output.write(chunk);
}
output.end();
- Change the
textfield toinput, usevoiceinstead of a numericspeakeror adescription, and updateformattoresponse_format. - Include
stream_format: "audio"to receive raw audio data as a stream rather than as the default response.
Without streaming
Before, with the Djelia SDK:
await djelia.tts.textToSpeech(
new TTSRequestV2("Aw ni ce", "Moussa speaks clearly"),
"speech.mp3",
false,
Versions.v2,
);
After, with the OpenAI SDK:
const speech = await client.audio.speech.create({
model: "jifili-1",
input: "Aw ni ce",
voice: "moussa",
response_format: "mp3",
});
fs.writeFileSync("speech.mp3", Buffer.from(await speech.arrayBuffer()));
- Update your code to use
inputinstead oftext, specifyvoicein place of a numericspeakerordescription, and useresponse_formatrather thanformat. - The
jifili-1model supports the followingresponse_formatvalues:mp3,wav,pcm,opus,ulaw,alaw,l16_8000,l16_16000, andfmp4. Any other value returns a 400 error withparam: "response_format".
Translation
Before, with the Djelia SDK:
const translation = await djelia.translation.translate(
new TranslationRequest("Bonjour", Language.FRENCH, Language.BAMBARA),
Versions.v1,
);
console.log(translation.text);
After, with the OpenAI SDK:
const translation = await client.chat.completions.create({
model: "banjugu-1",
messages: [{ role: "user", content: "Bonjour" }],
djelia: {
source_language: "fra_Latn",
target_language: "bam_Latn",
},
});
console.log(translation.choices[0].message.content);
- Specify the
source_languageandtarget_languageinside a top-leveldjeliaobject in your request payload. - Use language codes such as
bam_Latn,fra_Latn, andeng_Latn, ensuring thatsource_languageandtarget_languageare always different. - To access the translated text, read from
choices[0].message.contentinstead of the response's top-leveltextfield.
curl
Set up the client
Before:
DJELIA_V1_URL=https://djelia.cloud/api/v1
DJELIA_V2_URL=https://djelia.cloud/api/v2
After:
OPENAI_BASE_URL=https://api.djelia.cloud/openai/v1
The examples send the key as Authorization: Bearer $DJELIA_API_KEY. The x-api-key header is also accepted on /openai/v1.
Speech to text
Streaming
Before:
curl -N "$DJELIA_V2_URL/models/transcribe/stream?translate_to_french=false" \
-H "x-api-key: $DJELIA_API_KEY" \
-F file=@audio.mp3
After:
curl -N "$OPENAI_BASE_URL/audio/transcriptions" \
-H "Authorization: Bearer $DJELIA_API_KEY" \
-F file=@audio.mp3 \
-F model=sunjata-1 \
-F stream=true
- To transcribe audio, use the
/audio/transcriptionsendpoint and include-F model=sunjata-1in your request. - Native streaming responses provide objects containing
{text, start, end}fields. When using OpenAI-compatible streaming, you’ll receive Server-Sent Events (SSE) withtranscript.text.segment,transcript.text.delta, andtranscript.text.doneevents, followed by a[DONE]message. - For speech translation, switch to the
/audio/translationsendpoint and use-F language=fra_Latninstead of the previoustranslate_to_french=trueoption.
Without streaming
Before:
curl "$DJELIA_V2_URL/models/transcribe?translate_to_french=false" \
-H "x-api-key: $DJELIA_API_KEY" \
-F file=@audio.mp3
After:
curl "$OPENAI_BASE_URL/audio/transcriptions" \
-H "Authorization: Bearer $DJELIA_API_KEY" \
-F file=@audio.mp3 \
-F model=sunjata-1 \
| jq -r .text
- By default, non-streaming responses are returned as arrays of segments. To access timestamps, add
-F response_format=verbose_jsonand inspect the.segmentsfield; for a simple transcript, stick with the defaultjsonformat and read.text. temperaturetakes effect onsunjata-1.
Text to speech
Streaming
Before:
curl -N "$DJELIA_V2_URL/models/tts/stream" \
-H "x-api-key: $DJELIA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"text":"Aw ni ce","description":"Moussa speaks clearly","format":"mp3"}' \
--output speech.mp3
After:
curl -N "$OPENAI_BASE_URL/audio/speech" \
-H "Authorization: Bearer $DJELIA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "jifili-1",
"input": "Aw ni ce",
"voice": "moussa",
"response_format": "mp3",
"stream_format": "audio"
}' \
--output speech.mp3
- Update your payload by renaming
texttoinput, and usevoicein place of a numericspeakerordescription. Changeformattoresponse_formatfor clarity. - To receive raw audio chunks, include
"stream_format": "audio"in your request.
Without streaming
Before:
curl "$DJELIA_V2_URL/models/tts" \
-H "x-api-key: $DJELIA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"text":"Aw ni ce","description":"Moussa speaks clearly","format":"mp3"}' \
--output speech.mp3
After:
curl "$OPENAI_BASE_URL/audio/speech" \
-H "Authorization: Bearer $DJELIA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"jifili-1","input":"Aw ni ce","voice":"moussa","response_format":"mp3"}' \
--output speech.mp3
- Update your request body by changing
texttoinput, and usevoiceinstead of a numericspeakerordescription. Also, renameformattoresponse_formatfor clarity. - The
jifili-1model supports the following response formats:mp3,wav,pcm,opus,ulaw,alaw,l16_8000,l16_16000, andfmp4. Any other value returns a 400 error withparam: "response_format".
Translation
Before:
curl "$DJELIA_V1_URL/models/translate" \
-H "x-api-key: $DJELIA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"text":"Bonjour","source":"fra_Latn","target":"bam_Latn"}'
After:
curl "$OPENAI_BASE_URL/chat/completions" \
-H "Authorization: Bearer $DJELIA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "banjugu-1",
"messages": [{"role": "user", "content": "Bonjour"}],
"djelia": {
"source_language": "fra_Latn",
"target_language": "bam_Latn"
}
}' \
| jq -r .choices[0].message.content
- Put
sourceandtargetin adjeliaobject withsource_languageandtarget_language, in the JSON body. - Read
choices[0].message.contentinstead of the top-leveltext.
Model names
| Old ID | Use instead | Status |
|---|---|---|
djelia-asr-v1 | sunjata-1 | Retired on September 20, 2026; returns 410. sunjata-1 behaves differently |
djelia-asr-v2 | sunjata-1 | Retired on September 20, 2026; returns 410. sunjata-1 behaves differently and supports temperature |
djelia-asr-v3 | sunjata-1 | Retired on September 20, 2026; returns 410. Same model, new name |
djelia-tts-v1 | jifili-1 | Retired on September 20, 2026; returns 410. Numeric speakers became the voice moussa |
djelia-tts-v2 | jifili-1 | Retired on September 20, 2026; returns 410. Descriptions became the voice moussa |
djelia-tts-v3 | jifili-1 | Retired on September 20, 2026; returns 410. Same model, new name |
djelia-translate-v1 | banjugu-1 | Retired on September 20, 2026; returns 410. Same model, new name |
A retired id returns 410 with code: "model_retired", and the message names its replacement. OpenAI model names such as whisper-1 and tts-1 are still accepted as aliases; see OpenAI model aliases.
Errors
The OpenAI-compatible API provides error responses using the standard OpenAI error envelope. Official SDKs handle these by raising their usual exceptions based on the status and type. For detailed information on error codes and how streaming failures are managed, refer to the Errors documentation.
Checklist
- Search for
djelia.cloud; change API hosts, but keepconsole.djelia.cloudlinks. - Search for
/api/v1,/api/v2,/v1/models, or/v2/models; a native call remains. - Search for
/models/transcribe; move it to/audio/transcriptionsor/audio/translations. - Search for
/models/tts; move it to/audio/speech. - Search for
/models/translate; move it to/chat/completions. - Search for
translate_to_french; replace it with/audio/translationsandlanguage=fra_Latn. - Search for
djelia-asr-,djelia-tts-, ordjelia-translate-; replace each model using the table above.