How do I automate a daily morning briefing audio with a TTS API?

A daily briefing of 2,200 characters is one TTS job: 11 cents a day, $3.30 for 30 days on Sume, plus a 1-cent concat if you add a music sting.

4 min readSume
All posts

Automate a daily briefing by writing the script in your own scheduler, sending it to one asynchronous TTS job per day with the date in the idempotency key, and publishing the finished file. A five-item briefing of about 2,200 characters is about three minutes of speech and costs $0.11 per day on Sume, $3.30 for a 30-day month. Adding a music sting and joining it takes one Timeline audio concat at a flat $0.01, so a branded briefing is $0.12 a day.

Sume does not schedule anything or write the script; it turns text into an audio file when you ask. That split is the useful part: the schedule, the sources and the editorial judgment stay in your system, and the paid call is one small, predictable job.

Size the script in characters

Cartesia's pricing page says one minute of Sonic audio is 750 to 800 credits at one credit per character, and Sume TTS 1.0 meters one credit per character. A three-minute briefing is therefore 2,250 characters at the slow end and 2,400 at the fast end. Plan five items of about 400 characters each, plus a 100-character greeting and a 100-character sign-off, and you land near 2,200.

At $0.0475 per 1,000 characters that is $0.1045, rounded up by the catalog to $0.11. The charge is per job and per character sent, so the length of the listen is your cost control: add an item and you can see exactly what it adds, about 2 cents per 400 characters.

One job per day, safe to retry

A scheduler will sometimes fire twice or retry after a timeout. Put the date in the Idempotency-Key header so a repeat returns the same job instead of a second paid one. The script below submits the job and prints its id; in production, add a poll on /v1/jobs/{id}/status until terminal is true, or pass mode: "webhook" with a webhook_url and let the signed callback tell you the file is ready.

const day = new Date().toISOString().slice(0, 10);
const script = process.argv[2];

const res = await fetch("https://api.sume.com/v1/tts-1.0/generate", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.SUME_API_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": `briefing-${day}`,
  },
  body: JSON.stringify({
    transcript: script,
    voice: { id: process.env.VOICE_ID },
    language: "en",
    generation_config: { speed: 1.05 },
    mode: "async",
  }),
});
const out = await res.json();
console.log(day, (out.data ?? out).request_id);

Add a sting without paying every day

Make the intro sting once. A Music Router prompt for a short, instrumental sting costs $0.125 for one generation, and you reuse the file every day. The Timeline audio concat joins up to 20 parts with no re-synthesis and no silence at the seams, so the daily file is the sting plus the day's voice for $0.01. Use wav for the voice if you will join it; mp3 adds encoder padding at each edge.

If you want the sting under the first sentence rather than before it, use a Timeline render with the voice as the spine and the sting as the soundtrack, but that produces an MP4 at $0.10 per started output minute, which is overkill for a podcast feed.

What a month costs, by pace

30 daily briefings of about 2,200 characters, Sume rates as of 2026-10-07; vendor per-million-character rates read 2026-10-07 and applied to the same characters without rounding.
ServiceRate per 1M charactersOne day30 days
Sume TTS 1.0$47.50$0.11$3.30
Sume TTS 1.0 plus sting concat$47.50$0.12$3.60
MAI-Voice-2.1$22$0.048$1.45
ElevenLabs Flash / Turbo$40$0.088$2.64
ElevenLabs v3$80$0.176$5.28

Failure handling that keeps the feed on time

Because the cost per day is only a few cents, the engineering effort goes into reliability, not savings. The vendor with the lowest rate saves you cents a month at this volume; a missed feed costs more than that in trust. Log the job id, the character count and the date for every briefing, so a listener complaint can be traced to one job and its text, and so your monthly total is a sum you can check against the invoice.

  • Submit the job well before the publish time; queued is a normal accepted state, and a job can wait behind your workspace's concurrency limit.
  • If the job fails, the public error is on the job record; fix the cause and resubmit with a new key suffix such as -retry1, because the old key would return the old job.
  • Keep yesterday's file as a fallback and publish it with a note if the new one is late.
  • Confirm the live rate in GET /v1/catalog before you budget a month, and test with a single real job.

Sources

Related posts

More in Use cases

All Use cases posts

Written by Sume