
Webhooks vs polling pour les transcriptions : le choix asynchrone
Summarize this article with:
Optez pour le polling si vous traitez moins de 50 tâches par jour ou si un utilisateur regarde activement une barre de progression. Passez aux webhooks lorsque le volume dépasse environ 100 tâches par jour, lorsque les tâches s'exécutent en arrière-plan, ou lorsque les résultats doivent être diffusés vers plusieurs destinations. Le calcul est sans appel : à 200 tâches par jour, les webhooks réduisent les appels API d'un facteur 18. La partie délicate, c'est de les mettre en œuvre en toute sécurité : vérification HMAC, idempotence, et savoir quels fournisseurs prennent réellement en charge un mécanisme de callback.
Utilisez le polling si vous traitez moins de 50 tâches par jour ou si un utilisateur attend activement. Passez aux webhooks au-delà d'environ 100 tâches par jour, lorsque les tâches s'exécutent en arrière-plan. Voilà la décision en deux phrases. Tout ce qui suit, ce sont les détails d'implémentation qui font la différence entre un webhook qui fonctionne et un autre qui perd discrètement des transcriptions à 2 heures du matin.
Le calcul des ressources
Un exemple concret. Vous transcrivez 200 tâches par jour. Chacune prend en moyenne 3 minutes.
Polling toutes les 5 secondes :
- Par tâche : 36 requêtes de polling en moyenne (3 min x 12 polls/min)
- Par jour : 7 200 requêtes de polling
- Résultats utiles parmi ces requêtes : environ 1 %
Webhooks :
- Par tâche : 1 soumission + 1 livraison de webhook
- Par jour : 200 soumissions + 200 webhooks = 400 événements
- 100 % des événements contiennent un résultat
Les webhooks sont 18 fois plus efficaces à ce volume. À 2 000 tâches par jour, le polling devient réellement coûteux des deux côtés de l'API, et la plupart des fournisseurs commencent à vous limiter sur les vérifications de statut avant même de vous limiter sur les soumissions.
Quand le polling reste le bon choix
Vous n'avez aucun point de terminaison HTTP public. Les environnements de développement local, les applications mobile-first sans backend et les outils internes derrière un VPN ne peuvent pas recevoir de livraisons de webhooks. Le polling ne nécessite que du HTTP sortant.
Le volume est inférieur à 50 tâches par jour. Le coût en ressources est négligeable. La simplicité d'une boucle de polling l'emporte sur l'infrastructure d'un récepteur de webhooks.
L'utilisateur regarde activement. Un utilisateur a téléversé une interview et fixe une barre de progression. Le polling vous donne de quoi mettre à jour l'interface. Les webhooks exigeraient une plomberie supplémentaire (WebSocket, événements envoyés par le serveur ou service de push) pour relayer le signal de fin jusqu'au navigateur. Consultez construire avec les API de transcription pour une boucle de polling fonctionnelle.
Quand passer aux webhooks
Trois signaux :
Le volume franchit la barre des 100 tâches par jour. Le coût d'infrastructure d'un récepteur de webhooks est rentabilisé par les économies d'appels API en moins d'une semaine.
La latence n'a pas d'importance car l'utilisateur ne regarde pas. Traitement en arrière-plan d'enregistrements qui atterrissent dans une base de données pour consultation ultérieure. L'utilisateur verra le résultat à sa prochaine ouverture du tableau de bord.
Les résultats doivent être diffusés vers plusieurs destinations. Un webhook peut déclencher simultanément votre écriture en base, une notification Slack et une mise à jour HubSpot. Le polling doit faire tout cela séquentiellement dans votre code applicatif. Consultez intégrer la transcription avec Slack, Notion ou HubSpot pour les recettes de diffusion.
Quelles API de transcription prennent réellement en charge les webhooks
Cela varie davantage que ce que la documentation laisse entendre.
| Fournisseur | Mécanisme asynchrone | Paramètre de livraison | Vérification de signature | Relances |
|---|---|---|---|---|
| AssemblyAI | Webhook (POST) | webhook_url dans le corps | En-tête personnalisé (vous configurez nom + valeur) | 10 tentatives, 10 s entre chacune |
| Deepgram | Callback (POST) | paramètre de requête callback | En-tête dg-token (identifiant de clé API) | 10 tentatives, 30 s entre chacune |
| Rev.ai | Webhook (POST) | objet notification_config | En-tête d'authentification via config | Toutes les 30 min pendant jusqu'à 24 h |
| AWS Transcribe | Polling uniquement | GetTranscriptionJob | N/A | N/A |
| Google Cloud STT | Polling uniquement (opération longue) | Operations.get | N/A | N/A |
| OpenAI Whisper | Synchrone uniquement | N/A | N/A | N/A |
AWS Transcribe n'offre aucune livraison par webhook. Vous soumettez une tâche, puis vous interrogez GetTranscriptionJob jusqu'à ce que TranscriptionJobStatus soit égal à COMPLETED. Le LongRunningRecognize de Google Cloud Speech-to-Text renvoie un identifiant d'opération que vous interrogez avec Operations.get jusqu'à ce que done soit vrai. Le point de terminaison /v1/audio/transcriptions d'OpenAI est entièrement synchrone : vous restez bloqué jusqu'à ce que la réponse arrive ou que le délai expire.
Mon avis : le mécanisme de callback de Deepgram est le plus adapté à la production des trois qui prennent en charge la livraison asynchrone. Le payload d'AssemblyAI ne livre qu'un transcript_id et un champ status à la fin du traitement, ce qui signifie que vous avez toujours besoin d'un second appel API pour récupérer la transcription proprement dite. Deepgram envoie le résultat complet à votre URL de callback.
Pour un examen plus approfondi de la tarification des grandes API, consultez tarification des API speech-to-text 2026.
Configurer un webhook (API ConvertAudioToText)
L'appel d'enregistrement :
curl -X POST https://api.convertaudiototext.com/api/v1/dashboard/webhooks \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.com/webhooks/transcription",
"events": ["job.completed", "job.failed"]
}'
La réponse inclut un champ secret. Conservez-le précieusement. L'API génère le secret côté serveur et le renvoie une seule fois, au moment de la création. Il n'est pas stocké sous une forme récupérable.
Événements disponibles : job.queued, job.processing, job.completed, job.failed. La plupart des intégrations ne s'abonnent qu'à job.completed et job.failed.

Validation de la signature HMAC
Chaque livraison inclut un en-tête X-Webhook-Signature au format de valeur sha256=<hex>. La signature correspond à HMAC-SHA256(secret, raw_body).
En Node :
import crypto from 'crypto';
import express from 'express';
const app = express();
app.post('/webhooks/transcription',
express.raw({ type: 'application/json' }),
(req, res) => {
const sig = req.header('X-Webhook-Signature');
const expected = 'sha256=' + crypto
.createHmac('sha256', process.env.WEBHOOK_SECRET)
.update(req.body)
.digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(req.body.toString());
handleTranscript(event);
res.sendStatus(200);
}
);
En Python :
import hmac
import hashlib
def verify(signature: str, body: bytes, secret: str) -> bool:
expected = 'sha256=' + hmac.new(
secret.encode(),
body,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, expected)
Utilisez timingSafeEqual (Node) ou hmac.compare_digest (Python). Une comparaison naïve de chaînes laisse fuiter des informations par analyse temporelle du temps de réponse.
Analysez le corps après validation, jamais avant. Un middleware qui parse le JSON avant l'exécution de votre gestionnaire consommera les octets bruts, rendant le calcul de la signature impossible. L'exemple avec express.raw() ci-dessus est délibéré : vous obtenez d'abord le tampon brut, puis vous analysez.
Idempotence
Le worker de livraison peut se déclencher plus d'une fois pour le même événement. Les réseaux tombent en panne. Votre gestionnaire peut traiter un événement puis planter avant de renvoyer un 200. Le fournisseur relance. Votre gestionnaire s'exécute à nouveau.
Chaque événement possède un event_id unique (disponible dans le payload). Le schéma sûr :
async function handleTranscript(event) {
const inserted = await db.query(
`INSERT INTO processed_events (event_id) VALUES ($1)
ON CONFLICT DO NOTHING RETURNING id`,
[event.data.job_id + ':' + event.event]
);
if (inserted.rowCount === 0) return;
await saveTranscript(event.data.job_id, event.data.result_url);
}
ON CONFLICT DO NOTHING signifie que les livraisons dupliquées sortent silencieusement. La première livraison gagne ; les doublons sont ignorés sans lever d'erreurs.
Comportement des relances
Le worker de livraison de ConvertAudioToText relance les livraisons échouées selon ce calendrier (5 tentatives au total) :
| Tentative | Délai |
|---|---|
| 1 | Immédiate |
| 2 | 1 minute |
| 3 | 5 minutes |
| 4 | 15 minutes |
| 5 | 1 heure |
| 6 | 6 heures |
Après 5 tentatives échouées, la livraison est marquée failed. Vous pouvez consulter l'historique des livraisons et déclencher des relances manuelles depuis le tableau de bord des webhooks, ou utiliser le point de terminaison de relance :
curl -X POST https://api.convertaudiototext.com/api/v1/dashboard/webhooks/deliveries/{delivery_id}/retry \
-H "Authorization: Bearer $API_KEY"
Pour que votre gestionnaire se comporte correctement : renvoyez 2xx en cas de succès, 4xx pour les échecs définitifs (aucune relance nécessaire), 5xx pour les échecs transitoires (relance souhaitée). Répondez dans les 30 secondes. Si votre traitement est lent, accusez réception immédiatement et mettez le vrai travail en file d'attente :
app.post('/webhooks/transcription', (req, res) => {
validateSignature(req);
jobQueue.push(req.body);
res.sendStatus(200); // ack first, process after
});
Développement local
Les webhooks exigent une URL HTTPS publique. Deux approches qui fonctionnent :
Tunnel ngrok ou cloudflared. Expose votre serveur local à Internet avec une URL temporaire.
ngrok http 3000
# Use the resulting https URL as your webhook URL
Gestionnaire à double mode. Webhooks en production, polling en développement local. Une variable d'environnement bascule le comportement. Cela garde la boucle de retour locale simple sans modifier le code de production.
Modèles de production
Écriture directe en base. Le gestionnaire écrit la transcription dans Postgres ou MongoDB et renvoie un 200. Le code en aval interroge la base. Le modèle le plus simple, qui fonctionne à toute échelle.
Intégration directe. Le gestionnaire publie dans Slack, crée une page Notion ou met à jour un contact HubSpot. Adapté lorsque l'intégration constitue la destination principale. Échoue bruyamment (5xx) si le service en aval est hors ligne, ce qui déclenche automatiquement les relances.
Bus d'événements. Le gestionnaire publie vers Kafka, SNS ou un topic pub/sub interne. Plusieurs consommateurs traitent le même événement indépendamment. Découple la réception des webhooks du traitement en aval. Le bon modèle pour les pipelines volumineux où plusieurs systèmes consomment la même transcription. Consultez transcription par lot pour grands projets pour l'architecture du pipeline.
Combiner les deux modèles
Parfois, vous voulez les deux. L'utilisateur téléverse un fichier. Votre backend soumet la tâche et commence à faire du polling pour les mises à jour de l'interface. Le webhook se déclenche une fois le traitement terminé et devient l'enregistrement canonique dans votre base de données. L'utilisateur obtient un retour immédiat ; le backend reçoit un signal asynchrone fiable qui ne dépend pas du maintien ouvert de l'interface.
Cette approche hybride demande plus de code, mais offre la meilleure expérience utilisateur lorsque les utilisateurs attendent activement les résultats de fichiers qui leur tiennent à cœur, tandis que le système gère aussi de manière fiable les tâches en arrière-plan.
Si vous avez simplement besoin de transcriptions propres sans construire d'intégration backend, ConvertAudioToText gère tout le pipeline dans le navigateur, sans clé API requise.
FAQ
Quand faut-il utiliser le polling plutôt que les webhooks pour la transcription ?
Utilisez le polling lorsque vous n'avez pas de point de terminaison HTTP public (développement local, outils accessibles uniquement via VPN, applications mobiles sans backend), lorsque le volume est inférieur à 50 tâches par jour, ou lorsqu'un utilisateur attend activement et que vous devez mettre à jour une barre de progression en temps réel. Les webhooks ajoutent un coût d'infrastructure que le polling ne justifie pas à faible volume.
Quelles grandes API de transcription prennent en charge les webhooks ?
AssemblyAI prend en charge les webhooks via un paramètre webhook_url (10 tentatives de relance, délai d'attente de 10 secondes). Deepgram prend en charge un paramètre de requête callback avec vérification de l'en-tête dg-token et 10 relances toutes les 30 secondes. Rev.ai utilise un objet notification_config avec des relances pendant jusqu'à 24 heures. AWS Transcribe et Google Cloud Speech-to-Text imposent le polling : AWS via GetTranscriptionJob et Google via l'interface d'opérations longues Operations.get. OpenAI Whisper est entièrement synchrone, sans aucune livraison asynchrone.
Comment valider qu'un webhook provient bien de la bonne source ?
Le schéma standard repose sur HMAC-SHA256 : le fournisseur signe le corps brut de la requête avec votre secret partagé et place le résultat dans un en-tête. Votre gestionnaire recalcule le même HMAC et compare à l'aide d'une fonction d'égalité résistante aux attaques temporelles. N'utilisez jamais une simple comparaison de chaînes, qui laisse fuiter des informations par analyse temporelle. Deepgram utilise un mécanisme différent (un en-tête dg-token lié à votre clé API), l'approche varie donc selon le fournisseur.
Que doit renvoyer mon gestionnaire de webhook, et à quelle vitesse ?
Renvoyez un code d'état 2xx pour accuser réception, et faites-le dans la fenêtre de délai d'attente de votre fournisseur (30 secondes est courant). Si votre traitement réel est coûteux, accusez réception immédiatement et mettez le travail en file d'attente. Renvoyez 5xx pour les échecs transitoires que vous voulez voir relancés, 4xx pour les échecs définitifs que vous ne voulez pas relancer. Des réponses lentes déclenchent des tempêtes de relances qui peuvent saturer votre file de livraison.
Sources
- Documentation des webhooks AssemblyAI : https://www.assemblyai.com/docs/getting-started/webhooks (consulté le 2026-07-02)
- Documentation des callbacks Deepgram : https://developers.deepgram.com/docs/callback (consulté le 2026-07-02)
- Documentation des webhooks Rev.ai : https://docs.rev.ai/api/asynchronous/webhooks/ (consulté le 2026-07-02)
- AWS Transcribe GetTranscriptionJob : https://docs.aws.amazon.com/transcribe/latest/APIReference/API_GetTranscriptionJob.html (consulté le 2026-07-02)
- Google Cloud STT LongRunningRecognize : https://cloud.google.com/speech-to-text/docs/reference/rest/v1/speech/longrunningrecognize (consulté le 2026-07-02)
- API speech-to-text d'OpenAI : https://developers.openai.com/api/docs/guides/speech-to-text (consulté le 2026-07-02)
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

Speechmatics Alternative for Non-Developers: Web Transcription Without Code
Speechmatics is genuinely excellent for developers: 50 hours free per month, 56 languages, on-prem deployment. If you need a drag-and-drop web app with flat $9.99/mo pricing instead of an API, here is an honest comparison of the two.

Best Transcription Tools with API Access (2026)
Which transcription SaaS tools actually give you API keys, and on which plan? Verified pricing and plan gates for Descript, Sonix, Fireflies, Happy Scribe, AssemblyAI, and more.