callback_url or webhook_url: which field each Sume video route takes

POST /v1/videos takes callback_url; motion control, lip-sync and image routes take mode plus webhook_url. The field names and what they share.

5 min readSume
All posts

On Sume, POST /v1/videos takes callback_url in the request body, while the avatar-type routes such as Kling 3.0 motion control and MiniMax H3 Max lip-sync take a mode field and a webhook_url. Both deliver a signed POST to your HTTPS endpoint when the job finishes. The names differ because the two families of routes were designed in different places: the video route copies the OpenRouter video API, and the other routes use Sume's own communication fields.

If you copy a body from one route to the other, the webhook field is the one most likely to be wrong, so keep the table below next to your client code.. A wrong field name is quietly dangerous because an unknown key may be ignored instead of rejected, in which case the job runs normally and no webhook ever arrives. You then see the symptom, a clip that finished but never reached your system, long after the cause is forgotten. Treat the map as part of the contract with each route and review it whenever a new route joins your client.

The field map

Every field below comes from the Sume route docs. A route that does not list a callback field in its docs is not in the table.

Where each Sume route takes its webhook (Sume docs, read 2026-10-07)
RouteFieldNotes
POST /v1/videoscallback_urlHTTPS only, in the body
POST /v1/kling/3.0/motion-controlmode + webhook_urlmode selects async or waiting behavior
POST /v1/minimax/h3-max/lip-syncmode + webhook_urlSame communication fields as Fabric
POST /v1/imagesmode, webhook_url, wait_timeout_secondsCommunication additions shared by generate routes

What stays the same

The delivery itself is shared. On /v1/videos, Sume sends its own job webhook envelope with an x-sume-webhook-signature header, not an OpenRouter video.generation.* event with an OpenRouter signature. Check the webhooks reference for the exact header set on your route before you write the verifier, and route on the job in the payload and not on the URL path.

Refuse to verify with an empty secret, and verify the raw bytes before you parse the JSON. Stored receivers are in a stdlib receiver for videos and a Kling motion control receiver.

Both requests side by side

The first request is the video route and the second is the motion control route. The model, the inputs and the webhook field are the three places the bodies differ.

# /v1/videos: callback_url
curl -X POST "https://api.sume.com/v1/videos" \
  -H "Authorization: Bearer $SUME_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"wan-3.0","prompt":"A paper boat on a pond",
       "callback_url":"https://example.com/hooks/video"}'

# motion control: mode + webhook_url
curl -X POST "https://api.sume.com/v1/kling/3.0/motion-control" \
  -H "Authorization: Bearer $SUME_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"image_url":"https://example.com/still.png",
       "motion_video_url":"https://example.com/move.mp4",
       "duration_seconds":5,"mode":"async",
       "webhook_url":"https://example.com/hooks/video"}'

One receiver for every route

Because the envelope is shared, a single endpoint can serve both families. Give each submitted job its own idempotency key, store the job id that the submit response returns, and when a webhook arrives look the job up by the id in the payload. Do not infer the route from the URL, and do not assume the order of delivery: a webhook can arrive before the submit call has returned to your code, so write the job row first or make the handler tolerant of an unknown id by retrying the lookup.

Respond with a 2xx quickly and do the heavy work, such as downloading the clip, in a queue. A handler that takes a long time invites redelivery, and a second delivery of the same event should be a no-op in your code. Keep the status check on the job as the final authority: if a webhook is lost, the poll address returns the same terminal state.

A short checklist for a mixed client

If your client builds bodies for several routes, put the field mapping in one function and test it. Three tests are enough: a video body has callback_url and no webhook_url, a motion control or lip-sync body has webhook_url and a mode, and every webhook URL in a body is HTTPS. These checks catch the copy and paste mistake before a job is reserved and billed.

When polling is still the right choice

A webhook is optional on every route. You can poll GET /v1/videos/{id} or the shared GET /v1/jobs/{id}/status and /result. The submit response carries a polling_url, so a client that cannot expose a public endpoint can poll that address until the status is terminal.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume