Référence de l'API
Endpoints, champs, réponses, crédits, limites et erreurs.
Mis à jour le
Fonctionnement#
Chaque transcription est une tâche. Vous soumettez une source, la tâche s'exécute en arrière-plan et, lorsqu'elle réussit, elle renvoie vers une transcription que vous pouvez lire ou exporter autant de fois que vous le voulez. URL de base : https://www.transcriptdock.com. Toutes les requêtes et réponses sont au format 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"
Authentification#
Créez vos clés sur la page Clés API. Une clé n'est affichée qu'une seule fois, ressemble à td_live_... et va dans l'en-tête Authorization de chaque requête. Les clés ont des autorisations (scopes) choisies à la création : jobs:read, jobs:write, transcripts:read, uploads:write. Créez une clé par intégration afin de pouvoir la révoquer seule.
Authorization: Bearer td_live_YOUR_KEY
Idempotency-Key#
Obligatoire sur POST /v1/jobs, /v1/batches, /v1/jobs/{id}/retry, /v1/video-discoveries et /v1/language-discoveries : toute chaîne de 8 à 128 caractères ASCII imprimables. Envoyer la même clé avec le même corps dans les 48 heures renvoie l'objet d'origine. Une requête relancée ne crée ni ne facture donc jamais deux fois. La même clé avec un corps différent renvoie 409 IDEMPOTENCY_CONFLICT. Une bonne clé est votre propre identifiant de ce que vous transcrivez.
X-Request-Id#
Chaque réponse en contient un. Citez-le lorsque vous contactez l'assistance.
Endpoints#
| Méthode | Chemin | Ce qu'il fait | Crédits |
|---|---|---|---|
| POST | /v1/jobs | Transcrire une vidéo, un fichier ou un lien | 1 par transcription de sous-titres, 2 par minute de transcription par IA |
| GET | /v1/jobs/{id} | Statut de la tâche, attend jusqu'à 25 s | Gratuit |
| GET | /v1/jobs | Historique des tâches | Gratuit |
| POST | /v1/jobs/{id}/cancel | Annuler une tâche en file d'attente | Gratuit |
| POST | /v1/jobs/{id}/retry | Relancer une tâche échouée | Comme une nouvelle tâche |
| POST | /v1/batches | Transcrire plusieurs vidéos (taille de lot du forfait) | Par élément, comme ci-dessus |
| GET | /v1/batches/{id} | Statut du lot | Gratuit |
| GET | /v1/transcripts/{id} | Transcription au format JSON | Gratuit |
| GET | /v1/transcripts/{id}/export | Fichier txt, srt, vtt ou json | Gratuit |
| DELETE | /v1/transcripts/{id} | Supprimer une transcription | Gratuit |
| POST | /v1/uploads | Obtenir une URL pour envoyer un fichier | Gratuit |
| POST | /v1/uploads/{id}/complete | Marquer l'envoi comme terminé | Gratuit |
| POST | /v1/video-discoveries | Rechercher sur YouTube, lister une chaîne, une playlist ou un profil TikTok | 1 par page |
| GET | /v1/video-discoveries/{id} | Résultat de la recherche de vidéos | Gratuit |
| POST | /v1/language-discoveries | Lister les langues de sous-titres d'une vidéo YouTube | 1 |
| GET | /v1/language-discoveries/{id} | Liste des langues | Gratuit |
| POST | /v1/webhook-endpoints | Enregistrer une URL de webhook (session connectée) | Gratuit |
| GET | /v1/webhook-endpoints | Lister les URL de webhook | Gratuit |
| DELETE | /v1/webhook-endpoints/{id} | Désactiver une URL de webhook (session connectée) | Gratuit |
| GET | /v1/usage | Crédits et forfait | Gratuit |
| GET | /v1/capabilities | Ce que votre clé peut faire | Gratuit |
Créer une tâche#
/v1/jobsRenvoie 202 avec la tâche. Si votre espace de travail possède déjà une transcription de la même vidéo avec les mêmes options, renvoie 200 avec une tâche réussie, gratuitement (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"}
L'objet tâche#
Récupérer une tâche#
/v1/jobs/{id}?wait=25Renvoie la tâche. Avec wait (0 à 25 secondes), la requête reste ouverte et répond dès que la tâche est définitive. Un seul appel remplace ainsi une boucle d'interrogation. Les lectures ont leur propre limite, 120 par minute.
Lister les tâches#
/v1/jobs?limit=20&cursor=Les plus récentes d'abord, limit de 1 à 100. Passez le next_cursor de la réponse comme cursor pour obtenir la page suivante. Ajoutez platform et source_id (le source.media_id d'une tâche) ensemble pour ne voir que les tâches d'une seule vidéo, quel que soit le mode. C'est ainsi qu'un client vérifie qu'une transcription existe déjà dans l'espace de travail avant de soumettre à nouveau.
Annuler une tâche#
/v1/jobs/{id}/cancelAnnule une tâche qui n'a pas encore commencé la transcription par IA, et libère le blocage. Au-delà, l'API renvoie 409 CANCELLATION_NOT_ALLOWED et la tâche se termine.
Relancer une tâche#
/v1/jobs/{id}/retryCrée une nouvelle tâche à partir d'une tâche échouée dont l'erreur était retryable. Il faut une nouvelle Idempotency-Key ; corps facultatif { "max_credits": 40 }. Tarifée comme une nouvelle tâche. Les échecs définitifs (vidéo privée, absence de sous-titres) renvoient 409 JOB_NOT_RETRYABLE : corrigez l'entrée et soumettez à nouveau.
La transcription#
/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": "Never Gonna Give You Up" },"source_origin": "creator_captions","language": "en","text": "Welcome to this video. Today we cover the basics.","segments": [{ "start": 0, "end": 2.4, "text": "Welcome to this video" },{ "start": 2.4, "end": 4.9, "text": "Today we cover the basics" }],"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"}
Les transcriptions sont conservées pendant la durée de rétention de votre forfait : 7 jours pour l'essai, 30 pour Starter, 90 pour Pro et Scale. DELETE /v1/transcripts/{id} permet d'en supprimer une avant ce délai.
Exporter une transcription#
/v1/transcripts/{id}/export?format=srt| format | Vous obtenez |
|---|---|
| txt | Texte brut, un segment par ligne. |
| srt | Sous-titres SubRip. |
| vtt | Sous-titres WebVTT. |
| json | L'objet transcription ci-dessus. |
Gratuit et illimité. srt et vtt nécessitent des horodatages. Une transcription sans horodatages renvoie 422 TIMESTAMPS_UNAVAILABLE.
Lots#
/v1/batchesUne seule requête, plusieurs vidéos. Chaque élément a les mêmes champs que Créer une tâche. Le lot entier est accepté ou rejeté d'un bloc. Éléments par lot : 1 avec l'essai, 10 avec Starter, 25 avec Pro, 50 avec 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" }] }'
L'objet lot a un status (queued, processing, succeeded, partial_success, failed, cancelled), des compteurs (total_items, succeeded_items, failed_items, cancelled_items) et des items, chacun avec son job_id. Lisez-le avec GET /v1/batches/{id}. Chaque élément est une tâche normale.
Envoi de fichiers#
Votre propre audio ou vidéo (mp3, wav, m4a, ogg, aac, mp4, webm ; jusqu'à 250 Mo et 2 heures). Réservez un emplacement, envoyez le fichier à l'URL signée par une requête PUT, marquez-le comme terminé, puis soumettez-le comme tâche avec source.upload_id. Les envois utilisent toujours la transcription par IA.
# 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" }'
L'URL signée est valable 24 heures. Après ce délai, réservez un nouvel emplacement.
Webhooks#
/v1/webhook-endpointsEnregistrez une URL https et transmettez son id comme webhook_endpoint_id lors de la soumission. Nous envoyons un événement en POST lorsque la tâche ou le lot se termine. La réponse contient le secret de signature, une seule fois. L'enregistrement et la désactivation des endpoints nécessitent une session connectée : faites-le sur la page Webhooks du tableau de bord. Une clé API y reçoit 403 FORBIDDEN, mais elle peut lister les endpoints.
Événements#
{"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: récupérez ou exportezresult_id.job.failed:errorcontient le code.batch.completed: tous les éléments sont définitifs. Lisez le lot pour les résultats par élément.
Répondez par n'importe quel code 2xx en quelques secondes. Les livraisons en échec sont réessayées avec un délai croissant et peuvent être renvoyées depuis le tableau de bord. Un événement peut arriver plus d'une fois : dédoublonnez-le sur event_id.
Vérifier la signature#
En-têtes X-TranscriptDock-Event-Id, X-TranscriptDock-Timestamp et X-TranscriptDock-Signature. La signature est un HMAC-SHA256 (hexadécimal) de {event_id}.{timestamp}.{raw_body} avec votre secret. Rejetez tout événement datant de plus de cinq minutes.
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));}
Trouver des vidéos#
/v1/video-discoveriesRecherchez sur YouTube ou listez une chaîne, une playlist ou un profil TikTok, puis transmettez les URL à des tâches. Une recherche de vidéos s'exécute en arrière-plan, comme une tâche : lisez-la avec GET /v1/video-discoveries/{id} jusqu'à ce que status soit succeeded. 1 crédit par page ; les résultats sont conservés 24 heures.
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 }'
Le POST répond 202 avec status: "queued". Une fois terminée, GET /v1/video-discoveries/{id} ressemble à ceci :
{"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"}
Langues de sous-titres d'une vidéo#
/v1/language-discoveriesCorps { "source": { "url": "https://www.youtube.com/watch?v=..." } } avec une Idempotency-Key (YouTube uniquement, 1 crédit). Lisez GET /v1/language-discoveries/{id} pour obtenir la liste des pistes de sous-titres avec leurs codes, l'indication « créateur » ou « automatique » et la piste par défaut. Utilisez ces codes dans caption_languages.
Utilisation et capacités#
/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 exclut déjà credits_reserved (blocages des tâches en cours). prepaid_credits sont les crédits achetés, qui n'expirent jamais.
subscription est l'abonnement Stripe qui sous-tend un forfait payant, et null sans abonnement. Il indique son status, l'interval de facturation (monthly ou yearly), cancel_at_period_end et current_period_end, c'est-à-dire quand le forfait se renouvelle ou prend fin. period_end correspond au renouvellement des crédits mensuels, chaque mois, y compris sur les forfaits annuels.
/v1/capabilitiesCe que votre clé peut faire maintenant : pour chaque source (youtube, tiktok, instagram, upload, direct), les modes disponibles, ainsi que les limites et les tarifs. Lisez cette réponse au lieu de coder ces valeurs en dur. L'essai, par exemple, indique auto et transcribe à 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"}
Limites de requêtes#
| Forfait | Envois / min | Tâches en cours | Lectures / min |
|---|---|---|---|
| Essai | 10 | 10 | 120 |
| Starter | 60 | 100 | 120 |
| Pro | 120 | 500 | 120 |
| Scale | 300 | 2,000 | 120 |
Au-delà d'une limite, vous recevez 429 RATE_LIMITED avec un en-tête retry-after (en secondes) et details.detail qui nomme la limite. Rien n'est débité. Les webhooks et ?wait=25 vous tiennent loin de la limite de lecture.
Erreurs#
Toutes les erreurs ont la même forme. retryable: true signifie que la même requête peut réussir plus tard : attendez le nombre de secondes indiqué par retry-after s'il est présent, sinon patientez quelques secondes. Réutilisez ensuite la même Idempotency-Keypour qu'aucune tâche ne soit dupliquée. Pour toute autre erreur, il faut modifier votre côté de l'appel.
{"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"}
Une tâche qui échoue après avoir été acceptée reste en 200 sur GET /v1/jobs/{id}, avec status: "failed" et le même objet d'erreur dans error. Une tâche échouée ne coûte rien.
Codes#
| Code | HTTP | Nouvel essai | Signification et action à mener |
|---|---|---|---|
INVALID_REQUEST | 422 | Non | Un champ est absent ou a une mauvaise forme. details.detail le désigne. |
INVALID_URL | 422 | Non | L'URL n'est pas un lien https valide (2048 caractères au maximum). |
UNSUPPORTED_SOURCE | 422 | Non | Le lien n'est pas l'URL d'une vidéo YouTube ou TikTok. |
UNSAFE_URL | 422 | Non | Le lien média direct pointe vers une adresse réseau privée ou bloquée. |
INVALID_CURSOR | 422 | Non | Le curseur de recherche de vidéos a expiré ou est mal formé. Recommencez à partir de la première page. Un curseur de liste de tâches incorrect renvoie INVALID_REQUEST. |
CAPABILITY_UNAVAILABLE | 422 | Non | Ce mode n'est pas disponible pour cette source. GET /v1/capabilities indique ceux qui le sont. |
IDEMPOTENCY_CONFLICT | 409 | Non | Cette Idempotency-Key a déjà été utilisée avec un corps différent. Utilisez une nouvelle clé. |
UNAUTHENTICATED | 401 | Non | Aucune clé API ni jeton OAuth valide dans l'en-tête Authorization. |
FORBIDDEN | 403 | Non | La clé n'a pas l'autorisation (scope) requise pour cet endpoint, ou l'espace de travail est désactivé. |
EMAIL_UNVERIFIED | 403 | Non | Vérifiez l'adresse e-mail du compte avant d'utiliser l'API. |
NOT_FOUND | 404 | Non | Cet objet n'existe pas dans cet espace de travail. |
INSUFFICIENT_BALANCE | 402 | Non | Crédits insuffisants pour cette tâche. Achetez des crédits ou changez de forfait. |
PLAN_REQUIRED | 402 | Non | Cette fonction nécessite un forfait payant (transcription par IA, lots plus grands), ou les crédits d'essai sont épuisés. |
BUDGET_EXCEEDED | 402 | Non | Le coût mesuré dépasse max_credits. Rien n'a été débité : augmentez le plafond ou ignorez le média. |
JOB_NOT_RETRYABLE | 409 | Non | L'échec est définitif (vidéo privée, absence de sous-titres). Corrigez l'entrée et soumettez une nouvelle tâche. |
CANCELLATION_NOT_ALLOWED | 409 | Non | La transcription par IA a déjà commencé. La tâche va se terminer. |
RATE_LIMITED | 429 | Oui | Limite de débit ou de file d'attente dépassée. Attendez le nombre de secondes indiqué par retry-after. details.detail précise la limite concernée. |
SOURCE_NOT_FOUND | 422 | Non | La vidéo n'existe pas ou a été supprimée. |
SOURCE_PRIVATE | 422 | Non | La vidéo est privée. Seules les vidéos publiques fonctionnent. |
SOURCE_AUTH_REQUIRED | 422 | Non | La vidéo nécessite une connexion, une vérification d'âge ou un abonnement. |
SOURCE_REGION_RESTRICTED | 422 | Non | La vidéo est bloquée dans les régions depuis lesquelles nous la récupérons. |
NO_CAPTIONS | 422 | Non | Cette vidéo n'a pas de sous-titres et le mode était captions_only. Utilisez auto ou transcribe. |
LANGUAGE_UNAVAILABLE | 422 | Non | Aucune des langues de caption_languages n'existe pour cette vidéo. Retirez la liste pour prendre la piste par défaut. |
LANGUAGE_UNSUPPORTED | 422 | Non | La transcription par IA ne prend pas en charge la langue demandée. |
NO_SPEECH | 422 | Non | La transcription par IA n'a détecté aucune parole dans l'audio. |
NO_AUDIO | 422 | Non | Le média ne contient aucune piste audio. |
INVALID_MEDIA | 422 | Non | Le fichier n'a pas pu être lu comme un fichier audio ou vidéo. |
UNSUPPORTED_MEDIA | 422 | Non | Ce n'est pas un type de fichier audio ou vidéo. |
DURATION_LIMIT_EXCEEDED | 413 | Non | Durée supérieure à 2 heures. |
FILE_TOO_LARGE | 413 | Non | Taille supérieure à 250 Mo. |
TIMESTAMPS_UNAVAILABLE | 422 | Non | Cette transcription n'a pas d'horodatages, donc les exports srt et vtt ne sont pas disponibles. Utilisez txt ou json. |
PROVIDER_REJECTED | 422 | Non | Le modèle de transcription par IA n'a pas pu traiter cet audio. |
SOURCE_RATE_LIMITED | 503 | Oui | La plateforme source nous limite. La tâche se relance automatiquement. |
SOURCE_BLOCKED | 503 | Oui | La plateforme source a bloqué la récupération. La tâche se relance automatiquement. |
SOURCE_TIMEOUT | 503 | Oui | La plateforme source a dépassé le délai. La tâche se relance automatiquement. |
SOURCE_CHANGED | 503 | Oui | La source a changé pendant notre lecture. La tâche se relance automatiquement. |
PROVIDER_UNAVAILABLE | 503 | Oui | La transcription par IA est temporairement indisponible. La tâche se relance automatiquement. |
STORAGE_UNAVAILABLE | 503 | Oui | Le stockage des fichiers est temporairement indisponible. Relancez la requête. |
INTERNAL_ERROR | 500 | Oui | Erreur de notre côté. Relancez avec la même Idempotency-Key. Citez X-Request-Id si le problème persiste. |