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.

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
| Service | Rate per 1M characters | One day | 30 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/catalogbefore you budget a month, and test with a single real job.
Sources
Related posts
More in Use cases
- DALL-E 2 was removed May 12: four variations from one edit call
OpenAI removed dall-e-2 on May 12, 2026. Replace it with one Sume edit call that returns up to four new takes of a photo, with estimated cost at each quality.
- Driver onboarding videos with an AI avatar: five 30-second clips
Five short avatar clips can cover a driver's first day. What each should say, how to handle a multilingual crew honestly, and the cost by tier.
- Clinic waiting-room clip: 12 seconds of Wan 3.0 for 75 cents
A 12-second explainer loop for a clinic waiting-room screen costs 75 cents at 480p, $1.50 at 720p and $3.00 at 1080p on Sume's wan-3.0.
- Dentist office welcome video: a 9:16 AI avatar clip from one script
A dental practice can make a vertical welcome video without a shoot: one avatar, one script of 4 to 60 seconds, burned-in captions, and a staff review step.
Written by Sume