Verify a Sume TTS transcript_receipt SHA-256 yourself in Python
Recompute submitted_transcript_sha256 from your script with NFC and LF canonicalization and compare it to the transcript_receipt on a finished Sume TTS job.

A Sume TTS job generated from an accepted script carries a server-owned transcript_receipt in its result. One field, submitted_transcript_sha256, is the SHA-256 of the exact transcript the job read. You can recompute it from your own copy of the script and confirm the audio was made from the words you approved.
The receipt has six fields: job_id, script_revision_id, sentence_ids, canonicalization_version (always nfc-lf-sentence-v1), submitted_transcript_sha256 and input_integrity (always source_bound). A receipt you supply yourself is not accepted as proof; Sume's own verify-spine check is the authoritative one.
The recipe
Canonicalize each block to NFC with LF line endings, cut it at ., !, ?, take the sentences named in sentence_ids, join them, add a newline wherever the selection crosses into another block, strip surrounding whitespace, and hash the UTF-8 bytes. For a selection inside one block that is simply the joined sentence text, trimmed.
import hashlib, unicodedata
def canon(t):
t = unicodedata.normalize("NFC", t)
return t.replace("\r\n", "\n").replace("\r", "\n")
block = canon("Hello there. This is the approved line. Extra.")
chosen = ["Hello there.", " This is the approved line."]
assert "".join(chosen) in block
transcript = "".join(chosen).strip()
print(hashlib.sha256(transcript.encode("utf-8")).hexdigest())Reading the result
Compare the printed digest with result.transcript_receipt.submitted_transcript_sha256 from GET on the job. Equal digests mean the job read exactly those characters. A difference means a sentence was edited, the selection was different, or the line endings or Unicode form you hashed were not canonical. Fetch the job as described in Jobs and results.
For a whole-script check across many jobs, call POST /v1/tts-1.0/source/verify-spine; it also proves coverage, with no gap or overlap, which a single hash cannot.
Cost of a check
Hashing is local and free, and verify-spine is free and read-only. Only generating audio is billed, at $0.0475 per 1,000 characters.
Sources
Related posts
More in Developers
- verifyWebhook toleranceSeconds 0 turns off the replay check
In @sume-com/sdk, toleranceSeconds defaults to 300 and 0 skips the timestamp check. Keep the default and use the now seam to test old deliveries.
- 4K vertical Short in Timeline: the 2160 cap and 1214x2160
Timeline output width and height top out at 2160 and must be even, so 2160x3840 is refused. What the largest 9:16 frame is and whether a Short needs it.
- video_analyze or video_segment not in Sume tools_list? Dev host only
Sume's docs list video_analyze and video_segment as dev-only, shown only when a flag is on. On mcp.sume.com use video_inspect for what is in a clip.
- video_url on Sume video: only Omni edit, Genjutsu and Recast take it
On the Sume video API, video_url is a source clip, taken by gemini-omni-flash-1.1 (edit), higgsfield-genjutsu and h3-max-recast. Others use reference_video_u...
Written by Sume