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 TypeScript SDK createImage: a retired model id fails tsc
Sume's @sume-com/sdk lists accepted image model ids as a string union, so gpt-image-1 fails to compile. Use tsc as the migration checklist.
- TypeScript types for a Sume job status: narrow on sume_status
Type the Sume job envelope as a discriminated union on sume_status, so a switch covers queued to canceled and the compiler flags a missed case. Runs on Node 22.
- Unit test a transcription retry loop with a fake 429 in Python
Test your Sume STT retry code without calling the API: inject the POST and sleep, return a 429 with retry-after, and assert the same key is sent twice.
- Unity editor tool: generate an AI video clip with UnityWebRequest
A Unity coroutine posts a Wan 3.0 job to Sume, polls /v1/jobs/{id}/status with next_poll_after_seconds and downloads the MP4 with DownloadHandlerFile.
Written by Sume