Can you cancel a Sume TTS job? Only before generation starts

Sume cancels a job only before generation work begins. After that the cancel call is rejected with 409. How to code for both outcomes.

5 min readSume
All posts

Yes, but only early. POST /v1/jobs/{id}/cancel durably cancels a Sume job before generation work has started. Once any external generation task has begun, cancellation is rejected, so usage settlement cannot refund work that was already submitted. That applies to TTS, STT and every other job type that goes through the same job routes.

So a cancel button in your product should be a request, not a promise. Build the UI and the code so that a rejected cancel is a normal result.

What does the cancel route say?

The Sume OpenAPI spec lists 200, 400, 401, 404, 409, 429, 500 and 503 for the cancel route. A 200 returns canceled, an idempotency_hit flag that is true when the job was already canceled, and the job record. A 409 is the signal that generation has already begun.

Cancel outcomes for a job, Sume spec read 2026-10-04
Job state when you call cancelExpected result
Queued, generation not started200, status CANCELED
Already canceled200 with idempotency_hit true
Generation already submittedRejected, expect 409
Job id you cannot see404

How do you handle a rejected cancel?

Do not resubmit the same text. A second job is a second charge. Instead, let the first job finish, and discard the result if the user no longer wants it. If a sync wait timed out and you are tempted to retry, read what to do when a TTS sync wait times out first.

  • Check cancelable on the status response before you show a cancel control.
  • Treat 409 as success of the job, not failure of your app.
  • Keep job ids; they are your handle for status, result and events.

What does the code look like?

A small helper that reports which outcome you got:

import os, requests

H = {"Authorization": "Bearer " + os.environ["SUME_API_KEY"]}
job_id = os.environ["JOB_ID"]

r = requests.post(
    f"https://api.sume.com/v1/jobs/{job_id}/cancel",
    headers=H, timeout=30,
)
if r.status_code == 200:
    print("canceled", r.json()["data"]["canceled"])
elif r.status_code == 409:
    print("too late: generation already started, wait for the result")
else:
    print("unexpected", r.status_code, r.text[:200])

Why does Sume work this way?

The spec gives the reason directly: cancellation after submission would let usage settlement refund work already sent for generation. The status response carries a cancelable flag that is true only before external generation work has started, so check it rather than guessing.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume