Referensi API
Endpoint, kolom, respons, kredit, batas, dan kesalahan.
Diperbarui
Cara kerjanya#
Setiap transkrip dibuat lewat tugas. Anda mengirim sumber, tugas berjalan di latar belakang, dan jika berhasil, tugas itu menunjuk ke transkrip yang bisa Anda baca atau ekspor kapan saja. URL dasar: https://www.transcriptdock.com. Semua permintaan dan respons memakai JSON.
# 1. Submitcurl -X POST https://www.transcriptdock.com/v1/jobs \-H "Authorization: Bearer td_live_YOUR_KEY" \-H "Idempotency-Key: video-7680721699171601694" \-H "Content-Type: application/json" \-d '{ "source": { "url": "https://www.tiktok.com/@tiktok/video/7680721699171601694" }, "mode": "captions_only" }'# 2. Wait (returns as soon as the job finishes, up to 25 s per call)curl "https://www.transcriptdock.com/v1/jobs/11111111-1111-4111-8111-111111111111?wait=25" \-H "Authorization: Bearer td_live_YOUR_KEY"# 3. Exportcurl "https://www.transcriptdock.com/v1/transcripts/22222222-2222-4222-8222-222222222222/export?format=srt" \-H "Authorization: Bearer td_live_YOUR_KEY"
Autentikasi#
Buat kunci di halaman Kunci API. Kunci hanya ditampilkan sekali, berbentuk td_live_..., dan dimasukkan ke header Authorization pada setiap permintaan. Kunci memiliki cakupan akses yang dipilih saat dibuat: jobs:read, jobs:write, transcripts:read, uploads:write. Buat satu kunci untuk setiap integrasi agar Anda bisa mencabut satu kunci saja.
Authorization: Bearer td_live_YOUR_KEY
Idempotency-Key#
Wajib pada POST /v1/jobs, /v1/batches, /v1/jobs/{id}/retry, /v1/video-discoveries dan /v1/language-discoveries: berupa 8 sampai 128 karakter ASCII yang bisa dicetak. Mengirim kunci yang sama dengan isi yang sama dalam 48 jam akan mengembalikan objek asli, sehingga permintaan yang diulang tidak pernah membuat atau menagihkan dua kali. Kunci yang sama dengan isi berbeda mengembalikan 409 IDEMPOTENCY_CONFLICT. Kunci yang baik adalah ID Anda sendiri untuk hal yang sedang Anda transkripsi.
X-Request-Id#
Setiap respons menyertakannya. Sebutkan saat menghubungi dukungan.
Endpoint#
| Metode | Path | Fungsi | Kredit |
|---|---|---|---|
| POST | /v1/jobs | Transkripsi satu video, file, atau tautan | 1 per transkrip subtitle, 2 per menit transkripsi AI |
| GET | /v1/jobs/{id} | Status tugas, menunggu hingga 25 detik | Gratis |
| GET | /v1/jobs | Riwayat tugas | Gratis |
| POST | /v1/jobs/{id}/cancel | Batalkan tugas yang masih dalam antrean | Gratis |
| POST | /v1/jobs/{id}/retry | Coba lagi tugas yang gagal | Sebagai tugas baru |
| POST | /v1/batches | Transkripsi banyak video (sesuai ukuran batch paket) | Per item, seperti di atas |
| GET | /v1/batches/{id} | Status batch | Gratis |
| GET | /v1/transcripts/{id} | JSON transkrip | Gratis |
| GET | /v1/transcripts/{id}/export | File txt, srt, vtt, atau json | Gratis |
| DELETE | /v1/transcripts/{id} | Hapus transkrip | Gratis |
| POST | /v1/uploads | Dapatkan URL untuk mengunggah file | Gratis |
| POST | /v1/uploads/{id}/complete | Tandai unggahan selesai | Gratis |
| POST | /v1/video-discoveries | Cari di YouTube, daftar channel, playlist, atau profil TikTok | 1 per halaman |
| GET | /v1/video-discoveries/{id} | Hasil penemuan video | Gratis |
| POST | /v1/language-discoveries | Daftar bahasa subtitle video YouTube | 1 |
| GET | /v1/language-discoveries/{id} | Daftar bahasa | Gratis |
| POST | /v1/webhook-endpoints | Daftarkan URL webhook (dengan sesi masuk) | Gratis |
| GET | /v1/webhook-endpoints | Daftar URL webhook | Gratis |
| DELETE | /v1/webhook-endpoints/{id} | Nonaktifkan URL webhook (dengan sesi masuk) | Gratis |
| GET | /v1/usage | Kredit dan paket | Gratis |
| GET | /v1/capabilities | Apa yang bisa dilakukan kunci Anda | Gratis |
Buat tugas#
/v1/jobsMengembalikan 202 dengan tugasnya. Jika ruang kerja Anda sudah memiliki transkrip untuk video dan opsi yang sama, endpoint mengembalikan 200 dengan tugas yang sudah berhasil tanpa biaya (billing.kind: "cached").
{"id": "11111111-1111-4111-8111-111111111111","status": "queued","stage": "resolve","result_id": null,"error": null,"billing": { "credits_reserved": 2, "credits_charged": 0, "kind": "captions" },"source": { "platform": "tiktok", "media_id": "7680721699171601694", "canonical_url": "https://www.tiktok.com/@tiktok/video/7680721699171601694", "title": null, "upload_id": null },"options": { "mode": "auto", "language": null, "caption_preference": "prefer_creator" },"created_at": "2026-09-16T10:00:00.000Z"}
Objek tugas#
Ambil tugas#
/v1/jobs/{id}?wait=25Mengembalikan tugas. Dengan wait (0 sampai 25 detik), permintaan tetap terbuka dan kembali segera setelah tugas final, sehingga satu panggilan menggantikan loop polling. Pembacaan memiliki batas sendiri, yaitu 120 per menit.
Daftar tugas#
/v1/jobs?limit=20&cursor=Dari yang terbaru, limit 1 sampai 100. Kirim next_cursor dari respons sebagai cursor untuk halaman berikutnya. Tambahkan platform dan source_id (source.media_id sebuah tugas) bersama-sama untuk hanya melihat tugas untuk satu video, dalam mode apa pun. Dengan cara itulah klien memeriksa apakah ruang kerja sudah memiliki transkrip sebelum mengirim ulang.
Batalkan tugas#
/v1/jobs/{id}/cancelMembatalkan tugas yang belum mulai transkripsi AI; penahanan kredit dilepas. Setelah itu, endpoint mengembalikan 409 CANCELLATION_NOT_ALLOWED dan tugas akan diselesaikan.
Ulangi tugas#
/v1/jobs/{id}/retryMembuat tugas baru dari tugas yang gagal dengan error retryable. Memerlukan Idempotency-Key baru; body opsional { "max_credits": 40 }. Harganya sama seperti tugas baru. Kegagalan yang final (video privat, tidak ada subtitle) mengembalikan 409 JOB_NOT_RETRYABLE: perbaiki input lalu kirim ulang.
Transkrip#
/v1/transcripts/{id}{"id": "22222222-2222-4222-8222-222222222222","source": { "platform": "youtube", "media_id": "dQw4w9WgXcQ", "canonical_url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ", "title": "Sample video" },"source_origin": "creator_captions","language": "en","text": "This is the first caption. This is the second caption.","segments": [{ "start": 0, "end": 2.4, "text": "This is the first caption" },{ "start": 2.4, "end": 4.9, "text": "This is the second caption" }],"words": null,"timing_granularity": "segment","duration_seconds": 212.0,"recognition": null,"extraction_version": "worker-0.1.0","created_at": "2026-09-16T10:00:14.000Z"}
Transkrip disimpan selama masa retensi paket Anda (7 hari untuk uji coba, 30 untuk Starter, 90 untuk Pro dan Scale). DELETE /v1/transcripts/{id} menghapus satu transkrip lebih awal.
Ekspor transkrip#
/v1/transcripts/{id}/export?format=srt| format | Yang Anda dapatkan |
|---|---|
| txt | Teks biasa, satu segmen per baris. |
| srt | Subtitle SubRip. |
| vtt | Subtitle WebVTT. |
| json | Objek transkrip di atas. |
Gratis, tanpa batas. srt dan vtt memerlukan waktu; transkrip tanpa waktu mengembalikan 422 TIMESTAMPS_UNAVAILABLE.
Batch#
/v1/batchesSatu permintaan, banyak video. Setiap item memiliki kolom yang sama dengan Buat tugas; seluruh batch diterima atau ditolak bersama. Item per batch: 1 untuk uji coba, 10 untuk Starter, 25 untuk Pro, 50 untuk Scale.
curl -X POST https://www.transcriptdock.com/v1/batches \-H "Authorization: Bearer td_live_YOUR_KEY" \-H "Idempotency-Key: playlist-2026-09-16" \-H "Content-Type: application/json" \-d '{ "items": [{ "source": { "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ" }, "mode": "captions_only" },{ "source": { "url": "https://www.tiktok.com/@tiktok/video/7680721699171601694" }, "mode": "captions_only" }] }'
Objek batch memiliki status (queued, processing, succeeded, partial_success, failed, cancelled), jumlah (total_items, succeeded_items, failed_items, cancelled_items) dan items, masing-masing dengan job_id-nya. Bacalah dengan GET /v1/batches/{id}; setiap item adalah tugas biasa.
Unggahan#
Audio atau video Anda sendiri (mp3, wav, m4a, ogg, aac, mp4, webm; hingga 250 MB dan 2 jam). Pesan slot unggahan, PUT file ke URL bertanda tangan, tandai selesai, lalu kirim sebagai tugas dengan source.upload_id. Unggahan selalu memakai transkripsi AI.
# 1. Reservecurl -X POST https://www.transcriptdock.com/v1/uploads \-H "Authorization: Bearer td_live_YOUR_KEY" \-H "Content-Type: application/json" \-d '{ "filename": "interview.mp3", "content_type": "audio/mpeg", "bytes": 48213920 }'# -> { "id": "33333333-...", "signed_upload_url": "https://...", "expires_at": "...", "status": "pending" }# 2. Upload the bytes (same Content-Type you declared)curl -X PUT "SIGNED_UPLOAD_URL" -H "Content-Type: audio/mpeg" --data-binary @interview.mp3# 3. Completecurl -X POST https://www.transcriptdock.com/v1/uploads/33333333-3333-4333-8333-333333333333/complete \-H "Authorization: Bearer td_live_YOUR_KEY"# 4. Transcribe itcurl -X POST https://www.transcriptdock.com/v1/jobs \-H "Authorization: Bearer td_live_YOUR_KEY" \-H "Idempotency-Key: interview-01" \-H "Content-Type: application/json" \-d '{ "source": { "upload_id": "33333333-3333-4333-8333-333333333333" }, "mode": "transcribe" }'
URL bertanda tangan berlaku 24 jam; pesan slot baru setelah itu.
Webhook#
/v1/webhook-endpointsDaftarkan URL https dan kirim id-nya sebagai webhook_endpoint_id saat Anda mengirim. Kami mengirim POST berisi event saat tugas atau batch selesai. Respons menyertakan secret penandatanganan sekali saja. Mendaftarkan dan menonaktifkan endpoint memerlukan sesi masuk, jadi lakukan di halaman Webhook pada dasbor; kunci API mendapat 403 FORBIDDEN di sana, tetapi tetap bisa melihat daftar endpoint.
Event#
{"event_id": "44444444-4444-4444-8444-444444444444","type": "job.succeeded","created_at": "2026-09-16T10:00:14.000Z","job_id": "11111111-1111-4111-8111-111111111111","batch_id": null,"result_id": "22222222-2222-4222-8222-222222222222","metadata": { "order": "8812" },"error": null}
job.succeeded: ambil atau eksporresult_id.job.failed:errorberisi kodenya.batch.completed: semua item sudah final; baca batch untuk hasil per item.
Balas dengan 2xx apa pun dalam beberapa detik. Pengiriman yang gagal dicoba lagi dengan jeda yang makin lama dan bisa dikirim ulang dari dasbor. Sebuah event bisa datang lebih dari sekali: buang duplikat berdasarkan event_id.
Verifikasi tanda tangan#
Header X-TranscriptDock-Event-Id, X-TranscriptDock-Timestamp dan X-TranscriptDock-Signature. Tanda tangan berupa HMAC-SHA256 (hex) dari {event_id}.{timestamp}.{raw_body} dengan secret Anda. Tolak apa pun yang lebih dari lima menit.
import crypto from "node:crypto";export function verify(eventId: string, timestamp: string, rawBody: string, signature: string, secret: string): boolean {if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;const expected = crypto.createHmac("sha256", secret).update(`${eventId}.${timestamp}.${rawBody}`).digest("hex");return expected.length === signature.length && crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));}
Cari video#
/v1/video-discoveriesCari di YouTube atau daftar channel, playlist, atau profil TikTok, lalu masukkan URL-nya ke tugas. Penemuan berjalan di latar belakang seperti tugas: baca dengan GET /v1/video-discoveries/{id} sampai status bernilai succeeded. 1 kredit per halaman; hasil disimpan selama 24 jam.
curl -X POST https://www.transcriptdock.com/v1/video-discoveries \-H "Authorization: Bearer td_live_YOUR_KEY" \-H "Idempotency-Key: search-async-rust-1" \-H "Content-Type: application/json" \-d '{ "kind": "youtube_search", "query": "async rust", "limit": 5 }'
POST menjawab 202 dengan status: "queued". Respons GET /v1/video-discoveries/{id} yang sudah selesai terlihat seperti ini:
{"id": "55555555-5555-4555-8555-555555555555","kind": "youtube_search","status": "succeeded","request": { "kind": "youtube_search", "query": "async rust", "limit": 5 },"videos": [{"platform": "youtube","video_id": "wXtngLBkK4Q","url": "https://www.youtube.com/watch?v=wXtngLBkK4Q","title": "Async Rust explained in 20 minutes","channel_id": "UCSp-OaMpsO8K0KkOqyBl7_w","channel_title": "Let's Get Rusty","duration_s": 1155,"published_at": null,"published_text": "5 months ago","view_count": 83635,"view_count_text": "83,635 views","thumbnail_url": "https://i.ytimg.com/vi/wXtngLBkK4Q/hq720.jpg","tiktok": null}],"profile": null,"next_cursor": "opaque-token","error": null,"created_at": "2026-09-16T12:00:00.000Z","updated_at": "2026-09-16T12:00:03.000Z","expires_at": "2026-09-17T12:00:00.000Z"}
Bahasa subtitle video#
/v1/language-discoveriesIsi { "source": { "url": "https://www.youtube.com/watch?v=..." } } dengan Idempotency-Key (khusus YouTube, 1 kredit). Baca GET /v1/language-discoveries/{id} untuk daftar trek subtitle beserta kodenya, apakah dari kreator atau otomatis, dan default-nya. Gunakan kodenya di caption_languages.
Penggunaan dan kemampuan#
/v1/usage{"plan": "pro","period_end": "2026-10-16T00:00:00.000Z","credits_remaining": 5840,"credits_total": 6000,"credits_reserved": 4,"prepaid_credits": 0,"transcribe_credits_per_minute": 2,"minimum_billable_seconds": 60,"subscription": {"status": "active","interval": "yearly","cancel_at_period_end": false,"current_period_end": "2027-09-16T00:00:00.000Z"}}
credits_remaining sudah tidak termasuk credits_reserved (penahanan untuk tugas yang berjalan). prepaid_credits adalah kredit yang dibeli dan tidak pernah kedaluwarsa.
subscription adalah langganan Stripe di balik paket berbayar dan null jika tidak ada: status-nya, interval penagihan (monthly atau yearly), cancel_at_period_end, dan current_period_end, saat paket diperpanjang atau berakhir. period_end adalah saat kredit bulanan diperbarui, setiap bulan termasuk pada paket tahunan.
/v1/capabilitiesApa yang bisa dilakukan kunci Anda saat ini: untuk setiap sumber (youtube, tiktok, instagram, upload, direct) mode mana yang tersedia, beserta batas dan harga. Baca ini daripada menuliskannya langsung di kode; misalnya, uji coba melaporkan auto dan transcribe sebagai false.
{"youtube": { "enabled": true, "captions_only": true, "auto": true, "transcribe": true, "social_acquisition_fee": true },"tiktok": { "enabled": true, "captions_only": true, "auto": true, "transcribe": true, "social_acquisition_fee": true },"instagram": { "enabled": false, "captions_only": false, "auto": false, "transcribe": false, "social_acquisition_fee": true, "native_captions": "unverified_disabled" },"upload": { "enabled": true, "captions_only": false, "auto": true, "transcribe": true, "social_acquisition_fee": false },"direct": { "enabled": true, "captions_only": false, "auto": true, "transcribe": true, "social_acquisition_fee": false },"max_duration_ms": 7200000,"max_media_bytes": 262144000,"export_formats": ["txt", "json", "srt", "vtt"],"recognition_profiles": ["standard"],"transcribe_credits_per_minute": 2,"minimum_billable_seconds": 60,"price_version": "2026-09-14","asr_enabled": true,"instagram_enabled": false,"free_caption_credits": 50,"free_caption_credits_period": "month"}
Batas laju#
| Paket | Pengiriman / menit | Tugas yang berjalan | Pembacaan / menit |
|---|---|---|---|
| Uji coba | 10 | 10 | 120 |
| Starter | 60 | 100 | 120 |
| Pro | 120 | 500 | 120 |
| Scale | 300 | 2,000 | 120 |
Jika melebihi batas, Anda mendapat 429 RATE_LIMITED dengan header retry-after (detik) dan details.detail yang menyebut batasnya. Tidak ada yang ditagihkan. Webhook dan ?wait=25 membuat Anda jauh dari batas pembacaan.
Kesalahan#
Setiap kesalahan memiliki bentuk yang sama. retryable: true berarti permintaan yang sama bisa berhasil nanti: tunggu retry-after detik jika ada, jika tidak, tunggu beberapa detik, dan gunakan Idempotency-Key yang sama agar tidak ada yang terduplikasi. Kesalahan lain memerlukan perubahan di sisi Anda.
{"error": {"code": "INSUFFICIENT_BALANCE","message": "Not enough credits. Buy credits or upgrade your plan to continue.","retryable": false,"details": { "detail": "This job needs more credits than you have left. Buy credits or upgrade your plan." },"doc_url": "https://www.transcriptdock.com/docs/api-reference#error-codes"},"request_id": "66666666-6666-4666-8666-666666666666"}
Tugas yang gagal setelah diterima tetap 200 di GET /v1/jobs/{id}, dengan status: "failed" dan objek error yang sama di error. Tidak ada yang ditagihkan untuk tugas yang gagal.
Kode#
| Kode | HTTP | Coba lagi | Arti dan tindakan |
|---|---|---|---|
INVALID_REQUEST | 422 | Tidak | Ada kolom yang hilang atau bentuknya salah. details.detail menyebut kolomnya. |
INVALID_URL | 422 | Tidak | URL bukan tautan https yang valid (maks. 2048 karakter). |
UNSUPPORTED_SOURCE | 422 | Tidak | Tautan bukan URL video YouTube atau TikTok. |
UNSAFE_URL | 422 | Tidak | Tautan media langsung mengarah ke alamat jaringan privat atau yang diblokir. |
INVALID_CURSOR | 422 | Tidak | Kursor penemuan video sudah kedaluwarsa atau rusak. Mulai lagi dari halaman pertama. Kursor daftar tugas yang rusak mengembalikan INVALID_REQUEST. |
CAPABILITY_UNAVAILABLE | 422 | Tidak | Mode ini tidak tersedia untuk sumber ini. GET /v1/capabilities menunjukkan mode yang tersedia. |
IDEMPOTENCY_CONFLICT | 409 | Tidak | Idempotency-Key ini sudah dipakai dengan isi yang berbeda. Gunakan kunci baru. |
UNAUTHENTICATED | 401 | Tidak | Tidak ada kunci API atau token OAuth yang valid di header Authorization. |
FORBIDDEN | 403 | Tidak | Kunci tidak punya cakupan akses untuk endpoint ini, atau ruang kerja dinonaktifkan. |
EMAIL_UNVERIFIED | 403 | Tidak | Verifikasi email akun sebelum menggunakan API. |
NOT_FOUND | 404 | Tidak | Objek tidak ditemukan di ruang kerja ini. |
INSUFFICIENT_BALANCE | 402 | Tidak | Kredit tidak cukup untuk tugas ini. Beli kredit atau tingkatkan paket. |
PLAN_REQUIRED | 402 | Tidak | Ini memerlukan paket berbayar (transkripsi AI, batch yang lebih besar) atau kredit uji coba sudah habis. |
BUDGET_EXCEEDED | 402 | Tidak | Biaya yang terukur melebihi max_credits. Tidak ada yang ditagihkan; naikkan batasnya atau lewati media ini. |
JOB_NOT_RETRYABLE | 409 | Tidak | Kegagalannya bersifat final (video privat, tidak ada subtitle). Perbaiki input lalu kirim tugas baru. |
CANCELLATION_NOT_ALLOWED | 409 | Tidak | Transkripsi AI sudah dimulai; tugas akan selesai. |
RATE_LIMITED | 429 | Ya | Melebihi batas laju atau batas antrean. Tunggu sesuai retry-after; details.detail menyebut batas mana yang terlampaui. |
SOURCE_NOT_FOUND | 422 | Tidak | Video tidak ada atau sudah dihapus. |
SOURCE_PRIVATE | 422 | Tidak | Video bersifat privat. Hanya video publik yang bisa diproses. |
SOURCE_AUTH_REQUIRED | 422 | Tidak | Video memerlukan login, verifikasi usia, atau keanggotaan. |
SOURCE_REGION_RESTRICTED | 422 | Tidak | Video diblokir di wilayah tempat kami mengambil data. |
NO_CAPTIONS | 422 | Tidak | Video ini tidak punya subtitle dan mode-nya captions_only. Gunakan auto atau transcribe. |
LANGUAGE_UNAVAILABLE | 422 | Tidak | Tidak ada bahasa dalam caption_languages yang tersedia di video ini. Hapus daftarnya untuk memakai trek default. |
LANGUAGE_UNSUPPORTED | 422 | Tidak | Transkripsi AI tidak mendukung bahasa yang diminta. |
NO_SPEECH | 422 | Tidak | Transkripsi AI tidak menemukan ucapan dalam audio. |
NO_AUDIO | 422 | Tidak | Media tidak punya trek audio. |
INVALID_MEDIA | 422 | Tidak | File tidak dapat dibaca sebagai audio atau video. |
UNSUPPORTED_MEDIA | 422 | Tidak | Jenis file ini bukan audio atau video. |
DURATION_LIMIT_EXCEEDED | 413 | Tidak | Lebih panjang dari 2 jam. |
FILE_TOO_LARGE | 413 | Tidak | Lebih besar dari 250 MB. |
TIMESTAMPS_UNAVAILABLE | 422 | Tidak | Transkrip ini tidak punya waktu, sehingga ekspor srt dan vtt tidak tersedia. Gunakan txt atau json. |
PROVIDER_REJECTED | 422 | Tidak | Model transkripsi AI tidak dapat memproses audio ini. |
SOURCE_RATE_LIMITED | 503 | Ya | Platform sumber membatasi permintaan kami. Tugas akan mencoba lagi secara otomatis. |
SOURCE_BLOCKED | 503 | Ya | Platform sumber memblokir pengambilan data. Tugas akan mencoba lagi secara otomatis. |
SOURCE_TIMEOUT | 503 | Ya | Platform sumber kehabisan waktu. Tugas akan mencoba lagi secara otomatis. |
SOURCE_CHANGED | 503 | Ya | Sumber berubah saat kami membacanya. Tugas akan mencoba lagi secara otomatis. |
PROVIDER_UNAVAILABLE | 503 | Ya | Transkripsi AI sedang tidak tersedia. Tugas akan mencoba lagi secara otomatis. |
STORAGE_UNAVAILABLE | 503 | Ya | Penyimpanan file sedang tidak tersedia. Coba lagi permintaannya. |
INTERNAL_ERROR | 500 | Ya | Kesalahan dari sisi kami. Coba lagi dengan Idempotency-Key yang sama; sebutkan X-Request-Id jika masih berulang. |