Skip to content

Latest commit

 

History

History
830 lines (674 loc) · 27.9 KB

File metadata and controls

830 lines (674 loc) · 27.9 KB

Sunbird AI API Tutorial

This comprehensive tutorial describes how to use the Sunbird AI API and includes code samples in Python.

Supported Languages

  • English (eng)
  • Acholi (ach)
  • Ateso (teo)
  • Luganda (lug)
  • Lugbara (lgg)
  • Runyankole (nyn)
  • Swahili (swa)
  • Plus 20 more Ugandan languages

Coverage differs per endpoint: speech-to-text spans 51 African languages, chat/translation spans 32 (sunflower-14b) or 67 (sunflower-9b), and text-to-speech spans 20. See the matrix below.


Language Support by Endpoint

The matrix below summarises which languages each task endpoint currently serves. Code is the canonical ISO/SALT code the API accepts (full language names also work where an endpoint takes a language or voice).

  • /tasks/audio/speech — text-to-speech (orpheus-3b-tts voice catalog).
  • /tasks/audio/transcriptions — speech-to-text. Now covers 51 African languages via Sunbird's faster-whisper ASR model — see Part 3.
  • /tasks/chat/completions — Sunflower chat. The /tasks/chat/completions column below reflects the default sunflower-14b model (English + 31 Ugandan/regional languages), which /tasks/translate shares. The alternative sunflower-9b model covers a broader set of 67 African languages — see Part 6 for the per-model breakdown.
Language name Code /tasks/audio/speech /tasks/audio/transcriptions /tasks/chat/completions
Acholi ach
Afrikaans afr
Akan aka
Alur alz
Amharic amh
Aringa luc
Ateso teo
Bambara bam
Bari bfa
Bemba bem
Berber ber
Chichewa nya
Dagaare dga
Dagbani dag
English eng
Ewe ewe
French fra
Fulah / Fulani ful
Hausa hau
Igbo ibo
Ikposo kpo
Jopadhola adh
Kabyle kab
Kakwa keo
Kalenjin kln
Kanuri kau
Karamojong kdj
Kikuyu kik
Kinyarwanda kin
Kumam kdi
Kupsabiny kpz
Kwamba rwm
Lango laj
Lendu led
Lingala lin
Lubwisi tlj
Lugbara lgg ✅ †
Lugungu rub
Lugwere gwr
Luganda lug
Luhya luy
Lumasaba myx
Lunyole nuj
Luo (Dholuo) luo
Lusoga xog
Ma'di mhi
Malagasy mlg
Ndebele nbl
Nigerian Pidgin pcm
Oromo orm
Pokot pok
Rukiga cgg
Rukonjo koo
Runyankole nyn
Runyoro nyo
Ruruuli ruc
Rutooro ttj
Samia lsm
Sesotho / Sotho sot ✅ †
Setswana / Tswana tsn ✅ †
Shona sna
Somali som
Swahili swa
Thur lth
Wolof wol
Xhosa xho
Yoruba yor
Zulu zul

Lugbara, Sesotho, and Setswana are in the orpheus-3b-tts training mix but currently expose no individual voice IDs in this checkpoint, so practical synthesis depends on a future voice release.


Part 1: Authentication

Creating an Account

  1. If you don't already have an account, create one at https://api.sunbird.ai/register
  2. Go to the tokens page to get your access token / api key

Using the Authentication API

Register a New User

import requests

url = "https://api.sunbird.ai/auth/register"
data = {
    "username": "your_username",
    "email": "your_email@example.com",
    "password": "your_secure_password"
}

response = requests.post(url, json=data)
print(response.json())

Get Access Token

import requests

url = "https://api.sunbird.ai/auth/token"
data = {
    "username": "your_username",
    "password": "your_password"
}

response = requests.post(url, data=data)
token_data = response.json()
access_token = token_data["access_token"]
print(f"Your token: {access_token}")

Part 2: Translation (Sunflower Model)

Translate text between 32 Ugandan and East African languages using the Sunflower model. Languages are accepted as ISO 639-3 codes (lug) or full names (Luganda), case-insensitively, and translation works between any pair of supported languages. source_language is optional — when omitted, Sunflower infers it from the text.

import os
import requests
from dotenv import load_dotenv

load_dotenv()

url = "https://api.sunbird.ai/tasks/translate"
access_token = os.getenv("AUTH_TOKEN")

headers = {
    "accept": "application/json",
    "Authorization": f"Bearer {access_token}",
    "Content-Type": "application/json",
}

# Example: Translate from Luganda to English
data = {
    "source_language": "lug",
    "target_language": "eng",
    "text": "Ekibiina ekiddukanya omuzannyo gw'emisinde mu ggwanga ekya Uganda Athletics Federation kivuddeyo nekitegeeza nga lawundi esooka eyemisinde egisunsulamu abaddusi abanakiika mu mpaka ezenjawulo ebweru w'eggwanga egya National Athletics Trials nga bwegisaziddwamu.",
}

response = requests.post(url, headers=headers, json=data)
print(response.json())

source_language is optional, and full language names work too:

data = {
    "target_language": "Luganda",
    "text": "How are you?",
}

response = requests.post(url, headers=headers, json=data)
print(response.json())

Supported languages (ISO code → name):

language_codes = {
    "ach": "Acholi",
    "adh": "Jopadhola",
    "alz": "Alur",
    "bfa": "Bari",
    "cgg": "Rukiga",
    "eng": "English",
    "gwr": "Lugwere",
    "kdi": "Kumam",
    "kdj": "Karamojong",
    "keo": "Kakwa",
    "kin": "Kinyarwanda",
    "koo": "Rukonjo",
    "kpz": "Kupsabiny",
    "laj": "Lango",
    "lgg": "Lugbara",
    "lsm": "Samia",
    "luc": "Aringa",
    "lug": "Luganda",
    "mhi": "Ma'di",
    "myx": "Lumasaba",
    "nuj": "Lunyole",
    "nyn": "Runyankole",
    "nyo": "Runyoro",
    "pok": "Pokot",
    "rub": "Lugungu",
    "ruc": "Ruruuli",
    "rwm": "Kwamba",
    "swa": "Swahili",
    "teo": "Ateso",
    "tlj": "Lubwisi",
    "ttj": "Rutooro",
    "xog": "Lusoga",
}

The response shape is unchanged from the previous NLLB-backed endpoint:

{
    "id": "trans-1a2b3c...",
    "status": "COMPLETED",
    "output": {
        "translated_text": "Oli otya?",
        "source_language": "lug",
        "target_language": "eng"
    }
}

Part 3: Speech-to-Text (STT)

Convert speech audio to text. The unified POST /tasks/audio/transcriptions endpoint is powered by Sunbird's faster-whisper ASR model (Sunbird/faster-whisper-51-african-languages, a Whisper large-v3 fine-tune) covering 51 African languages. Supports MP3, WAV, M4A, OGG, and more.

Migrating from the legacy STT routes? /tasks/modal/stt, /tasks/stt, /tasks/stt_from_gcs, and /tasks/org/stt are deprecated (they still work but return Deprecation/Sunset headers). Switch to /tasks/audio/transcriptions.

Breaking change. This endpoint previously accepted platform, adapter, whisper, recognise_speakers, org, and gcs_blob_name. Those parameters have been removed and are now rejected with 422. Speaker diarization and the organization workflow are still available on the deprecated /tasks/org/stt and /tasks/stt routes.

Transcribe a file

audio and language are both required. The model reuses Whisper's language-token slots for African languages, which makes automatic language detection unreliable — always pass a language explicitly.

import os
import requests
from dotenv import load_dotenv

load_dotenv()

url = "https://api.sunbird.ai/tasks/audio/transcriptions"
access_token = os.getenv("AUTH_TOKEN")

headers = {
    "accept": "application/json",
    "Authorization": f"Bearer {access_token}",
}

audio_file_path = "/path/to/audio_file.wav"

files = {
    "audio": ("recording.wav", open(audio_file_path, "rb"), "audio/wav"),
}
data = {
    "language": "lug",   # required: ISO 639-3 code, one of the 51 below
}

response = requests.post(url, headers=headers, files=files, data=data)
result = response.json()
print(f"Transcription: {result['audio_transcription']}")

Example response:

{
  "audio_transcription": "Ekibiina ekiddukanya ...",
  "language": "lug",
  "audio_url": "gs://.../audio.wav",
  "audio_transcription_id": 123,
  "duration_seconds": 12.4,
  "segments": null,
  "diarization_output": {},
  "formatted_diarization_output": "",
  "was_audio_trimmed": false,
  "original_duration_minutes": null
}

Timestamped segments

Set timestamps=true to also receive per-segment start/end times in segments. It is false by default, in which case segments comes back as null.

data = {
    "language": "ach",
    "timestamps": True,
}

response = requests.post(url, headers=headers, files=files, data=data)
result = response.json()

print(result["audio_transcription"])
for segment in result["segments"]:
    print(f"[{segment['start']:7.2f} -> {segment['end']:7.2f}] {segment['text']}")
{
  "audio_transcription": "Gyebaleko ssebo",
  "language": "ach",
  "duration_seconds": 2.25,
  "segments": [
    {"start": 0.0, "end": 1.0, "text": "Gyebaleko"},
    {"start": 1.0, "end": 2.25, "text": "ssebo"}
  ]
}

Note: For files larger than 100MB, only the first 10 minutes will be transcribed.

Supported languages (51)

Pass the ISO 639-3 code as language. All ten languages served by the previous version of this endpoint are still supported.

Code Language Code Language Code Language
ach Acholi kab Kabyle nyn Runyankole
afr Afrikaans kau Kanuri orm Oromo
aka Akan kik Kikuyu pcm Nigerian Pidgin
amh Amharic kin Kinyarwanda ruc Ruruuli
bam Bambara kln Kalenjin rwm Kwamba
bem Bemba koo Rukonjo sna Shona
ber Berber kpo Ikposo som Somali
cgg Rukiga led Lendu sot Sotho
dag Dagbani lgg Lugbara swa Swahili
dga Dagaare lin Lingala teo Ateso
eng English lth Thur tsn Tswana
ewe Ewe lug Luganda ttj Rutooro
fra French luo Luo wol Wolof
ful Fulani luy Luhya xho Xhosa
hau Hausa mlg Malagasy xog Lusoga
ibo Igbo myx Lumasaba yor Yoruba
nbl Ndebele zul Zulu
nya Chichewa

As a Python dictionary:

SALT_LANGUAGE_IDS_WHISPER = {
    'ach': "Acholi",          'kab': "Kabyle",           'nyn': "Runyankole",
    'afr': "Afrikaans",       'kau': "Kanuri",           'orm': "Oromo",
    'aka': "Akan",            'kik': "Kikuyu",           'pcm': "Nigerian Pidgin",
    'amh': "Amharic",         'kin': "Kinyarwanda",      'ruc': "Ruruuli",
    'bam': "Bambara",         'kln': "Kalenjin",         'rwm': "Kwamba",
    'bem': "Bemba",           'koo': "Rukonjo",          'sna': "Shona",
    'ber': "Berber",          'kpo': "Ikposo",           'som': "Somali",
    'cgg': "Rukiga",          'led': "Lendu",            'sot': "Sotho",
    'dag': "Dagbani",         'lgg': "Lugbara",          'swa': "Swahili",
    'dga': "Dagaare",         'lin': "Lingala",          'teo': "Ateso",
    'eng': "English",         'lth': "Thur",             'tsn': "Tswana",
    'ewe': "Ewe",             'lug': "Luganda",          'ttj': "Rutooro",
    'fra': "French",          'luo': "Luo",              'wol': "Wolof",
    'ful': "Fulani",          'luy': "Luhya",            'xho': "Xhosa",
    'hau': "Hausa",           'mlg': "Malagasy",         'xog': "Lusoga",
    'ibo': "Igbo",            'myx': "Lumasaba",         'yor': "Yoruba",
                              'nbl': "Ndebele",          'zul': "Zulu",
                              'nya': "Chichewa",
}

Per-language accuracy scales with the amount of training data available for each language; see the model card for per-language WER/CER figures.


Part 4: Language Detection

Automatically detect the language of text input. Useful for routing text to appropriate translation or processing pipelines.

import os
import requests
from dotenv import load_dotenv

load_dotenv()

url = "https://api.sunbird.ai/tasks/language_id"
access_token = os.getenv("AUTH_TOKEN")

headers = {
    "accept": "application/json",
    "Authorization": f"Bearer {access_token}",
    "Content-Type": "application/json",
}

text = "Oli otya? Webale nnyo ku kujja wano."

data = {"text": text}

response = requests.post(url, headers=headers, json=data)
result = response.json()
print(f"Detected language: {result}")

Supported Languages: Acholi, Ateso, English, Luganda, Lugbara, Runyankole


Part 5: Text-to-Speech (TTS)

Synthesize speech from text. The POST /tasks/audio/speech endpoint is served by the RunPod Orpheus-3B deployment (orpheus-3b-tts) — multilingual, multi-speaker; voices are catalog tags (e.g. salt_lug_0001). List them with GET /tasks/voice/speakers.

Breaking change. This endpoint previously accepted model, platform, and max_new_audio_tokens, and offered a spark-tts model. RunPod Orpheus is now the only TTS backend: those parameters are rejected, and the legacy per-provider routes (/tasks/modal/tts, /tasks/runpod/tts, /tasks/modal/orpheus/*, /tasks/tts, the /stream* and speaker-listing routes, and refresh-url) were removed. Use the endpoints below.

Single synthesis

import os
import requests
from dotenv import load_dotenv

load_dotenv()

url = "https://api.sunbird.ai/tasks/audio/speech"
access_token = os.getenv("AUTH_TOKEN")

headers = {
    "accept": "application/json",
    "Authorization": f"Bearer {access_token}",
    "Content-Type": "application/json",
}

payload = {
    "text": "I am a nurse who takes care of many people.",
    "voice": "salt_lug_0001",     # catalog tag; see GET /tasks/voice/speakers
    "language": "eng",            # ISO code or full name; picks a voice if none given
    "response_mode": "url",       # "url" (default), "stream", or "both"
}

response = requests.post(url, headers=headers, json=payload)
print(response.status_code)
print(response.json())

orpheus-3b-tts: languages covered

Speaker IDs encode both the source corpus (salt_*, waxal_*, slr32_*, slr129_*, bateesa_*) and the language. Languages marked with an em dash in the Speaker IDs column are present in the model's training mix but do not currently expose individual voice IDs in this checkpoint.

Config Language ISO 639-1 Region Speaker IDs
ach Acholi Uganda, South Sudan salt_ach_0001
waxal_ach_0001
waxal_ach_0005
waxal_ach_0006
waxal_ach_0008
afr Afrikaans af South Africa, Namibia slr32_afr_0009
eng English en (control language) salt_eng_0001
salt_eng_0002
salt_eng_0003
ewe Ewe ee Ghana, Togo slr129_ewe_0001
ful Fulah ff West Africa (Sahel) waxal_ful_0003
waxal_ful_0004
waxal_ful_0006
hau Hausa ha Nigeria, Niger, Chad waxal_hau_0004
waxal_hau_0006
waxal_hau_0007
waxal_hau_0008
ibo Igbo ig Nigeria waxal_ibo_0003
waxal_ibo_0005
waxal_ibo_0008
kik Kikuyu ki Kenya waxal_kik_0003
waxal_kik_0004
kin Kinyarwanda rw Rwanda bateesa_kin_0001
lgg Lugbara Uganda, DRC
lin Lingala ln DRC, Republic of Congo slr129_lin_0001
lug Luganda lg Uganda salt_lug_0001
waxal_lug_0002
waxal_lug_0003
waxal_lug_0004
waxal_lug_0005
waxal_lug_0006
waxal_lug_0007
waxal_lug_0008
luo Luo (Dholuo) Kenya, Tanzania waxal_luo_0001
waxal_luo_0002
waxal_luo_0003
waxal_luo_0004
nyn Runyankole Uganda salt_nyn_0001
waxal_nyn_0003
waxal_nyn_0004
waxal_nyn_0007
waxal_nyn_0008
sot Sesotho st Lesotho, South Africa
swa Swahili sw East Africa waxal_swa_0006
waxal_swa_0007
teo Ateso Uganda, Kenya salt_teo_0001
tsn Setswana tn Botswana, South Africa
xho Xhosa xh South Africa slr32_xho_0012
yor Yoruba yo Nigeria, Benin waxal_yor_0002
waxal_yor_0006
waxal_yor_0008

Per-language quality scales with the amount of training data Sunbird collected for that language; some configs have many more speaker hours than others. Audition the voices for each language before relying on a particular speaker — use the discovery snippet under Listing voices below.

Response modes

response_mode controls how the audio is returned:

  • url — synthesize, upload to GCP, return a signed URL (valid ~30 minutes) — default
  • stream — stream the raw audio bytes straight back (constant client memory; no GCS upload)
  • both — stream the raw audio bytes and return the signed URL in the X-Audio-Url response header

Note: RunPod synthesizes the full waveform before sending the first byte, so stream bounds client memory but does not reduce time-to-first-audio.

Listing voices

auth = {"Authorization": f"Bearer {access_token}"}

# Orpheus voices grouped by language (default)
print(requests.get("https://api.sunbird.ai/tasks/voice/speakers", headers=auth).json())

# Voices for one language
print(requests.get(
    "https://api.sunbird.ai/tasks/voice/speakers",
    headers=auth,
    params={"language": "lug"},
).json())

Batch synthesis

Synthesize up to 16 items in a single request (RunPod /tts/batch cap):

url = "https://api.sunbird.ai/tasks/audio/speech/batch"
payload = {
    "items": [
        {"text": "Good morning.", "voice": "salt_lug_0001"},
        {"text": "How are you?", "voice": "salt_eng_0001"},
    ]
}
response = requests.post(url, headers=headers, json=payload)
print(response.json())

Refreshing an expired URL

Signed URLs expire after ~30 minutes. Re-sign a stored object with GET /tasks/audio/speech/url:

print(requests.get(
    "https://api.sunbird.ai/tasks/audio/speech/url",
    headers={"Authorization": f"Bearer {access_token}"},
    params={"gcs_object": "orpheus_tts/2026-06-03/abc.wav"},
).json())

Example response (POST /tasks/audio/speech):

{
  "audio_url": "https://storage.googleapis.com/.../tts_audio/....wav?...",
  "model": "orpheus-3b-tts",
  "platform": "runpod",
  "voice": "salt_lug_0001",
  "audio_url_expires_at": "2026-06-03T22:59:36.954061Z",
  "language": "lug",
  "sample_rate": 24000,
  "duration_seconds": 4.0,
  "gcs_object": "orpheus_tts/2026-06-03/....wav",
  "request_id": "0f1e2d3c4b5a...",
  "timings_ms": {"inference_ms": 1820.5, "upload_ms": 234.1, "total_ms": 2095.6}
}

Part 6: Conversational AI (Sunflower)

The Sunflower models provide conversational AI for African languages through an OpenAI-compatible endpoint: POST /tasks/chat/completions. The request and response formats mirror the OpenAI Chat Completions API, so you can move between the OpenAI API and the Sunbird API by changing only the base URL and API key.

Deprecated: POST /tasks/sunflower_inference and POST /tasks/sunflower_simple are deprecated and will be removed in a future release. Use POST /tasks/chat/completions instead — a single instruction is just a request with one user message.

Choosing a model

Select a model with the model field. Two models are available:

model Coverage Best for
sunflower-14b (default) English + 31 Ugandan / regional languages (32 total) High-accuracy translation, factual Q&A, summarization, and explanation across Ugandan languages
sunflower-9b 67 African languages (good / moderate / basic tiers) Broad pan-African translation, instruction-following, and multi-turn chat

sunflower-14b is the default when model is omitted. The old identifier Sunbird/Sunflower-14B is no longer accepted — sending it returns a 400 error asking you to use sunflower-14b instead.

sunflower-14b — supported languages (English + 31 Ugandan/regional): Acholi (ach), Alur (alz), Aringa (luc), Ateso (teo), Bari (bfa), English (eng), Jopadhola (adh), Kakwa (keo), Karamojong (kdj), Kinyarwanda (kin), Kumam (kdi), Kupsabiny (kpz), Kwamba (rwm), Lango (laj), Lubwisi (tlj), Lugbara (lgg), Lugungu (rub), Lugwere (gwr), Luganda (lug), Lumasaba (myx), Lunyole (nuj), Ma'di (mhi), Pokot (pok), Rukiga (cgg), Rukonjo (koo), Runyankole (nyn), Runyoro (nyo), Ruruuli (ruc), Rutooro (ttj), Samia (lsm), Swahili (swa), Lusoga (xog).

sunflower-9b — supported languages (67 African languages, grouped by the model's understanding tier):

  • Good: Afrikaans, Zulu, Nigerian Pidgin, Chichewa, Swahili, Xhosa, Somali, Lingala, Sotho, Igbo, Malagasy, Kinyarwanda, Hausa, Tswana, Yoruba, Luganda, Shona, Ndebele, Amharic, Kirundi, Runyoro, Luo, Ewe, Runyankole.
  • Moderate: Kikuyu, Lusoga, Acholi, Rukiga, Rutooro, Oromo, Bemba, Ruruuli, Akan, Lango, Lugwere, Lugbara, Kumam, Lugungu, Lumasaba, Ateso, Lunyole.
  • Basic: Kabyle, Rukonjo, Bambara, Lubwisi, Wolof, Samia, Jopadhola, Alur, Bari, Kakwa, Dagbani, Karamojong, Berber, Fulani, Kwamba, Ma'di, Aringa, Luhya, Kalenjin, Kupsabiny, Lendu, Dagaare, Ik, Pokot, Kanuri, Dinka.

Per-language quality scales with the amount of training data available for each language. Full evaluations and language codes are on the model pages: sunflower-14b and sunflower-qwen3.5-9b.

Chat Completion

import requests

url = "https://api.sunbird.ai/tasks/chat/completions"

headers = {
    "accept": "application/json",
    "Authorization": "Bearer <your-access-token>",
    "Content-Type": "application/json",
}

payload = {
    "model": "sunflower-14b",
    "messages": [
        {
            "role": "user",
            "content": "Good morning, what is the weather today?",
        }
    ],
    "temperature": 0.3,
}

response = requests.post(url, headers=headers, json=payload)

print(response.status_code)
print(response.json())

Example Response:

{
  "id": "chatcmpl-8f14e45fceea167a5a36dedd4bea2543",
  "object": "chat.completion",
  "created": 1718000000,
  "model": "sunflower-14b",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "I'm glad you're up! While I can't provide real-time weather updates, I can help you understand weather forecasts or explain common weather patterns in Uganda."
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 22,
    "completion_tokens": 47,
    "total_tokens": 69
  }
}

Using the OpenAI SDK

Because the endpoint is OpenAI-compatible, the official OpenAI Python SDK works out of the box:

from openai import OpenAI

client = OpenAI(
    api_key="<your-access-token>",
    base_url="https://api.sunbird.ai/tasks",
)

completion = client.chat.completions.create(
    model="sunflower-14b",
    messages=[
        {
            "role": "user",
            "content": "translate from english to luganda: i am very hungry they should serve food in time",
        }
    ],
    temperature=0.1,
)

print(completion.choices[0].message.content)
# Ndi muyala nnyo, emmere erina okugabibwa mu budde.

Multi-turn Conversations

Maintain context by sending the running message history. You can also set a custom system message (when omitted, a default Sunflower system message is applied):

payload = {
    "model": "sunflower-14b",
    "messages": [
        {"role": "system", "content": "You are a helpful multilingual assistant."},
        {"role": "user", "content": "Translate 'hello' to Luganda."},
        {"role": "assistant", "content": "'Hello' is 'Gyebaleko'."},
        {"role": "user", "content": "And to Acholi?"},
    ],
}

Streaming

Set "stream": true to receive Server-Sent Events in OpenAI chat.completion.chunk format, terminated by data: [DONE]. With the OpenAI SDK:

stream = client.chat.completions.create(
    model="sunflower-14b",
    messages=[{"role": "user", "content": "Tell me about Uganda."}],
    stream=True,
)

for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)

Supported request parameters: model (sunflower-14b or sunflower-9b; the old Sunbird/Sunflower-14B identifier is no longer accepted), messages, temperature (0.0-2.0, default 0.3), max_tokens, top_p, stop, and stream.


Part 7: File Upload (Signed URLs)

Generate secure signed URLs for direct client uploads to GCP Storage. Useful for uploading audio files before transcription.

import os
import requests
from dotenv import load_dotenv

load_dotenv()

# Step 1: Generate upload URL
url = "https://api.sunbird.ai/tasks/generate-upload-url"
access_token = os.getenv("AUTH_TOKEN")

headers = {
    "accept": "application/json",
    "Authorization": f"Bearer {access_token}",
    "Content-Type": "application/json",
}

data = {
    "file_name": "recording.wav",
    "content_type": "audio/wav"
}

response = requests.post(url, headers=headers, json=data)
result = response.json()

upload_url = result["upload_url"]
file_id = result["file_id"]

print(f"Upload URL: {upload_url}")
print(f"File ID: {file_id}")
print(f"Expires at: {result['expires_at']}")

# Step 2: Upload file directly to GCS
with open("/path/to/your/recording.wav", "rb") as f:
    upload_response = requests.put(
        upload_url,
        data=f,
        headers={"Content-Type": "audio/wav"}
    )

if upload_response.status_code == 200:
    print("File uploaded successfully!")

Features:

  • Temporary signed URLs (valid for 30 minutes)
  • Direct upload to Google Cloud Storage
  • Path traversal protection
  • Support for multiple content types

Additional Resources

Rate Limiting

API endpoints are rate-limited to ensure fair usage. If you need higher rate limits for production use, please contact the Sunbird AI team.

Feedback and Questions

Don't hesitate to leave us any feedback or questions by opening an issue in this repo.