Konthora API
The same API that powers the text-to-speech and transcription workspaces on this site, documented for direct use. No API key and no account: every job returns its own access token.
Base URL
All endpoints live under the versioned base URL below. Requests and responses are JSON, except for file downloads, which return the audio or transcript file itself.
https://devsharif-konthora-api.hf.space/api/v1There is no other version: the path always starts with /api/v1. Browser (fetch) calls are accepted from konthora.dev.bd and from localhost development origins only; server-side calls from anywhere are fine.
Authentication
There are no API keys. Creating a job returns a jobId and an accessToken. Send that token as a Bearer token on every later call for that job — status checks, audio downloads, transcripts, and result files:
Authorization: Bearer YOUR_TOKEN- The token is shown once. The create-job response is the only place the full token appears; the server stores only a hash of it. If you lose the token, there is no way to recover the job — create a new one.
- One token per job. A token only works for the job it was issued with. Using it on another job returns 401.
- Public endpoints need no token. Listing voices, reading transcription capabilities, and fetching a voice preview are unauthenticated.
Text to speech
Turn text into spoken audio. Kokoro is the default engine; Edge voices are Microsoft neural voices served as a second engine while Edge is reachable. Use the same voices the text-to-speech workspace offers — see all voices for the catalogue.
List voices
GET/tts/voices
Returns the voice catalogue the server will currently accept: all Kokoro voices, plus Edge voices only while Edge is reachable. When Edge is down, its voices are simply absent from this list.
curl https://devsharif-konthora-api.hf.space/api/v1/tts/voicesEach voice carries id, displayName, gender, accent, language, recommended, speed limits (defaultSpeed, minimumSpeed, maximumSpeed), engine (kokoro or edge), and previewUrl. The preview URL is empty for Edge voices — they have no hosted preview clips, and the on-demand preview endpoint below is what serves them.
Create a job
POST/tts/jobs
Submits text for synthesis and returns jobId, accessToken, and status (initially queued).
| Field | Required | Rules |
|---|---|---|
| text | Yes | 1–2000 characters, at least one non-whitespace character. Control characters other than tab, newline, and carriage return are rejected. |
| voiceId | Yes | Must be an id from GET /tts/voices. An unknown or currently unserved voice returns 400 VOICE_UNSUPPORTED. |
| engine | No (default kokoro) | kokoro or edge. It must match the voice's own engine; a mismatch returns 400. The server resolves the engine from the voice in any case, so this field cannot switch a voice to the other engine. |
| accent | No (default American English) | For Kokoro voices it must be one of the accents in the voice catalogue; for Edge voices any non-empty accent is accepted. The accent actually used is always taken from the voice itself. |
| speed | No (default 1.0) | Speech rate factor, 0.75–1.25. |
| outputFormat | No (default mp3) | mp3 or wav. See the format note below: if FFmpeg is unavailable the server silently falls back to the other format. |
| sentencePauseMs | No (default 220) | Silence inserted at sentence boundaries, 0–1000 ms. |
| paragraphPauseMs | No (default 500) | Silence inserted at paragraph boundaries, 0–2000 ms. |
| normalizeText | No (default true) | Applies the server's conservative text-normalization pass before synthesis. |
curl -X POST https://devsharif-konthora-api.hf.space/api/v1/tts/jobs \
-H "Content-Type: application/json" \
-d '{
"text": "Welcome to Konthora. This is how my voice sounds.",
"voiceId": "af_heart",
"engine": "kokoro",
"accent": "American English",
"speed": 1.0,
"outputFormat": "mp3",
"sentencePauseMs": 220,
"paragraphPauseMs": 500,
"normalizeText": true
}'Check job status
GET/tts/jobs/{jobId}
Poll this endpoint until status is completed or failed. Requires the Bearer token.
curl https://devsharif-konthora-api.hf.space/api/v1/tts/jobs/JOB_ID \
-H "Authorization: Bearer YOUR_TOKEN"status is one of queued, processing, completed, failed, or expired. progressStage gives finer detail: queued, preparing_text, generating_speech, processing_audio, finalizing_file, then completed, failed, or expired.
The response also includes createdAt and expiresAt, durationSeconds (null until the audio exists), characterCount, outputFormat (the format actually produced — see the format note below), errorCode and errorMessage on failure, and downloadUrl, which is only present once the job is completed.
Download the audio
GET/tts/jobs/{jobId}/audio
Returns the finished audio file (audio/mpeg for MP3, audio/wav for WAV) as a download named like konthora-speech-<first 8 characters of the job id>.mp3. Requires the Bearer token. A HEAD request is also accepted. Calling it before the job completes returns 400 — the audio is not available for the job's current state.
curl https://devsharif-konthora-api.hf.space/api/v1/tts/jobs/JOB_ID/audio \
-H "Authorization: Bearer YOUR_TOKEN" \
-o konthora-speech.mp3Preview a voice
GET/tts/preview/{voice_id}
Returns a short MP3 clip of one Edge voice reading a single sentence in its own language, so you can hear a voice before spending a job on it. No token needed.
curl https://devsharif-konthora-api.hf.space/api/v1/tts/preview/en-US-AriaNeural \
-o preview.mp3- Edge voices only. Kokoro voices and unknown ids return 404 VOICE_UNSUPPORTED. Kokoro previews are static clips served through the
previewUrlfield of the voice list instead. - One fixed sentence per language. The clip reads a single sentence in the voice's language — English, Bangla, Hindi, Spanish, French, Italian, or Portuguese; any other language falls back to the English sentence.
- Cached, and cheap. The clip is synthesized once per voice and then served from disk (cached by browsers for a day). Previews have their own rate-limit bucket of 120 per hour and never consume the 30-per-hour TTS job quota.
- Edge must be up. If Edge is unreachable when you ask, the endpoint returns 503 even if the voice is still listed in the catalogue.
Format note: Kokoro synthesis produces a WAV master; MP3 output is made by transcoding it with FFmpeg, and Edge synthesis produces MP3, which is transcoded to WAV the same way. If FFmpeg is unavailable on the server, the requested format is silently replaced with the other one and the status response's outputFormat tells you which file you actually got — so always read that field instead of assuming your request was honoured.
Transcription
Turn an audio or video file into a timestamped transcript. Transcription is English only: the model is faster-whisper small.en, so auto detection maps to English and the reported detected language is always en. The same flow powers the audio-to-text workspace.
Capabilities
GET/transcription/capabilities
Returns the limits and options the server currently enforces, so clients can validate before uploading: accepted file extensions, maximum file size in bytes, maximum media duration in seconds, supported languages, timestamp modes, export formats, and whether word timestamps are available.
curl https://devsharif-konthora-api.hf.space/api/v1/transcription/capabilitiesCreate a job
POST/transcription/jobs
Uploads a media file as multipart/form-data and returns jobId, accessToken, and status. The file streams to the server in 1 MB chunks.
| Field | Required | Rules |
|---|---|---|
| file | Yes | Extensions: .mp3, .wav, .m4a, .aac, .mp4, .webm, .mov. Maximum 100 MB and 600 seconds (10 minutes) of media. The extension, the declared MIME type, and the file's binary header are all checked — a renamed file of the wrong type is rejected. |
| language | No (default auto) | auto or en only. Both mean English: auto detection maps to English under the small.en model. Any other value returns 400 LANGUAGE_UNSUPPORTED. |
| timestampMode | No (default sentence) | sentence, paragraph, or word. Word mode includes per-word start/end times in the structured transcript. |
| exportFormat | No (default txt) | txt, srt, vtt, or json. This is the default format for the result download; the download endpoint can override it per request. |
curl -X POST https://devsharif-konthora-api.hf.space/api/v1/transcription/jobs \
-F "file=@recording.mp3" \
-F "language=auto" \
-F "timestampMode=sentence" \
-F "exportFormat=txt"After upload, the server inspects the media container with FFprobe (rejecting files longer than 600 seconds or with no audio track) and extracts the audio to a 16 kHz mono WAV with FFmpeg before transcribing. If the upload is cancelled or the file cannot be read, the job is cleaned up and the queue slot is released.
Check job status
GET/transcription/jobs/{jobId}
Poll this endpoint until status is completed or failed. Requires the Bearer token.
curl https://devsharif-konthora-api.hf.space/api/v1/transcription/jobs/JOB_ID \
-H "Authorization: Bearer YOUR_TOKEN"status is one of queued, processing, completed, failed, or expired. progressStage moves through uploading (while the file streams in), inspecting_media, extracting_audio, transcribing, and formatting_transcript.
The response also includes the original filename and size, media duration, detected language and its probability, transcript and word counts, segment count, the timestamp mode and export format you chose, expiresAt, errorCode and errorMessage on failure, and resultUrl, which is only present once the job is completed.
Get the structured transcript
GET/transcription/jobs/{jobId}/transcript
Returns the transcript as structured JSON: schema version, job id, detected language and probability, duration, the full text, per-segment start/end times and text, and — when word timestamps are available — a flat word list with per-word start/end times and probabilities. Requires the Bearer token. Only available once the job is completed; before that it returns 400 RESULT_NOT_READY.
curl https://devsharif-konthora-api.hf.space/api/v1/transcription/jobs/JOB_ID/transcript \
-H "Authorization: Bearer YOUR_TOKEN"Download the transcript file
GET/transcription/jobs/{jobId}/result
Renders the stored transcript in the requested format and returns it as a file download, named after the original file (for example recording.srt). Requires the Bearer token. Without a format query parameter it uses the exportFormat chosen at job creation; pass ?format=txt, srt, vtt, or json to override it. An unknown format returns 400, and a job that is not completed returns 400 RESULT_NOT_READY.
curl "https://devsharif-konthora-api.hf.space/api/v1/transcription/jobs/JOB_ID/result?format=srt" \
-H "Authorization: Bearer YOUR_TOKEN" \
-o transcript.srtLimits and expiry
Limits are enforced per client IP over a sliding one-hour window. When a limit is hit the response is 429 with a Retry-After header telling you how many seconds to wait.
| Bucket | Per hour, per IP | Concurrency |
|---|---|---|
| Text-to-speech jobs | 30 job creations | 2 active jobs at once; the TTS queue holds 10 jobs |
| Transcription jobs | 15 job creations | 1 active job at a time; the transcription queue holds 5 jobs |
| Voice previews | 120 previews | Separate bucket — previews never consume the TTS job quota |
A full queue returns 503 QUEUE_FULL, and hitting the active-job cap returns 429 — both mean “wait for a running job to finish”, not “wait an hour.” Listing voices, reading capabilities, polling status, and downloading results are not rate-limited.
Expiry: finished jobs — completed or failed — are kept for 60 minutes after they finish. The status response's expiresAt tells you exactly when. After that the audio or transcript files are deleted from disk and the job reports expired; later reads return 410 JOB_EXPIRED. Download results promptly — there is no way to extend a job's life.
Errors
Errors are JSON with a machine-readable code and a human-readable message: {"code": "RATE_LIMITED", "message": "..."}. Note that request validation failures return 400, not the 422 FastAPI would send by default.
| Status | Code | Meaning |
|---|---|---|
| 400 | INVALID_REQUEST | A field failed validation — for example text over 2000 characters, speed outside 0.75–1.25, a voice/engine mismatch, an unsupported language, timestamp mode, export format, or file type, a file over 100 MB, a result requested before the job finished, or an audio download for a job that is not completed. |
| 401 | UNAUTHORIZED | The Bearer token is missing or does not match the job. |
| 404 | JOB_NOT_FOUND / VOICE_UNSUPPORTED | No job with that id exists, or the preview endpoint was asked for a Kokoro or unknown voice. |
| 410 | JOB_EXPIRED | The job finished more than 60 minutes ago and its output has been deleted. |
| 429 | RATE_LIMITED | The hourly limit or the active-job cap for your IP was hit. Check the Retry-After header. |
| 500 | GENERATION_FAILED / INTERNAL_SERVER_ERROR | Audio generation failed, or something unexpected went wrong on the server. The message is deliberately generic. |
| 503 | QUEUE_FULL / SERVICE_UNAVAILABLE / MODEL_UNAVAILABLE / ENCODER_UNAVAILABLE | The job queue is full, Edge previews are down, or the speech engine or audio encoder is unavailable. Retry later. |
Things to know before you build
- Jobs live in server memory. Job records are kept in memory, not in a database. If the API service restarts, job ids from before the restart stop resolving (404) — keep your tokens and downloads short-lived, and do not store job ids as permanent references.
- One worker per queue. TTS and transcription each run a single worker, so jobs run one at a time; long texts and long files queue behind whatever is already running.
- Edge voices can disappear mid-day. Edge is an unofficial free endpoint with no SLA. Its voices only appear in the voice list while a cached availability probe says Edge is reachable, and preview requests can still 503 if Edge goes down between probes.
- Transcription is English only. Uploading non-English audio still runs, but the model only knows English — the transcript will be wrong, not an error.
- Download URLs are relative. The
downloadUrlandresultUrlfields in status responses are paths like/api/v1/tts/jobs/…/audio; resolve them against the base URL above. - Poll, don't guess. There are no webhooks. Poll the status endpoint every couple of seconds and stop when the status is
completed,failed, orexpired.
Prefer the website? The text-to-speech workspace and the audio-to-text workspace use exactly this API, with the same voices, limits, and 60-minute expiry.