← Blog · 22 September 2026 · Lire en français

Voice your articles by API: the route for a homemade or headless CMS

You're not on WordPress. Here's how a REST API turns an article into audio in one request: send the text, get a synchronous response or a webhook, show the player in one line. The real path, no magic.

Integration guides almost always assume an off-the-shelf CMS: WordPress, Drupal, a theme you must not break. But plenty of publishers run on something else: a homemade CMS, a headless back office, the group's own framework. For them, a closed plugin is the wrong building block. What they need is a clear, predictable API that takes an article and returns audio, without forcing a dependency on the newsroom side. That is exactly what the API for any CMS does, and this article walks through the real path, step by step, with nothing dressed up.

The basic move: one request, one response

The entry point is a single route: a POST /api/v1/podcasts with the article's text, its title, and an id of your own (external_id), the one the article already carries in your database. Authentication is an API key in a header (Bearer), like any modern REST API. No server-side account to create, no proprietary SDK to install: an HTTP call is enough, whatever your language.

That choice has a pleasant practical consequence: you test the integration from a terminal before writing a single line in your CMS. A curl with a paragraph, a key, and you see the response come back. It is the kind of check we always recommend doing first, because it cleanly separates "the API answers" from "my template renders it right".

Sync or async: two rhythms, two needs

The API exposes two modes, and the right one depends on your publishing chain.

In synchronous mode, you add wait: true to the request: the response only arrives with the audio ready, usually in five to fifteen seconds for an article. This is the mode for newsrooms that want to publish the article and its audio in one piece: the moment the author hits publish, the audio already exists and goes out with the rest. The cost is a request that holds the connection while the audio is built, which suits a single article perfectly.

In asynchronous mode, you block nothing: the API answers immediately, the build happens behind the scenes, and a signed webhook tells you when the audio is ready. Each webhook call carries a timestamp and an HMAC-SHA256 signature computed with your secret: you recompute it on your side and compare before accepting, which guarantees the call really comes from us and not from a third party. This is the mode for queues and large volumes, where you would rather process notifications at your own pace. If webhooks and feeds are new to you, the RSS feed is another, simpler door for turning your articles into an automatic podcast with no code.

Archives: up to 25 articles per request

A site that has been running for years does not have one article to voice, it has hundreds. The API accepts a batch send, up to 25 articles per request, on the same rules as single sends. You catch up on a backlog without hammering the API with one call per article, and you keep control of the throughput. For a duration and cost estimate on a large backlog, the full calculation is in how long it takes to add audio to an existing blog.

Showing the player: one line in your template

Once the audio is built, you need to hear it. The player drops in with a single line (player.js) carrying the article's id, wherever you want it in your template, usually before the first paragraph. It brings chapters, the second-precise timestamped link and automatic theming that follows your page's colours, with no styling on your part. You do not touch the rendering of your article: you add a component, and nothing else in your layout moves.

Updates: the double-billing trap, avoided

The question that always comes up in production: what happens when a corrected article is sent again? You send the same external_id. The audio in place keeps being served, and the article moves to a "stale" state: you know it changed, but nothing regenerates on its own. You trigger the new version when the text has settled, not on every corrected comma. This is a deliberate choice: speech synthesis is billed per character, and an accidental regeneration on every save would cost money for nothing. The API is built for production, with idempotency and deduplication, precisely so that kind of accident does not happen.

What the API does not do for you

Let's be honest about the limits. The API returns audio and a player: it does not decide for you where to place the player in your layout, nor when to trigger a regeneration, nor how to manage your async queue. Those are integration decisions that stay with you, and that is intentional: a clean building block plugs in, it does not take over. If your need is the opposite, to write no code at all, this is not the right route, and integrating by feed or plugin will be more direct, as described in integrating audio by API or RSS feed on WordPress.

Reading quality, for its part, does not depend on the integration mode: whether you go through the API, a feed or a plugin, the same French normalisation applies upstream, the one we defend on the French text-to-speech page. The API changes how audio enters your site, not what comes out of the speaker. And for a specific headless CMS, the Strapi, Sanity or Contentful case is handled separately in integrating audio with a headless CMS.

Give your articles a voice with WeDispatch

This blog is itself voiced by WeDispatch. Curious how it sounds on your content?

Book a demo

Read next