tts_text_source_conflict 400: transcript or transcript_source
Sume TTS wants exactly one of transcript and transcript_source. Sending both, neither or a malformed source returns 400. Which code, and how to fix.

A Sume TTS generate request needs exactly one text input: transcript (literal text, 1 to 20,000 characters) or transcript_source (a reference to an accepted script: script_revision_id plus sentence_ids). Send both, neither, or a malformed source, and you get a 400. Two codes are involved, and they are easy to mix up. These come back in Sume's standard error envelope with an HTTP status and a stable code.
The request schema itself says "Provide exactly one of transcript_source or transcript." The source service then answers with the code that tells you which way you erred.
Which code means what
| You sent | Code | Message |
|---|---|---|
| Both transcript and transcript_source | tts_text_source_conflict | Exactly one of transcript_source and transcript is required. |
| Neither | tts_text_source_required | Exactly one of transcript_source and transcript is required. |
| transcript that is empty or whitespace | tts_text_source_required | transcript must be nonempty. |
| transcript_source with an extra key, a bad id, an empty list, over 1,000 ids or duplicate ids | tts_text_source_conflict | Invalid transcript_source. |
| transcript_source on a request with no thread | tts_text_source_required | Source resolution requires a thread. |
The shape that works
transcript_source accepts only the keys script_revision_id and sentence_ids. Ids match ^[A-Za-z0-9_-]{1,128}$. Anything else, including a stray thread_id inside the object, is treated as invalid. Source resolution is thread-scoped, so a bare key with no thread behind it cannot use transcript_source.
Use the literal form when you do not need provenance. The two forms cost the same, $0.0475 per 1,000 characters with a one-cent minimum per job; the source form adds a server-owned receipt to the finished job.
curl -s https://api.sume.com/v1/tts-1.0/generate \
-H "x-api-key: $SUME_API_KEY" -H "idempotency-key: line-001" \
-H "content-type: application/json" \
-d "{\"transcript\": \"Hello from Sume.\", \"voice\": {\"mode\": \"id\", \"id\": \"$VOICE_ID\"}}"Fix by symptom
- Conflict: delete one of the two fields. Do not send an empty string for the one you are not using; an empty
transcriptis its own error. - Required: you sent neither; add the one you meant.
- Invalid transcript_source: print the object and check for unknown keys and duplicate ids.
Sources
Related posts
More in Developers
- Sume TTS transcript_receipt: it proves the text, not the pronunciation
A source-bound Sume TTS job returns a transcript_receipt with a SHA-256 of the submitted text. It proves what was sent, not how it was spoken. Listen too.
- TTS sentence_ids: max 1,000 per request vs the 20,000-character cap
Sume TTS transcript_source takes 1 to 1,000 sentence ids, but the 20,000-character limit usually binds first: only sentences under 20 characters hit 1,000.
- Sume TTS voice.id 400: why 'alloy' fails and a UUID works
Sume TTS voice.id must be a UUID or a voi_ library id, not a voice name. Names borrowed from other vendors return a 400 before any work starts.
- Sume TTS: webhook_url, sync wait or polling? The four modes
Sume TTS jobs take mode async, sync, subscribe or webhook. A webhook needs a public HTTPS webhook_url, and sync waits at most 30 seconds.
Written by Sume