Base URL: https://api.bodhan.ai/v1 · Auth: Authorization: Bearer <your key>
Keys are per model. To rotate one, delete it and make a new one.
The /v1 routes keep the OpenAI request and response shapes, so the SDK you
already use works once its base URL points at Bodhan.
| Model |
What it does |
indic-translate |
Translation between English and 22 Indian languages, in native script, Roman or code-mixed |
indic-transliterate |
Script conversion — same language in and out, only the script changes |
indic-transcribe |
Speech to text |
indic-ocr |
Document OCR — a page image in, Markdown in reading order out |
indic-speak |
Text to speech |
from openai import OpenAI
client = OpenAI(
base_url="https://api.bodhan.ai/v1",
api_key="YOUR_BODHAN_KEY",
)
# Translation
r = client.chat.completions.create(
model="indic-translate",
messages=[{"role": "user", "content": "Good morning"}],
extra_body={"target_language_code": "te", "target_script": "native"},
)
# Speech to text
t = client.audio.transcriptions.create(
model="indic-transcribe", file=open("lesson.wav", "rb"),
)
# Document OCR: a page image in, Markdown in reading order out
o = client.chat.completions.create(
model="indic-ocr",
messages=[{"role": "user", "content": [
{"type": "image_url", "image_url": {"url": "data:image/png;base64,..."}},
]}],
)
print(o.choices[0].message.content)
For OCR, the reference has the full response
shape and the layout blocks it returns.
Or with curl:
curl https://api.bodhan.ai/v1/chat/completions \
-H "Authorization: Bearer YOUR_BODHAN_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"indic-translate","messages":[{"role":"user","content":"Welcome"}],"target_language_code":"hi"}'
Limits
Each key has a requests-per-minute allowance and a concurrency ceiling on its
model. Read them off the response rather than hardcoding them — every
response carries both:
x-ratelimit-limit-requests requests per minute for this key
x-ratelimit-limit-parallel-requests concurrent requests for this key
Over the allowance you get HTTP 429 with a retry-after header saying how
many seconds until a slot frees up; the window slides. Retries count against
the limit. Running out of credit also returns 429, with a different message.
If you need more throughput, write to support.