Skip to content

API

Manzil: https://console.gapi.uz. Har bir so‘rov Authorization: Bearer <token> sarlavhasi bilan. Tokenlar kabinetning «API tokenlar» bo‘limida yaratiladi va loyihaga bog‘langan.

Javoblar JSON da. Xato shunday ko‘rinadi:

json
{"error": "insufficient_balance", "hint": "balance 3.20 g (0.00 g held by jobs in flight), this job needs 4.71 g; the beta balance is topped up to 240 g at midnight Asia/Tashkent"}

Vazifalar

POST /v1/jobs: yozuvni yuklash

multipart/form-data:

MaydonBu nima
fileAudio: mp3, wav, ogg/opus, m4a, flac, webm. 200 MiB gacha
settingsLoyiha sozlamalari ustidan shu so‘rov uchun sozlamalar JSON, ixtiyoriy
vocabularyLoyiha lug‘ati o‘rniga shu so‘rov uchun atamalar JSON massivi, ixtiyoriy
webhook_urlTayyor bo‘lganda xabar yuboriladigan manzil, ixtiyoriy

Javob 202: {"id", "state": "queued", "class": "batch", "estimated_seconds", "created_at", "result_url"}. result_url to‘liq manzil — uni saqlab, shundayligicha chaqirsa bo‘ladi. class oddiy yuklashda batch, POST /v1/transcribe da interactive.

Formatlar ro‘yxati to‘liq emas: ffmpeg o‘qiydigan hamma narsa qabul qilinadi, xom AAC oqimi ham. Dekodlanmagan fayl 422 audio_unreadable oladi.

Yozuvni yuklash shart emas: agar u allaqachon havolada tursa, havolani yuboring, biz o‘zimiz yuklab olamiz. Bu telefoniya integratsiyalari uchun qulay — u yerda yozuv baribir omborda yotadi.

bash
curl -X POST https://console.gapi.uz/v1/jobs \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"url": "https://example.com/call.mp3", "settings": {"emotion": false}}'

Uchinchi yo‘l — faylning o‘zini multipart siz so‘rov tanasida yuborish, nomini X-File-Name sarlavhasida ko‘rsatib. Unda sozlamalar loyihadan olinadi.

Xuddi shu uchta shaklni POST /v1/transcribe ham qabul qiladi.

GET /v1/jobs/{id}: holat

state: queued, running, done, failed, cancelled. Davom etayotganda progress_seconds bor. Muvaffaqiyatsizlikda error bor.

GET /v1/jobs/{id}/events: hodisalar

text/event-stream. Bu shunchaki jarayon ko‘rsatkichi emas: replikalar tayyor bo‘lgani sari shu yerga keladi, shuning uchun matnni yozuv tugashini kutmay, suhbat davomida ko‘rsatsa bo‘ladi.

HodisaNima bor
segmentsTayyor replikalar massivi, tartib bilan, natijadagi ko‘rinishda
stateVazifa holatini o‘zgartirdi: data da GET /v1/jobs/{id} qaytaradigan vazifaning o‘zi
doneVazifa tugadi; oqim yopiladi. data da {"state", "job"}, tayyorida esa yana result_url
event: segments
data: [{"index": 0, "start": 0.42, "end": 3.9, "speaker": 1, "text": "Assalomu alaykum…"}]

Kech ulangan avval tayyor bo‘lgan hammasini, keyin yangisini oladi — demak boshini o‘tkazib yuborib bo‘lmaydi.

done dan oldingi oxirgi to‘plam replikalarni yana bir marta, endi yakuniy ko‘rinishda yuboradi: yozuv ketayotganda ulardagi tinish belgilari vaqtinchalik. Shuning uchun replikalarni index bo‘yicha yig‘ing, avval kelganini almashtirib — shunda oqim oxirida sizda aynan natijadagi matn bo‘ladi.

Har yigirma soniyada oqimga : keepalive izoh qatori ketadi, proksi ulanishni yopmasin uchun. Oqim uzilsa, hech narsa yo‘qolmaydi: qaytadan obuna bo‘ling yoki natijani butunlayicha oling.

GET /v1/jobs/{id}/result: natija

Javob formati bo‘limida tasvirlangan. Natija 30 kun saqlanadi.

GET /v1/jobs: ro‘yxat

json
{"jobs": [{"id": "41f79b78-…", "state": "done", "class": "batch", "estimated_seconds": 283,
           "audio_seconds": 282.7, "created_at": "…", "finished_at": "…"}]}

Loyihaning oxirgi 50 vazifasi, yangisi yuqorida; ?limit= uni 200 tagacha ko‘taradi. Maksimumdan katta son tashlab yuborilmaydi, balki qisiladi: limit=500 ham o‘sha 200 tani qaytaradi. Sahifalab o‘tish yo‘q: bu arxivni yuklab olish emas, yaqin o‘tmishga qarash. O‘chirilgan vazifalar ro‘yxatda ko‘rinmaydi.

DELETE /v1/jobs/{id}: bekor qilish yoki o‘chirish

Bitta so‘rov ikkovidan hozir ma’noga egasini bajaradi.

Navbatdagi yoki ishlayotgan vazifa — bekor qilinadi. Holat cancelled bo‘ladi, hisobdan hech narsa yechilmaydi, job.cancelled webhooki keladi. Javobda vazifaning o‘zi. Bekor qilish — ishni to‘xtatish, unutish emas: vazifa ro‘yxatda qoladi.

Allaqachon tugagan vazifa — o‘chiriladi. Javob {"id", "state", "deleted": true}, va shu daqiqadan u yo‘q: na ro‘yxatda, na GET /v1/jobs/{id} da, na natijada, na hodisalar oqimida; takroriy DELETE 404 job_not_found javobini beradi. Ham bekor qilish, ham o‘chirish uchun DELETE ni ikki marta chaqiring.

O‘chirish vazifani sizdan yashiradi, lekin bizda o‘chirmaydi: u uchun yechilgan pul hisob tarixida qoladi, yozuv va matn esa odatdagi saqlash muddatini yashab bo‘ladi. Aks holda hisobni tushuntirib bo‘lmasdi.

POST /v1/transcribe: qisqa va darhol

POST /v1/jobs bilan bir xil maydonlar, 5 daqiqagacha yozuvlar uchun. 200 javob bu natijaning o‘zi, vazifa identifikatori X-Job-Id sarlavhasida. 3 daqiqada natija tayyor bo‘lmasa, job_id bilan 202 keladi: keyin GET /v1/jobs/{id} orqali so‘rang.

So‘rov uchun sozlamalar

settings maydoni kabinetning «Sozlamalar» bo‘limidagi kalitlarni qabul qiladi; ko‘rsatilmaganlari loyihadan olinadi.

json
{
  "formatting": true,
  "itn": true,
  "word_timestamps": false,
  "stereo_channels_as_speakers": true,
  "diarization": true,
  "max_speakers": 2,
  "gender": true,
  "speaker_roles": true,
  "call_direction": "inbound",
  "speaker_identification": true,
  "emotion": false,
  "pii": false
}

webhook_url ham shu yerga qo‘yiladi, agar uni qolgan sozlamalar yonida saqlash qulay bo‘lsa; so‘rovning alohida maydoni bo‘lsa, u kuchliroq.

Kalitlar tekshiriladi: mavjud bo‘lmagani yuklashni 400 unknown_setting bilan rad etadi, maslahat esa uni nomma-nom aytadi. Ya’ni diarization o‘rniga diarisation — darhol xato, hisobdan oddiy matn kabi yechilgan oddiy matn emas.

Har bir kalit nima qiladi: Opsiyalar.

Loyiha lug‘ati

Kabinetdagi «Lug‘at» bo‘limidagi atamalarning o‘zi: kompaniya va mahsulot nomlari, ismlar. Sukut bo‘yicha ro‘yxat loyihaga tegishli: vazifa yaratilganda faol versiyaning nusxasini oladi, shuning uchun lug‘atni tahrirlash allaqachon yuborilgan ishni qayta yozmaydi. Alohida yozuv o‘z ro‘yxati bilan ham kelishi mumkin — quyida.

So‘rovNima qiladi
GET /v1/vocabularyFaol lug‘at: terms, version, updated_at, min_terms, max_terms
PUT /v1/vocabulary {"terms": [...]}Yangi versiyani saqlab, uni yoqadi; bo‘sh massiv lug‘atni olib tashlaydi
bash
curl -X PUT https://console.gapi.uz/v1/vocabulary \
     -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
     -d '{"terms": ["MetaSell", "Bitrix24", "amoCRM", "Toshkent"]}'

1 tadan 20 tagacha atama, har biri ko‘pi bilan 4 so‘z va 80 belgi. Takrorlar va bo‘sh satrlar indamay tashlab yuboriladi, tartib saqlanadi; takror harf katta-kichikligiga qaramay aniqlanadi, ya’ni «metasell» va «MetaSell» bitta atama va birinchisi qoladi. Ro‘yxat qanchalik qisqa bo‘lsa, model kerakli so‘zni shunchalik aniq topadi, shuning uchun faqat yozuvlaringizda haqiqatan yangraydiganini yozing. Xatolar: term_too_long, term_too_many_words, too_many_terms.

Har bir saqlash — yangi raqamlangan versiya va eng oxirgisi faol bo‘ladi, ya'ni noto‘g‘ri tahrir yo‘qotish emas, bir qadam orqaga. Versiyalar tarixi kabinetda ko‘rinadi.

Bitta so‘rov uchun lug‘at

Atamalar faqat shu yozuv uchun kerak bo‘lsa — birovning katalogini qayta ishlayapsiz yoki ro‘yxatni saqlashdan oldin sinab ko‘ryapsiz — ularni fayl bilan birga yuboring:

bash
curl -X POST https://console.gapi.uz/v1/jobs \
  -H "Authorization: Bearer $TOKEN" \
  -F file=@call.mp3 \
  -F 'vocabulary=["MetaSell", "Bitrix24", "amoCRM"]'

Ro‘yxat shu vazifa uchun va faqat shuning uchun loyiha lug‘atining o‘rnini bosadi: faol versiya o‘zgarmaydi, keyingi yozuv yana loyiha lug‘ati bilan ketadi. Bo‘sh massiv «bu yozuvni umuman lug‘atsiz hisobla» degani. Qoidalar va xato kodlari PUT dagidek, noto‘g‘ri atama esa vazifa paydo bo‘lishidan oldin yuklashni rad etadi.

JSON shaklidagi yuklashda maydon xuddi shunday ataladi: "vocabulary": [...]. Fayl so‘rov tanasi sifatida yuborilsa, lug‘at loyihadan olinadi. POST /v1/transcribe bu maydonni POST /v1/jobs bilan barobar qabul qiladi.

Nima qo‘llangani natijada ko‘rinadi: vocabulary_terms — vazifa nechta atama olgani, vocabulary_dropped — tozalashdan keyin bittasi ham qolmasa, true.

Loyiha ovozlari

So‘rovNima qiladi
GET /v1/speakersOvozlar ro‘yxati: id, number, name (ismsizlarda bo‘sh), voiceprints, shuningdek kind, seen_count, last_seen_at, expires_at, has_sample
POST /v1/speakers {"name"}Izsiz ovoz yaratish
PATCH /v1/speakers/{id} {"name"}Ism berish yoki o‘zgartirish
DELETE /v1/speakers/{id}Ovozni barcha izlari bilan o‘chirish
POST /v1/speakers/{id}/enrollTayyor yozuvdan iz qo‘shish: {"job_id", "speaker_index"} yoki {"job_id", "segment_indexes": [...]}
DELETE /v1/speakers/{id}/voiceprintsBarcha izlarni o‘chirish, ismni qoldirish
GET /v1/speakers/{id}/sampleBu ovoz eshitiladigan o‘n ikki soniyagacha audio (audio/wav; odatda qisqaroq — eng uzun replika olinadi). Bu ovozning saqlangan yozuvi bo‘lmasa 404 no_sample, yozuvning o‘zi saqlanmasa 410 audio_expired
DELETE /v1/speakers?kind=candidateBir turdagi barcha ovozlarni birdan o‘chirish: candidate, recurring yoki named

Batafsil: Ovozlar va so‘zlovchilar.

Foydalanish

GET /v1/usage g dagi balans va kunlik to‘ldirish maqsadini qaytaradi:

json
{"unit": "g", "balance_g": 203.63, "in_flight_g": 4.5, "available_g": 199.13, "topup_target_g": 240,
 "next_topup": "00:00 Asia/Tashkent", "day": "2026-09-09", "used_seconds": 3425.6, "remaining_seconds": 11947.8}

GET /v1/billing balans hamda to‘ldirish va yechishlar tarixini qaytaradi. Narx qanday hisoblanadi: Balans va to‘lov.

Webhooklar

Loyihada webhook_url berilgan yoki so‘rovda uzatilgan bo‘lsa, vazifa tugagach shu manzilga JSON bilan POST keladi:

json
{"event": "job.done", "id": "41f79b78-…", "state": "done", "class": "batch", "estimated_seconds": 283,
 "audio_seconds": 282.7, "error": null, "created_at": "…", "finished_at": "…",
 "result_url": "https://console.gapi.uz/v1/jobs/41f79b78-…/result"}

event bu job. va holat: job.done, job.failed, job.cancelled — bitta switch xatni ajratadi. audio_seconds bu hisobdan yechilgan yozuv uzunligi; yiqilgan vazifada u yo‘q.

Webhook vazifaning har qanday yakunida keladi, faqat muvaffaqiyatlisida emas: state done, failed va cancelled bo‘lishi mumkin, demak bekor qilingan yoki yiqilgan vazifa ham kutishni yopadi, sizning tomondagi taymaut esa faqat biz yeta olmagan holat uchun kerak.

Birinchi so‘rov vazifa tugagan zahoti ketadi: u fondagi ko‘rikni kutmaydi — vazifaning yakunlanishi yetkazishni o‘zi uyg‘otadi.

Istalgan 2xx bilan javob bering, javobga o‘n soniya beriladi. Har bir yetkazish o‘z ulanishini ochadi va uni yopadi: biz sizning tomoningizda ulanishni ushlab turmaymiz.

Xato bo‘lsa yetkazish 5 martagacha takrorlanadi, tanaffus esa oldingi urinishdan emas, vazifaning tugashidan hisoblanadi: u tugagach taxminan 30 s, 2 daq, 4.5 daq va 8 daq. Takroriy urinishlar daqiqada bir marta ko‘rib chiqiladi, shuning uchun bu sonlar taxminiy — birinchi so‘rovdan farqli o‘laroq.

O‘chirilgan vazifa webhook yubormaydi.

Limitlar

NimaQancha
Fayl hajmi200 MiB (209 715 200 bayt)
Yozuv uzunligi4 soatgacha
Sinxron so‘rov /v1/transcribe5 daqiqagacha yozuvlar
Bir tokenga daqiqasiga yuklashlar60
Bir tokenga daqiqasiga o‘qish so‘rovlari3000
Bir tokenga daqiqasiga boshqaruv so‘rovlari600
Natijani saqlash30 kun
Balanshar kuni Toshkent vaqti bilan yarim tunda 240 g gacha to‘ldiriladi
Hisobda loyihalar, loyihada tokenlar3, 10
Loyihada ovozlar, ovozda izlar500, 10
Lug‘atdagi atamalar1 dan 20 gacha

Yozuvni yuborish va u haqda so‘rash har xil turadi, shuning uchun limitlar ham har xil: yuklash modeli bor mashinani band qiladi, GET /v1/jobs/{id} esa bazadagi bitta qator. Holatni bemalol so‘rasa bo‘ladi — daqiqasiga 3000 ta bu o‘ttizta vazifa, sekundiga ikki so‘rovdan. Lekin GET /v1/jobs/{id}/events yoki webhook yaxshiroq: unda umuman so‘rash kerak emas.

Chelaklar uchta va alohida-alohida sanaladi. Yuklashlarga POST /v1/jobs va POST /v1/transcribe kiradi. Boshqaruvga — loyihani o‘zgartiradigan, lekin mashinani band qilmaydigan hammasi: ovozlar va lug‘at. Qolgani o‘qish.

429 javobida Retry-After sarlavhasi bor, unda soniyalar soni: oynada joy bo‘shashiga shuncha qoldi. Undan uzoq kutish shart emas, kamroq kutish esa foydasiz.

Bu jadvaldagi sonlar — sukut bo‘yicha qiymatlar, o‘zgarmas emas: to‘ldirish maqsadi, fayl hajmi, uzunlik va loyihadagi bir vaqtdagi vazifalar hisob uchun kelishuv bo‘yicha o‘zgaradi.

Oshib ketganda 429 keladi: rate_limited, insufficient_balance yoki too_many_active_jobs.

Xato kodlari

Kod error maydonida, yonida odam o‘qiydigan hint. Uch guruhni ajratgan ma’qul: so‘rovni tuzatish, kutib qayta urinish va endi qaytmaydigan.

So‘rov shu holida qabul qilinmaydi.

KodHTTPQachon
missing_token, invalid_token401Authorization sarlavhasi yo‘q, yoki token noto‘g‘ri yoki bekor qilingan
account_blocked403Hisob bloklangan; bizga yozing
file_required400multipart da file maydoni yo‘q
invalid_multipart, invalid_json400Tana tahlil qilinmaydi
invalid_url, fetch_failed400, 502Havola http(s) emas, tahlil qilinmaydi yoki undagi audio yuklanmadi
invalid_webhook_url400webhook_url http(s) emas
invalid_call_direction, invalid_max_speakers400Qiymat chegaradan tashqarida: yo‘nalish inbound, outbound yoki bo‘sh; spikerlar 4 tagacha
unknown_setting400settings da mavjud bo‘lmagan kalit; maslahat uni nomlaydi va bor kalitlarni sanaydi
upload_failed400So‘rov tanasi bo‘sh yoki o‘rtasida uzilgan
invalid_speaker_name400Ovoz nomi 1–120 belgidan tashqarida
missing_job_id400job_id siz enroll
speaker_index_out_of_range400Natijada bunday raqamli spiker yo‘q; maslahat nechtaligini aytadi
invalid_request400Qiymat bu ruchka kutgan shaklda emas
method_not_allowed405Shu manzil boshqa metodni qabul qiladi; u Allow sarlavhasida aytilgan
no_voiceprint422Bu spikerning izi yo‘q: «Ovozdan tanish» yoqilgan va kamida 3 soniya nutq kerak
insufficient_speech422Iz uchun 3 soniyadan kam nutq belgilangan
terms_required400terms siz PUT /v1/vocabulary
term_too_long, term_too_many_words, too_many_terms400Atama 80 belgidan uzun, 4 so‘zdan ko‘p, yoki atamalar 20 tadan ko‘p
audio_unreadable422Fayl dekodlanmaydi
audio_too_long422Yozuv 4 soatdan uzun
too_long_for_sync4225 daqiqadan uzun yozuv uchun /v1/transcribe; /v1/jobs dan foydalaning
file_too_large413200 MiB dan katta. Hajm Content-Length sarlavhasida ko‘rinsa, javob yuklash tugashini kutmay darhol keladi

Kutib, qayta urinish.

KodHTTPQachon
rate_limited429So‘rovlar juda ko‘p; Cheklovlar ga qarang
insufficient_balance429g dagi balans bu yozuvga yetmaydi; maslahat qancha borligi va to‘ldirish qachonligini aytadi
too_many_active_jobs429Loyihada navbatdagi va ishlayotgan vazifalar ruxsat etilgan darajaga yetdi
result_not_ready409Vazifa hali ketmoqda; GET /v1/jobs/{id} so‘rang yoki hodisalariga obuna bo‘ling
no_runner_for_diarization, no_runner_for_options503Kerakli modeli bor bo‘sh mashina yo‘q; keyinroq takrorlang
storage_full507Bizning tomonda joy tugadi; buni ko‘rib turibmiz

Endi qaytmaydi.

KodHTTPQachon
job_not_found404Bu loyihada bunday vazifa yo‘q — hech qachon bo‘lmagan, o‘chirilgan yoki id boshqa
speaker_not_found404Bu loyihada bunday ovoz yo‘q
job_result_not_found404enroll tayyor bo‘lmagan, bu loyihaga tegishli bo‘lmagan yoki o‘chirilgan vazifaga ishora qiladi
no_sample404Bu ovozning saqlangan yozuvi yo‘q
not_found404API da bunday manzil yo‘q
result_expired410Natija 30 kundan oshdi va o‘chirildi
audio_expired410Yozuvning o‘zi endi saqlanmaydi: ovoz namunasini eshittirib bo‘lmaydi

Alohida internal va 500: bu sizniki emas, bizning nosozligimiz. Bunday javobni takrorlash arziydi, agar u takrorlanaversa — bizga yozing, biz uni o‘z loglarimizda ko‘ramiz.

Noto‘g‘ri id — UUID emas, shablondan kelgan bo‘sh o‘zgaruvchi — bu 500 emas, 404: bunday vazifa shunchaki yo‘q.