Développer avec une API de transcription : première intégration
apidéveloppeurstutoriel

Développer avec une API de transcription : première intégration

BMMamane B. MoussaMay 26, 2026Updated July 2, 202611 min read

Summarize this article with:

L'intégration en cinq étapes

Vous pouvez ajouter la transcription à n'importe quel backend en moins d'une heure : obtenez une clé API, envoyez l'audio en POST (par upload de fichier ou par URL), interrogez ou recevez un webhook à l'achèvement, récupérez le résultat et exportez-le dans le format dont vous avez besoin. Les modèles présentés ici sont illustrés avec l'API ConvertAudioToText, mais le schéma « soumettre puis interroger » est standard chez tous les fournisseurs de transcription asynchrone. Si vous hésitez encore entre plusieurs fournisseurs, consultez d'abord le comparatif des API de transcription 2026.

Les cinq étapes sont : s'authentifier, soumettre une tâche, récupérer le résultat, gérer les erreurs et exporter. Chaque section ci-dessous couvre une étape avec du code prêt à exécuter.

Étape 1 : Obtenir une clé API

L'accès à l'API sur ConvertAudioToText nécessite l'abonnement Business. Dans le tableau de bord, allez dans Paramètres, puis Clés API, puis créez une nouvelle clé. Donnez-lui un nom descriptif lié à l'intégration ("production-backend", "staging-ingest"). La clé n'est affichée qu'une seule fois, copiez-la donc immédiatement.

Format de la clé : ck_live_ suivi de 64 caractères hexadécimaux. Traitez-la comme un mot de passe. Stockez-la dans une variable d'environnement, jamais dans votre gestionnaire de versions.

Chaque requête utilise Authorization: Bearer <key> :

curl https://api.convertaudiototext.com/api/v1/result/some-job-id \
  -H "Authorization: Bearer ck_live_..."

En Node.js :

const headers = { 'Authorization': `Bearer ${process.env.CATT_API_KEY}` };

En Python :

headers = {'Authorization': f'Bearer {os.environ["CATT_API_KEY"]}'}

Étape 2 : Soumettre une tâche de transcription

Le point de terminaison est POST /api/v1/transcribe. Il renvoie immédiatement un HTTP 201 accompagné d'un job_id ; la transcription elle-même est asynchrone.

Deux voies de soumission existent : l'upload de fichier et l'URL. Elles renvoient la même forme de réponse.

Upload de fichier

Utilisez cette voie lorsque l'audio est local ou lorsque vos utilisateurs vous l'envoient sous forme d'upload multipart.

import FormData from 'form-data';
import { createReadStream } from 'fs';
import fetch from 'node-fetch';

async function submitFileJob(filePath, language = 'en') {
  const form = new FormData();
  form.append('source', 'upload');
  form.append('language', language);
  form.append('file', createReadStream(filePath));

  const res = await fetch('https://api.convertaudiototext.com/api/v1/transcribe', {
    method: 'POST',
    headers: { 'Authorization': `Bearer ${process.env.CATT_API_KEY}` },
    body: form
  });

  if (!res.ok) throw new Error(`Échec de la soumission : ${res.status}`);
  const { job_id, status } = await res.json();
  return { job_id, status };
}

Soumission par URL

Utilisez cette voie lorsque l'audio se trouve déjà dans un stockage cloud (S3, R2, GCS ou toute URL HTTPS publique). Le serveur télécharge à haut débit depuis l'origine, ce qui est plus rapide que de réuploader depuis votre machine.

async function submitURLJob(audioURL, language = 'en') {
  const res = await fetch('https://api.convertaudiototext.com/api/v1/transcribe', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.CATT_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      source: 'url',
      input_url: audioURL,
      language: language
    })
  });

  if (!res.ok) throw new Error(`Échec de la soumission : ${res.status}`);
  const { job_id, status } = await res.json();
  return { job_id, status };
}

Les deux renvoient { job_id: "uuid-string", status: "queued" }.

Outil d'upload audio de ConvertAudioToText
Outil d'upload audio de ConvertAudioToText

L'outil d'upload audio propulsé par l'API. Le même pipeline de traitement s'exécute que vous utilisiez l'interface web ou l'API.

Étape 3 : Récupérer le résultat

Une tâche terminée est disponible via GET /api/v1/result/{job_id}. Deux approches pour attendre : le polling et les webhooks.

Polling

Interrogez toutes les 5 secondes jusqu'à ce que status soit "completed" ou "failed". Le point de terminaison répond instantanément ; le délai vient entièrement du côté de la transcription.

async function pollForResult(jobId, maxWaitMs = 600000) {
  const start = Date.now();

  while (Date.now() - start < maxWaitMs) {
    const res = await fetch(
      `https://api.convertaudiototext.com/api/v1/result/${jobId}`,
      { headers: { 'Authorization': `Bearer ${process.env.CATT_API_KEY}` } }
    );
    const data = await res.json();

    if (data.status === 'completed') return data;
    if (data.status === 'failed') throw new Error(data.error || 'Tâche échouée');

    await new Promise(r => setTimeout(r, 5000));
  }

  throw new Error('Délai dépassé en attendant le résultat de la transcription');
}

N'interrogez pas plus vite qu'une fois par seconde et par tâche. La limite globale est de 100 requêtes par minute et par IP ; une boucle serrée sur de nombreuses tâches finira donc par la déclencher.

Webhooks

Pour une meilleure utilisation des ressources à grande échelle, les webhooks remplacent entièrement le polling. Enregistrez une URL de webhook une seule fois :

curl -X POST https://api.convertaudiototext.com/api/v1/dashboard/webhooks \
  -H "Authorization: Bearer $CATT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.com/webhooks/transcription",
    "events": ["job.completed", "job.failed"]
  }'

La réponse contient un champ secret. Conservez-le. Le serveur enverra une requête POST à votre URL à chaque événement correspondant. La charge utile ressemble à ceci :

{
  "event": "job.completed",
  "timestamp": "2026-07-01T14:22:05Z",
  "data": {
    "job_id": "550e8400-e29b-41d4-a716-446655440000",
    "status": "completed",
    "duration": 1842,
    "result_url": "https://api.convertaudiototext.com/api/v1/result/550e8400-...",
    "completed_at": "2026-07-01T14:22:04Z"
  }
}

Vérifiez chaque livraison avec HMAC-SHA256. Le serveur envoie la signature dans X-Webhook-Signature sous la forme sha256=<hex> :

import crypto from 'crypto';

function verifyWebhookSignature(rawBody, signature, secret) {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signature)
  );
}

// Dans votre gestionnaire Express/Fastify :
app.post('/webhooks/transcription', express.raw({ type: 'application/json' }), (req, res) => {
  const sig = req.headers['x-webhook-signature'];
  if (!verifyWebhookSignature(req.body, sig, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('Signature invalide');
  }

  const { event, data } = JSON.parse(req.body);
  if (event === 'job.completed') {
    // récupérer la transcription complète depuis data.result_url
  }
  res.status(200).end();
});

Les webhooks nécessitent l'abonnement Business et une URL HTTPS publiquement accessible. Pour une comparaison plus approfondie des deux approches, consultez le guide webhook vs polling pour les transcriptions.

Étape 4 : Analyser le résultat

La réponse d'une tâche terminée imbrique la transcription sous une clé transcript. La forme exacte est contrôlée par le formateur côté serveur, mais les champs que vous trouverez toujours sont :

{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "completed",
  "language": "en",
  "duration": 1842,
  "filename": "interview.mp3",
  "transcript": {
    "text": "Bonjour, bienvenue dans l'émission...",
    "summary": "Une interview à propos...",
    "confidence": 0.97,
    "word_count": 4210,
    "timeline": [
      {
        "speaker": "Intervenant 0",
        "text": "Bonjour, bienvenue dans l'émission.",
        "start": 0.12,
        "end": 1.87
      }
    ],
    "topics": [...],
    "sentiments": [...]
  }
}

Le champ text contient la transcription complète concaténée. Le tableau timeline vous donne les énoncés attribués à chaque intervenant avec leur horodatage. Les champs summary, topics et sentiments sont renseignés pour l'audio en anglais sur les offres incluant les insights IA ; ils seront supprimés ou absents sur l'offre Starter.

Étape 5 : Formats d'export

Téléchargez les fichiers formatés via :

curl "https://api.convertaudiototext.com/api/v1/result/$JOB_ID/srt" \
  -H "Authorization: Bearer $CATT_API_KEY" > captions.srt  # SRT pour les sous-titres vidéo

curl "https://api.convertaudiototext.com/api/v1/result/$JOB_ID/vtt" \
  -H "Authorization: Bearer $CATT_API_KEY" > captions.vtt  # WebVTT

curl "https://api.convertaudiototext.com/api/v1/result/$JOB_ID/txt" \
  -H "Authorization: Bearer $CATT_API_KEY" > transcript.txt  # Texte brut avec étiquettes d'intervenants

curl "https://api.convertaudiototext.com/api/v1/result/$JOB_ID/json" \
  -H "Authorization: Bearer $CATT_API_KEY" > transcript.json  # JSON structuré

curl "https://api.convertaudiototext.com/api/v1/result/$JOB_ID/docx" \
  -H "Authorization: Bearer $CATT_API_KEY" > transcript.docx  # DOCX

Tous les points de terminaison d'export nécessitent un abonnement payant. Les requêtes du niveau gratuit renvoient HTTP 402 avec un champ upgrade_url. Pour construire des workflows de sous-titrage à grande échelle, les points de terminaison SRT et VTT fonctionnent bien dans des pipelines par lots.

Gestion des erreurs

Trois catégories d'erreurs à gérer, chacune avec une stratégie de récupération différente.

Les erreurs 4xx viennent de votre bug. Authentification incorrecte (401), champs requis manquants (400), quota épuisé (402) ou limite de débit atteinte (429). Ne réessayez pas sans corriger la requête. Sur un 429, lisez le champ retry_after dans le corps de la réponse.

Les erreurs 5xx sont transitoires. Réessayez avec un backoff exponentiel. La plupart disparaissent en moins de 30 secondes.

Échecs au niveau de la tâche. Une tâche peut être soumise avec succès (HTTP 201) puis échouer plus tard pendant le traitement. status passe alors à "failed" et error indique la raison. Causes fréquentes : audio corrompu, enregistrements silencieux du début à la fin, codecs non pris en charge. Ne relancez la tâche que si la source audio est valide.

async function transcribeWithRetry(audioPath, maxAttempts = 3) {
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
    try {
      const { job_id } = await submitFileJob(audioPath);
      return await pollForResult(job_id);
    } catch (err) {
      // 4xx : corriger la requête, ne pas réessayer
      if (err.status >= 400 && err.status <= 499) throw err;
      // Dernière tentative : abandonner
      if (attempt === maxAttempts - 1) throw err;
      // 5xx : attendre puis réessayer
      const delayMs = 1000 * Math.pow(2, attempt);
      await new Promise(r => setTimeout(r, delayMs));
    }
  }
}

Limites de débit

Les limites qui s'appliquent aux requêtes API authentifiées :

CoucheLimitePérimètre
Globale100 requêtes/minPar adresse IP
Tâches de transcription10 soumissions/minPar utilisateur authentifié
Upload multipart (appels de signature)1000/minPar IP, plafond distinct

La limite de tâches de transcription signifie que vous pouvez soumettre jusqu'à 10 tâches par minute, pas 10 simultanées ; les tâches au-delà de ce seuil sont mises en file d'attente côté serveur.

Atteindre l'une de ces limites renvoie HTTP 429 avec retry_after en secondes dans le corps de la réponse.

Un exemple complet et fonctionnel

import { createReadStream } from 'fs';
import FormData from 'form-data';
import fetch from 'node-fetch';

const API_KEY = process.env.CATT_API_KEY;
const BASE    = 'https://api.convertaudiototext.com/api/v1';

async function submit(filePath, language = 'en') {
  const form = new FormData();
  form.append('source', 'upload');
  form.append('language', language);
  form.append('file', createReadStream(filePath));

  const res = await fetch(`${BASE}/transcribe`, {
    method: 'POST',
    headers: { 'Authorization': `Bearer ${API_KEY}` },
    body: form
  });

  if (!res.ok) throw Object.assign(new Error('Échec de la soumission'), { status: res.status });
  return res.json();
}

async function poll(jobId, maxWaitMs = 600000) {
  const deadline = Date.now() + maxWaitMs;

  while (Date.now() < deadline) {
    const res = await fetch(`${BASE}/result/${jobId}`, {
      headers: { 'Authorization': `Bearer ${API_KEY}` }
    });
    const data = await res.json();

    if (data.status === 'completed') return data;
    if (data.status === 'failed') throw new Error(data.error || 'Échec de la transcription');

    await new Promise(r => setTimeout(r, 5000));
  }
  throw new Error('Délai dépassé');
}

export async function transcribeFile(filePath, language = 'en') {
  const { job_id } = await submit(filePath, language);
  const result     = await poll(job_id);
  return result.transcript?.text ?? '';
}

À partir de là, ajoutez un cache des résultats de transcription pour éviter de retraiter des fichiers identiques, et remplacez le polling par des webhooks dès que vous avez plus de quelques tâches simultanées.

Mon avis : le schéma « soumettre puis interroger » est le même chez tous les grands fournisseurs de transcription asynchrone, si bien que le code client se transfère presque tel quel. Ce qui diffère, ce sont le format de l'en-tête d'authentification, les noms des champs dans la réponse, et le fait que certaines fonctionnalités avancées comme les étiquettes d'intervenants nécessitent un abonnement supérieur. Vérifiez chacun de ces points dans la documentation actuelle du fournisseur avant de passer en production.

Si vous n'avez besoin que d'une transcription propre de temps en temps, sans avoir à gérer de clés API ni de paliers d'abonnement, ConvertAudioToText vous permet d'uploader, de transcrire et de copier votre transcription gratuitement, sans aucune configuration.

Questions fréquentes

Quel abonnement faut-il pour utiliser l'API ?

La création d'une clé API sur ConvertAudioToText nécessite l'abonnement Developer ou Business. Developer inclut 600 minutes par mois ; Business est illimité. Consultez /pricing pour connaître les derniers paliers avant l'achat.

Quelle est la limite de débit pour les tâches de transcription ?

La limite globale est de 100 requêtes par minute et par adresse IP. Les soumissions de tâches de transcription sont en outre plafonnées à 10 tâches par minute et par utilisateur. Atteindre l'une de ces limites renvoie un HTTP 429 avec un en-tête Retry-After.

Polling ou webhooks : lequel choisir ?

Le polling convient aux intégrations à faible volume ou ponctuelles et ne nécessite aucun point de terminaison public. Les webhooks deviennent préférables dès que vous avez plusieurs tâches simultanées : au lieu d'interroger N tâches toutes les quelques secondes, votre serveur reçoit une requête POST par achèvement. Les webhooks nécessitent l'abonnement Business et une URL HTTPS publiquement accessible.

Comment vérifier qu'une charge utile de webhook est authentique ?

Chaque enregistrement de webhook renvoie une chaîne secrète. Lorsque le serveur livre une charge utile, il calcule le HMAC-SHA256 du corps JSON brut à l'aide de ce secret et envoie le résultat dans l'en-tête X-Webhook-Signature sous la forme sha256=hex. Recalculez le même HMAC de votre côté et comparez. Rejetez toute requête où les deux valeurs ne correspondent pas.

Quels formats d'export l'API prend-elle en charge ?

Les tâches terminées peuvent être exportées en SRT, VTT, TXT, JSON, DOCX et PDF via GET /api/v1/result//. Tous les points de terminaison d'export nécessitent un abonnement payant ; les requêtes du niveau gratuit renvoient HTTP 402.

Sources

Try transcription free

Convert any audio or video to clean, unwatermarked text — speaker labels, timestamps, and AI summaries included. First 10 minutes free, no account.

Related Articles