19 adresses, 24 opérations. Pour chacune : ce qu'elle lit, ce qu'elle renvoie, et les erreurs qu'il faut traiter. Tout est déplié, parce qu'on arrive ici en cherchant un nom de champ.
6 fonctions du produit n'ont pas de route publique. Les découvrir au milieu d'un chantier coûte une demi-journée ; les lire ici en coûte deux minutes.
Créer un extrait partageable
La fonction existe, dans l'espace client. Elle n'a pas de route publique : un extrait se fabrique à la main, en écoutant, et c'est précisément ce qu'un programme ne sait pas faire à votre place.
Chercher un mot prononcé dans vos audios
Disponible dans l'espace client, pas par clé. Ce que l'API donne, c'est la position de chaque mot d'UN article donné.
Créer ou lister vos sites
Une clé PORTE un site, elle n'en gère pas. Le rattachement se fait à la création de la clé, dans l'espace client ou par l'échange de code.
Enregistrer un webhook une fois pour toutes
Il n'y a pas de réglage de webhook au niveau du compte. L'adresse se passe À CHAQUE APPEL de génération, et elle n'est pas retenue. Si vous cherchiez où la configurer, la réponse est : nulle part, et c'est voulu.
Déclarer un flux RSS à surveiller
La découverte par flux existe comme mode d'intégration, mais elle se configure dans l'espace client, pas par l'API.
Filtrer ou paginer la liste des articles
`GET /podcasts` ne lit aucun paramètre et rend les trente derniers. Pas de filtre d'état, pas de curseur, pas de date. C'est la limite la plus susceptible de vous surprendre, donc elle est écrite ici et sur la route elle-même.
Commencer
Ce qu'il faut avoir compris avant le premier appel.
Authentification
En-tête de toutes les requêtes
Une clé par site, transmise en en-tête. Aucune route n'est servie sans elle, sauf le catalogue de voix et l'échange de code, signalés comme tels.
Authorization: Bearer wd_live_xxxxxxxxxxxxxxxx
À savoir : Avec l'extension WordPress vous ne manipulerez jamais cette clé : elle s'échange de serveur à serveur. La clé en clair n'existe que pour les intégrations maison, et elle n'est jamais réaffichée après sa création.
Langue des messages d'erreur
En-tête Accept-Language
Les messages d'erreur sont rendus en français par défaut, en anglais si vous le demandez. Le CODE HTTP, lui, ne change jamais : c'est sur lui qu'il faut brancher votre logique, pas sur le texte.
Accept-Language: en
À savoir : Deux routes ne traduisent pas encore leurs messages, dont les recommandations. Traitez le code, pas la phrase.
Limites de débit
Trois routes en portent une
Dix générations par minute, quatre lots par minute, trente aperçus de voix par heure. Les quatorze autres routes n'ont pas de limite de débit. Un dépassement rend un 429.
429 { "error": "…maximum 10 générations par minute…" }
À savoir : Deux de ces trois compteurs vivent en mémoire d'instance : ce sont des garde-fous, pas des garanties contractuelles. Seule la limite de génération est comptée en base.
Les codes de refus
Ce qu'il faut savoir traiter
Dix codes couvrent tout ce que l'API peut refuser. Branchez votre logique dessus, jamais sur le texte du message.
400 requête mal formée, champ absent ou hors bornes
401 clé absente, inconnue ou révoquée
402 la retouche dépasse le budget inclus et n'a pas été confirmée
403 le compte est bloqué, ou la capacité n'est pas ouverte
404 la ressource visée n'existe pas, ou n'est pas la vôtre
409 l'état actuel interdit l'opération demandée
429 une limite de débit ou le volume mensuel est atteint
500 un défaut de notre côté, à signaler
502 un service dont nous dépendons a répondu de travers
503 indisponibilité temporaire, réessayez plus tard
À savoir : UN 409 N'EST PAS UNE ERREUR DE VOTRE CÔTÉ : il dit que l'ordre des opérations ne va pas, une régénération déjà en cours, un audio produit avant le calage mot à mot. Le rejouer à l'identique plus tard marche souvent. Un 400 rejoué à l'identique, jamais.
Produire
Envoyer un texte et obtenir un audio. Le mode synchrone publie l'article déjà sonorisé.
POST
Générer l'audio
/api/v1/podcasts
La route principale. Avec `wait` à vrai, la réponse attend la fin de la synthèse et contient l'adresse du fichier : l'article se publie déjà sonorisé, sans délai visible.
Ce que la route lit
textobligatoireLe texte intégral, de 100 à 100 000 caractères.
titlefacultatifSert au flux podcast et à la page de provenance.
canonical_urlfacultatifL'adresse de l'article chez vous.
external_idfacultatifVotre identifiant. C'est lui qui garantit la déduplication : le même envoyé deux fois ne produit qu'un audio.
rubriquefacultatifDétermine la voix, l'habillage et les statistiques par section. Alias accepté : `section`.
authorfacultatifAlimente les statistiques par signature. Alias accepté : `byline`.
voicefacultatifIdentifiant de voix. Une voix inconnue est refusée par un 400, pas remplacée en silence.
triggerfacultatif`auto` pour soumettre à l'interrupteur du compte, `manual` pour forcer.
publish_atfacultatifDate ISO future : prépare l'audio pour une publication programmée.
webhook_urlfacultatifAdresse https publique, appelée quand l'audio est prêt. Elle vaut POUR CET APPEL et n'est jamais retenue comme réglage.
auto_regeneratefacultatifRégénérer automatiquement quand le texte change.
waitfacultatifVrai pour recevoir l'audio dans la réponse. Sans effet au-delà de 20 000 caractères.
Idempotency-Key Rejouer le même appel avec la même clé ne produit pas un second audio.
POST https://wedispatch.fr/api/v1/podcasts
Content-Type: application/json
{
"text": "Le conseil municipal a adopte hier soir...",
"title": "Le budget 2027 adopte",
"external_id": "id-dans-votre-cms",
"rubrique": "Politique",
"wait": true
}
Ce qu'elle renvoie : `article_id`, `job_id`, `status`, `embed`, et avec `wait` : `audio_url`, `duration_s`, `version`, `engine`, `voice`, `fallback`.
À traiter : 400 texte, voix, langue ou date invalides · 403 compte bloqué · 429 quota mensuel atteint, ou dix par minute dépassé
À savoir : Un article de plus de 1 000 caractères consomme un crédit de plus par tranche entamée, et la tranche entamée est perdue.
POST
Génération par lot
/api/v1/podcasts/batch
Jusqu'à vingt-cinq articles en une requête, pratique pour un fonds d'archives. Chaque champ unitaire est accepté par entrée, et `language`, `trigger` et `auto_regenerate` acceptent aussi une valeur pour tout le lot.
Ce que la route lit
itemsobligatoireTableau non vide, vingt-cinq entrées au maximum. Chaque entrée accepte les mêmes champs que la génération unitaire.
Ce qu'elle renvoie : `accepted`, `total`, et `results[]` où chaque entrée porte son propre `status` : `processing`, `ready`, `stale`, `quota`, `blocked`, `skipped` ou `error`.
À traiter : 400 items absent, vide ou au-delà de vingt-cinq · 429 quatre lots par minute dépassé
À savoir : `wait` n'existe PAS sur cette route, et l'en-tête d'idempotence n'y est pas lu. Le volume mensuel restant borne le lot avant les limites de débit : vingt-cinq articles avec dix crédits restants en traite dix et signale le reste en `quota`.
POST
Régénérer entièrement
/api/v1/podcasts/{article_id}/regenerate
Pour un article modifié en profondeur. Consomme un crédit comme une génération. Elle repart aussi d'un compteur de correction vierge (`patch_chars_used`), qui n'est qu'une mesure du texte repris sur cet audio : il n'ouvre aucun droit, et une correction coûte le même prix avant et après.
Ce que la route lit
voicefacultatifChanger de voix au passage.
languagefacultatifChanger de langue au passage.
publish_atfacultatifProgrammer la mise en ligne de la nouvelle version.
webhook_urlfacultatifAppelé quand la nouvelle version est prête.
POST https://wedispatch.fr/api/v1/podcasts/{article_id}/regenerate
Ce qu'elle renvoie : `article_id`, `job_id`, `status`, `regens_included`, `regens_used`.
À traiter : 404 article inconnu · 409 aucun texte stocké à régénérer · 429 plafond de régénérations ou quota mensuel
À savoir : C'est la première cause de consommation involontaire, en général après une petite correction de texte. Regardez d'abord si la retouche suffit : elle ne facture que le passage réécrit, là où une régénération repaie l'article entier.
Suivre
L'état d'un article, et la liste des derniers.
GET
Suivre un article
/api/v1/podcasts/{article_id}
L'état d'un article et, quand il est prêt, l'adresse de son audio. À appeler après un envoi sans `wait`, ou à la réception d'un webhook.
GET https://wedispatch.fr/api/v1/podcasts/{article_id}
Ce qu'elle renvoie : `article_id`, `title`, `status` (`processing`, `ready`, `stale` ou `failed`), `regen_count`, `audio` (`null` ou l'objet complet avec `url`, `duration_s`, `version`), `embed`, `subtitles`.
Les trente derniers articles du compte, du plus récemment modifié au plus ancien.
GET https://wedispatch.fr/api/v1/podcasts
Ce qu'elle renvoie : `articles[]` : `id`, `title`, `canonical_url`, `audio_status`, `char_count`, `regen_count`, `updated_at`, et selon l'état de la base `rubrique` et `author`.
À savoir : CETTE ROUTE N'ACCEPTE AUCUN PARAMÈTRE. Ni filtre d'état, ni pagination, ni date. Trente lignes, toujours. Si vous avez besoin de retrouver les articles à régénérer, comparez vous-même `audio_status` sur ce que vous recevez.
DELETE
Retirer un audio
/api/v1/podcasts/{article_id}
Supprime les fichiers audio d'un article. L'article, son texte source et ses statistiques d'écoute sont conservés.
À savoir : Si votre thème filtre le contenu par un point d'entrée inhabituel, l'insertion automatique peut échouer. Le conteneur explicite vous rend la main sur l'emplacement exact.
GET
Sous-titres
/api/v1/podcasts/{article_id}/subtitles
Fichier de sous-titres aligné sur la lecture RÉELLE, pas sur le texte source. C'est ce qui évite la dérive dès le premier nombre développé.
Ce que la route lit
formatfacultatif`srt` par défaut, ou `vtt`.
GET https://wedispatch.fr/api/v1/podcasts/{article_id}/subtitles?format=vtt
Ce qu'elle renvoie : Le fichier lui-même, en texte brut. Ce n'est pas du JSON.
À traiter : 400 format inconnu · 404 article ou calage introuvable · 409 audio produit avant le calage mot à mot
Retoucher
Agir sur un audio déjà produit sans tout régénérer.
GET
La position de chaque mot
/api/v1/podcasts/{article_id}/words
Le premier des deux temps d'une retouche : un passage se désigne par des index de mots, il faut donc d'abord savoir où chaque mot tombe dans la bande son.
GET https://wedispatch.fr/api/v1/podcasts/{article_id}/words
Ce qu'elle renvoie : `article_id`, `title`, `duration_s`, `words[]` avec pour chaque mot son début et sa fin.
À traiter : 403 la retouche n'est pas ouverte sur ce compte · 409 le moteur utilisé ne produit pas de calage mot à mot · 409 audio antérieur au calage
POST
Retoucher un passage
/api/v1/podcasts/{article_id}/correct
Vous réécrivez le passage fautif, lui seul est resynthétisé et recousu dans l'audio existant. L'adresse du fichier ne change pas, donc vos pages n'ont rien à mettre à jour.
Ce que la route lit
from_wordobligatoireIndex du premier mot à remplacer, dans le tableau rendu par la route précédente.
to_wordobligatoireIndex du dernier mot, inclus.
textobligatoireCe qu'il faut entendre à la place.
accept_credit_usefacultatifConfirme que vous acceptez de dépenser le ou les crédits. Toute retouche en coûte au moins un : sans ce champ, la demande est refusée en 402 avec son prix.
POST https://wedispatch.fr/api/v1/podcasts/{article_id}/correct
{
"from_word": 142,
"to_word": 149,
"text": "deux virgule quatre millions d'euros"
}
Ce qu'elle renvoie : `ok`, `version`, `duration_s`, `patch_chars`, `patch_chars_used`, `credits_used`, `review`.
À traiter : 402 la dépense n'a pas été confirmée · 403 la retouche n'est pas ouverte sur ce compte · 409 audio sans calage mot à mot
À savoir : Le prix est rendu SUR LE REFUS, dans `credits_required` : c'est au moment où l'on est refusé qu'on a besoin de savoir ce que la demande coûterait. Un crédit ouvre mille caractères et chaque retouche ouvre les siens, il n'existe donc pas de retouche à zéro crédit. `review` à vrai signale une couture serrée qui mérite une écoute avant diffusion.
Régler
Les réglages du compte lisibles et modifiables par clé.
GET
Lire les réglages
/api/v1/profile
Tous les réglages du compte, groupés par domaine, plus ce que votre offre ouvre réellement.
GET https://wedispatch.fr/api/v1/profile
Ce qu'elle renvoie : `player`, `reading` (dont le lexique de prononciation), `sound`, `gate`, `capabilities`, `player_templates`, et `editable` : la liste exacte des champs qu'une clé peut écrire.
À savoir : `editable` est la source de vérité. Plutôt que de recopier la liste ci-dessous dans votre code, lisez-la : elle vous dira ce qui est modifiable le jour où elle changera.
GET
Lire le lexique de prononciation
/api/v1/pronunciations
Les corrections de prononciation du compte, celles qui s'appliquent à tous les articles avant synthèse.
GET https://wedispatch.fr/api/v1/pronunciations
Ce qu'elle renvoie : `pronunciations` (la liste `{ de, vers }`), `count`, `max`.
À savoir : La LECTURE n'est pas réservée : un compte qui perd l'option doit pouvoir relire et exporter ce qu'il avait posé. C'est l'écriture qui l'est.
POST
Ajouter ou corriger une prononciation
/api/v1/pronunciations
Fusionne dans le lexique existant : ce que vous n'envoyez pas n'est pas touché. Un mot déjà présent voit sa prononciation remplacée, jamais dupliquée.
POST https://wedispatch.fr/api/v1/pronunciations
{ "de": "Ploërmel", "vers": "Plo-air-mel" }
Ce qu'elle renvoie : La liste complète après le geste, plus `added`, `replaced`, `ignored`.
À traiter : 400 aucune entrée exploitable (`de` et `vers` requis, 80 caractères au plus) · 403 le lexique n'est pas ouvert sur ce compte · 409 lexique plein (200 entrées)
À savoir : Un appel qui n'a RIEN posé rend une erreur, jamais un 200 : sans quoi votre interface afficherait « enregistré » pour une correction qui n'existe pas. La casse ne crée pas de doublon, les accents si : « Ploërmel » et « Ploermel » sont deux entrées, et c'est voulu.
DELETE
Retirer une prononciation
/api/v1/pronunciations
Par mot source, casse ignorée. Retirer un mot absent n'est pas une erreur.
Ce qu'elle renvoie : La liste complète après le geste, plus `removed`.
À traiter : 400 ni `de`, ni `pronunciations`, ni `all: true`
À savoir : Tout vider EXIGE `all: true`. Un DELETE sans corps est ce qu'un client HTTP envoie quand il se trompe d'appel ; lui faire effacer deux cents entrées irrécupérables serait un piège.
PUT
Modifier les réglages
/api/v1/profile
Vingt-cinq champs sont modifiables par clé, dont le lexique de prononciation, la voix par défaut, les règles de voix et l'apparence du lecteur.
PUT https://wedispatch.fr/api/v1/profile
{ "default_voice": "...", "player_template": "..." }
Ce qu'elle renvoie : `ok`, plus `ignored[]` si vous avez envoyé des champs qui ne sont pas modifiables par clé.
À traiter : 400 aucun champ modifiable dans le corps envoyé · 403 le réglage demandé n'est pas ouvert sur ce compte · 409 le réglage exige un calage mot à mot absent
À savoir : Un champ non modifiable n'est pas une erreur : il est écarté et RENDU dans `ignored`, pour que vous le voyiez au lieu de le supposer appliqué. Le mode d'accès conditionnel n'est jamais modifiable par clé, délibérément.
Mesurer
La consommation et les écoutes. Des comptages, jamais des personnes.
GET
L'état du compte
/api/v1/account
Le volume souscrit, la consommation du mois, et ce que l'offre inclut.
GET https://wedispatch.fr/api/v1/account
Ce qu'elle renvoie : `plan_label`, `volume`, `usage` (dont `credits_used`, `credits_quota`, `articles_left`), `included`, `access`, `offre`, `urls`.
À savoir : `plans` et `next_plan` sont vides et le resteront : ils datent des anciens forfaits et ne sont gardés que pour ne casser aucune intégration existante. La structure de `offre` n'est pas décrite ici, faute d'avoir été auditée : lisez-la plutôt que de la supposer.
GET
La consommation du mois
/api/v1/usage
Ce qui a été consommé sur la période en cours, en crédits et en caractères.
GET https://wedispatch.fr/api/v1/usage
Ce qu'elle renvoie : `period`, `quota_credits`, `credits_used`, `credits_left`, `percent_used`, `warning`, `blocked`, `generations`, `regenerations`, `listens`, `audio_minutes`.
GET
Les écoutes
/api/v1/stats
Des comptages agrégés, par article, par rubrique et par signature. Jamais par personne : l'information n'existe pas.
GET https://wedispatch.fr/api/v1/stats
Ce qu'elle renvoie : `generated_at`, `totals`, `last_30_days`, `articles`, `authors`.
À savoir : Aucun paramètre : pas de filtre de période, pas de pagination. La structure interne des agrégats n'est pas détaillée ici faute d'audit : elle est stable, mais nous préférons vous la faire lire que vous la décrire de mémoire.
POST
Nous dire ce qui n'allait pas
/api/v1/feedback
Un retour court, envoyé par l'extension WordPress au moment où quelqu'un la désactive, et UNIQUEMENT s'il a cliqué « Envoyer ». Documentée ici parce qu'elle existe : une route qu'on n'écrit pas est une route qu'on oublie de sécuriser.
Ce qu'elle renvoie : `ok`. Toujours 200 : l'appelant est en train de désactiver une extension, son geste ne doit dépendre d'aucune de nos pannes.
À savoir : Ne contient jamais de contenu d'article ni rien sur un auditeur. Les champs inconnus sont ignorés sans erreur, pour qu'une version future de l'extension ne perde pas son retour sur un détail de forme.
Les voix
Le catalogue, et un aperçu sonore avant de choisir.
GET
Le catalogue de voix
/api/v1/voices
Les voix disponibles pour votre compte, y compris vos voix signature.
GET https://wedispatch.fr/api/v1/voices
Ce qu'elle renvoie : `engine`, `default`, `voices[]` avec `id`, `label`, `gender`, `style`, `langs[]`, et `sample` quand un extrait existe.
À savoir : Cette route est servie SANS clé, parce que la documentation et le démonstrateur en dépendent. En revanche, une clé PRÉSENTÉE et refusée fait échouer l'appel : elle ne retombe jamais sur le catalogue public, ce qui masquerait une clé morte.
POST
Écouter une voix
/api/v1/voices/preview
Un extrait sonore sur votre propre texte, avant de choisir. Ne consomme aucun crédit.
Ce que la route lit
textobligatoireDe 100 à 3 000 caractères.
voicefacultatifSinon la voix par défaut du compte.
languagefacultatifSinon la langue par défaut.
POST https://wedispatch.fr/api/v1/voices/preview
{ "text": "...", "voice": "..." }
Ce qu'elle renvoie : Le fichier audio lui-même. L'en-tête `X-WeDispatch-Billed` vaut zéro, et l'en-tête `X-WeDispatch-Voice` dit quelle voix a réellement parlé.
À traiter : 400 texte trop court ou trop long · 429 trente aperçus par heure dépassés
À savoir : Une voix inconnue n'est PAS refusée ici : elle est remplacée par la voix par défaut. Lisez l'en-tête de réponse pour savoir laquelle a servi, sans quoi vous croirez avoir écouté celle que vous aviez demandée.
Accès conditionnel
Pour un contenu réservé : vérifier un jeton d'écoute côté serveur.
GET
La configuration d'accès
/api/v1/access
Le mode d'accès du compte et le secret qui permet de signer des jetons d'écoute.
GET https://wedispatch.fr/api/v1/access
Ce qu'elle renvoie : `mode`, `preview_seconds`, `token_ttl_s`, `secret`, `client_id`.
À savoir : Le secret ne sort jamais du serveur. Cette route est à appeler depuis votre back-office, jamais depuis une page.
POST
Vérifier un jeton d'écoute
/api/v1/access/check
Pour un contenu réservé : votre serveur vérifie qu'un jeton donne bien droit à cet article.
Ce que la route lit
articleobligatoireL'identifiant de l'article demandé.
tokenfacultatifLe jeton présenté. Son absence rend simplement un refus motivé.
POST https://wedispatch.fr/api/v1/access/check
{ "article": "{article_id}", "token": "..." }
Ce qu'elle renvoie : `valid`, `status`, `reason`, `detail`, `mode`. Le motif dit précisément pourquoi : jeton absent, mal formé, signature invalide, mauvais article, ou expiré.
À traiter : 400 champ article manquant
POST
Échanger un code contre une clé
/api/v1/connect/exchange
Ce que fait l'extension WordPress à l'installation : elle échange un code à durée courte contre sa propre clé, de serveur à serveur. L'utilisateur ne voit jamais la clé.
Ce que la route lit
codeobligatoireLe code obtenu à l'écran d'autorisation.
secretobligatoireLe secret de votre installation.
POST https://wedispatch.fr/api/v1/connect/exchange
{ "code": "...", "secret": "..." }
Ce qu'elle renvoie : `api_key`, `plan`, `tier`, `site`, `label`.
À traiter : 400 code expiré ou invalide · 400 maximum dix clés actives atteint · 404 compte introuvable
À savoir : C'est la seule route, avec le catalogue de voix, qui ne demande pas de clé : elle sert justement à en obtenir une.
Un cas qui n'est pas couvert ?
Cette documentation décrit ce que le code fait, pas ce que nous aimerions qu'il fasse. Si vous cherchez une route qui n'y est pas, elle n'existe probablement pas : dites-nous ce que vous vouliez faire, c'est utile même quand la réponse est non.