TikTok publish_id status: poll it after the Sume job webhook fires
The TikTok Direct Post page I read returns a publish_id to check status and mentions no webhook. Let Sume's webhook trigger the post, then poll TikTok.

TikTok's Direct Post reference returns a publish_id that you use to check the status of a post, and the page I read mentions no webhook for it. Build the chain in two hops: Sume's signed job.completed webhook starts the post, then your worker polls TikTok's status for the publish_id until it settles.
Sume pushes terminal job events only, so the first hop is push and the second is a poll you own.
Who tells you what?
Each hop has its own signal.
| Hop | Signal | Mechanism |
|---|---|---|
| Render done | job.completed, job.failed or job.canceled | Signed Sume webhook, with status_url polling as backup |
| Post started | publish_id from init | TikTok init response |
| Post settled | Status of the publish_id | Poll TikTok's status endpoint |
How do I dedupe the first hop?
Sume retries until it gets a 2xx and tells receivers to use job_id as the idempotency key. Insert the job id once; ignore repeats. The sample uses SQLite.
import sqlite3
db = sqlite3.connect(":memory:")
db.execute("create table seen (job_id text primary key)")
def first_time(job_id: str) -> bool:
cur = db.execute("insert or ignore into seen values (?)", (job_id,))
db.commit()
return cur.rowcount == 1
if __name__ == "__main__":
print(first_time("job_1"), first_time("job_1"))What if a webhook never arrives?
After 10 refused attempts a delivery fails but the job still reached its terminal state. Keep status_url polls as the recovery path, or redeliver with POST /v1/jobs/{job_id}/webhook/redeliver (Webhooks).
Sources
Related posts
More in Developers
- TikTok upload_url is valid for one hour: finish the Sume job first
TikTok says the Direct Post upload_url is valid for one hour after issuance. Wait for the Sume job to complete before you initialize so the upload fits.
- Time a 360p Omni draft vs 720p: separate queue wait from run time
Google says the 360p draft is up to 60% faster. Measure it on Sume with a Python script that splits pending time from in_progress time.
- Timeline refuses a 180-second Short: clips end more than 0.5 s early
Timeline 1.0 allows video coverage to stop at most 0.5 seconds before the end of the audio spine. Check slot ends in Python before you plan a 180-second Short.
- Timeline plan first: the unbilled estimate for a 30-second Short
POST /v1/timeline-1.0/plan compiles your cut without a job or a charge and returns duration, segments and estimated cost. A 30-second render bills one minute.
Written by Sume