Klerku API docs
One endpoint turns Albanian speech into text, with English understood in the same recording. It follows OpenAI's /v1/audio/transcriptions, so the official OpenAI libraries work unchanged.
| Base URL | https://api.klerku.com/v1 |
| Authentication | Authorization: Bearer klk_… |
| Model | transkriptuesi-v3: Albanian and English |
| Price | €0.99 per hour of audio, billed per second, prepaid |
Quickstart
- Sign in with Google or Apple and add hours on the Billing page.
- Create a key on the API keys page and keep it in an environment variable:
export KLERKU_API_KEY="klk_…" - Send a file:
curl https://api.klerku.com/v1/audio/transcriptions \ -H "Authorization: Bearer $KLERKU_API_KEY" \ -F file=@intervista.m4a
# pip install openai import os from openai import OpenAI client = OpenAI(base_url="https://api.klerku.com/v1", api_key=os.environ["KLERKU_API_KEY"]) with open("intervista.m4a", "rb") as f: r = client.audio.transcriptions.create(model="transkriptuesi-v3", file=f) print(r.text)
// npm install openai import OpenAI from "openai"; import fs from "node:fs"; const client = new OpenAI({ baseURL: "https://api.klerku.com/v1", apiKey: process.env.KLERKU_API_KEY }); const r = await client.audio.transcriptions.create({ model: "transkriptuesi-v3", file: fs.createReadStream("intervista.m4a"), }); console.log(r.text);
{"text": "Përshëndetje. Po ju telefonoj për faturën e tetorit sepse në sistem duket ende e papaguar. …"}base_url and the key. Existing code that sends model="whisper-1" keeps working.Authentication
Every request needs an API key in the Authorization header. Keys start with klk_.
Authorization: Bearer klk_…
- Create and revoke keys on the API keys page. A key is shown once, when you create it; we store only a hash.
- Keep keys on your server. Anyone who has a key can spend your balance, so don't ship one inside a mobile app or a web page.
- Use one key per app or environment, so you can revoke one without touching the others.
Create a transcription
https://api.klerku.com/v1/audio/transcriptionsSend the audio as multipart/form-data. The response comes back when the whole file is transcribed.
Request body
| Field | Description |
|---|---|
filerequired | The audio or video file. Anything ffmpeg reads: mp3, m4a, aac, wav, flac, ogg, opus, webm, mp4, amr, WhatsApp voice notes. Up to 3 hours. |
modeloptional | transkriptuesi-v3. Any other value, such as whisper-1, is accepted and uses the same model. |
response_formatoptional | json (default), text, srt, vtt or verbose_json. See Response formats. |
timestamp_granularities[]optional | segment, word, or both (send the field twice). Only with verbose_json. Default: segment. |
language, prompt, temperature | Accepted for compatibility and ignored. The model recognises Albanian and English on its own, even when speakers switch mid-sentence. |
Request headers
| Header | Description |
|---|---|
Authorizationrequired | Bearer klk_… |
X-Klerku-Contributeoptional | false keeps this request's audio out of training data, even if your account contributes. See Your data. |
Example with word timestamps
curl https://api.klerku.com/v1/audio/transcriptions \ -H "Authorization: Bearer $KLERKU_API_KEY" \ -F file=@thirrja.mp3 \ -F model=transkriptuesi-v3 \ -F response_format=verbose_json \ -F "timestamp_granularities[]=word" \ -F "timestamp_granularities[]=segment"
with open("thirrja.mp3", "rb") as f: r = client.audio.transcriptions.create( model="transkriptuesi-v3", file=f, response_format="verbose_json", timestamp_granularities=["word", "segment"], ) for w in r.words: print(f"{w.start:6.2f} {w.word}")
const r = await client.audio.transcriptions.create({ model: "transkriptuesi-v3", file: fs.createReadStream("thirrja.mp3"), response_format: "verbose_json", timestamp_granularities: ["word", "segment"], }); for (const w of r.words) console.log(w.start.toFixed(2), w.word);
Response formats
The examples below are real output for the 26-second support call played on the home page.
json (default)
{"text": "Përshëndetje. Po ju telefonoj për faturën e tetorit sepse në sistem duket ende e papaguar. E kontrollova tani. Pagesa është bërë dje me bank transfer. …"}text
The transcript as plain text, text/plain.
verbose_json
Adds the duration, segments and, if you ask for them, words. Times are in seconds from the start of the file.
{
"task": "transcribe",
"language": "albanian",
"duration": 25.601,
"text": "Përshëndetje. Po ju telefonoj për faturën e tetorit …",
"segments": [
{ "id": 0, "start": 0.32, "end": 11.68, "text": "Përshëndetje. Po ju telefonoj … me bank transfer." },
…
],
"words": [
{ "word": "Përshëndetje.", "start": 0.32, "end": 1.52 },
{ "word": "Po", "start": 1.6, "end": 1.68 },
…
]
}srt and vtt
Subtitles ready for a video player: cues of up to 7 seconds and two lines of about 42 characters, broken at sentence ends where possible.
1 00:00:00,320 --> 00:00:06,000 Përshëndetje. Po ju telefonoj për faturën e tetorit sepse në sistem duket ende e 2 00:00:06,000 --> 00:00:08,800 papaguar. E kontrollova tani.
Response headers
| Header | Meaning |
|---|---|
X-Audio-Duration | Length of the audio in seconds, as decoded. |
X-Billed-Seconds | What this request cost, in whole seconds. |
X-Processing-Seconds | Time spent transcribing, in seconds. |
X-Klerku-Contribute | true if this request's audio is kept to improve the model, false if not. |
List models
https://api.klerku.com/v1/models{
"object": "list",
"data": [{ "id": "transkriptuesi-v3", "object": "model", "owned_by": "klerku" }]
}Errors
Errors use OpenAI's shape, so client libraries raise their usual exceptions.
{
"error": {
"message": "Not enough prepaid time for this audio. Add hours at https://api.klerku.com.",
"type": "insufficient_quota",
"param": null,
"code": "insufficient_quota"
}
}| Status | When |
|---|---|
400 | The request isn't multipart/form-data, the file is missing, empty or unreadable, or response_format is unknown. |
401 | The key is missing, wrong or revoked. |
402 | Your balance is empty, or the audio is longer than your balance. Checked before any work is done, so nothing is charged. X-Audio-Duration tells you how long the file is. |
413 | The audio is longer than 3 hours. Split it and send the parts. |
429 | More than 2 requests at once on your account. Wait for one to finish. |
5xx | Something failed on our side. You are not charged; retry with a short backoff. |
Limits and speed
- Length: up to 3 hours of audio per request.
- Concurrency: 2 requests at a time per account. Need more? Tell us.
- Size: no separate file-size limit, but compressed formats (m4a, mp3, opus) upload much faster than WAV.
- Speed: about 9 minutes of processing per hour of audio; a short voice note takes a few seconds. After a quiet period the first request can take about 10 seconds longer while the service starts.
- Timeouts: keep the connection open until the response arrives. For a 3-hour file that can be around 30 minutes, so raise your HTTP client's timeout.
Billing
- €0.99 per hour of audio, paid in advance in packs of 5, 10, 25 or 100 hours. Hours never expire.
- Each request is billed by the audio's length, rounded up to the next whole second.
X-Billed-Secondsshows the amount. - Failed requests and requests refused with
402are not charged. - Polar is our merchant of record: it calculates VAT at checkout and issues invoices, which you can download from the Billing page.
Your data
To make Albanian recognition better, we keep a copy of the audio you send, converted to 16 kHz mono, together with the transcript we returned. It is stored on our own servers without your name, email or account details, under a pseudonymous tag, and used only to train and test our speech models. It is never sold or shared.
- Turn it off for your account in the console, on the Overview page. It stops from the next request.
- Turn it off for one request with the header
X-Klerku-Contribute: false. The response headerX-Klerku-Contributeconfirms what happened. - Delete what was kept by asking us; the tag lets us find your account's recordings.
Requests that fail or are refused are never kept. We also keep the time, length and key of each request for billing. Read the Privacy Policy and Terms.