Polling an avatar video job: HeyGen 30s then 60s vs Sume hints

HeyGen's skill polls every 30 seconds, then every 60. Sume's job status returns next_poll_after_seconds. A runnable Python poller that follows it.

6 min readSume
All posts

The answer

Use the interval Sume hands you instead of a fixed schedule. HeyGen's translate skill page (read 2026-10-04) recommends polling every 30 seconds for 3 minutes, then every 60 seconds, which suits its 5 to 15 minute typical job. Sume's job status reports next_poll_after_seconds, alongside terminal, result_ready and sume_status, per the Jobs and results docs. A poller that waits that long and stops when terminal is true needs no tuning.

What the Sume docs define

Job statuses are queued, processing, completed, failed and canceled. You can read GET /v1/jobs/:id/status, /result and /events; events are a pull snapshot, not a stream. Submitting supports async mode by default, a sync or subscribe mode capped at a 30 second wait with the same behaviour, and webhooks. Reading /result before completion returns 409 job_not_completed, so poll status first. Reuse the same Idempotency-Key on retries.

The Avatar videos docs say a talking-video request is one avatar and one shared scene per final video, and that its duration is 4 to 60 seconds, so jobs are short compared with long-form dubbing.

A poller that follows the hint

The script below reads the key from the environment, refuses to run without one, takes a job id as its argument, and sleeps for the interval the API returns, with a 30 second fallback when none is given.

import json, os, sys, time, urllib.request

key = os.environ.get("SUME_API_KEY", "")
if not key:
    sys.exit("Set SUME_API_KEY first")
job = sys.argv[1] if len(sys.argv) > 1 else sys.exit("usage: poll.py JOB_ID")
base = "https://api.sume.com/v1/jobs/" + job

def get(path):
    req = urllib.request.Request(base + path, headers={"Authorization": "Bearer " + key})
    with urllib.request.urlopen(req, timeout=30) as r:
        return json.load(r)

while True:
    st = get("/status")
    print(st.get("sume_status"), st.get("result_ready"))
    if st.get("terminal"):
        break
    time.sleep(st.get("next_poll_after_seconds") or 30)
if st.get("result_ready"):
    print(json.dumps(get("/result"), indent=2))

Comparing the two approaches

Fixed schedules are fine; server hints are less work.

Polling guidance, HeyGen skill page and Sume docs (read 2026-10-04)
QuestionHeyGen translate skillSume jobs
Interval30 s for 3 min, then 60 sUse next_poll_after_seconds
Typical duration5 to 15 min, some over 30Short clips, 4 to 60 s of video
Stop conditionJob complete or failedterminal is true
Alternative to pollingNot covered on the pageWebhook mode

When not to poll

If a server of yours can receive a callback, use webhook mode and skip the loop. If a job looks stuck, the pull-only events snapshot is what the events endpoint post uses to see where it is. Do not call /result on a timer; wait for result_ready.

Sources

Related posts

More in Sume Avatar 1.0

All Sume Avatar 1.0 posts

Written by Sume