Vercel Workflows: a hook that waits for a Sume run webhook

A Vercel Workflows hook pauses a workflow until an outside event resumes it. Use one to wait for Sume's run webhook with no polling.

5 min readSume
All posts

A Vercel Workflow can start a Sume run in one step and then wait on a hook, which pauses the workflow until your webhook route resumes it. The Sume run webhook is the natural resume signal: one format.run.terminal event arrives per run, your route verifies it and resumes the hook, and the workflow continues. The wait itself does not use compute.

The Vercel facts are from Workflow and Workflow concepts, both read 2026-10-10. The Sume facts are from Run webhooks and Create a run.

What are the Vercel pieces?

The pages describe two directives, "use workflow" for the durable function and "use step" for a unit of work inside it. Steps have built-in retries. A sleep uses no compute. Hooks, created with defineHook, wait for external events: a workflow creates one, and other code resumes it with a payload. The docs page that redirects from the old /docs/workflow address now lives under /docs/workflows.

One caution about names. The Vercel docs describe the feature as Workflow in some places and Workflows in others, and the older address redirects. Check the current page before you copy an import path, because a durable-execution API is the kind of surface that changes between releases.

Vercel Workflows pieces (Vercel docs, read 2026-10-10)
PieceWhat the docs sayRole in a Sume flow
use workflowMarks the durable functionThe whole render job
use stepA unit of work, with built-in retriesThe submit call and the result fetch
sleepUses no computeSpacing between status checks
HookCreated with defineHook, resumed by outside codeWaits for the Sume run webhook

How does the flow look?

Step one sends POST /v1/formats/{handle}/{slug}/runs with an Idempotency-Key, a communication.webhook_url that points at your route, and a spend cap. Step two creates a hook and awaits it. Your route receives the Sume delivery, verifies the HMAC-SHA256 signature over <timestamp>.<raw_body>, and resumes the hook with the request_id and the outcome. Step three fetches the result.

Because steps retry on their own, the submit must be idempotent. A step retried after a lost response sends the same key, and Sume returns 200 with idempotency_hit: true and the original run instead of a second paid render.

The sample leaves the hook creation as a comment on purpose. The exact call shapes for defineHook, create and resume are on the Vercel concepts page, and they are Vercel's to define, not ours. What matters for Sume is the order: submit, wait on the hook, then fetch the result.

What should the webhook route check?

Verify before you resume. The route reads the raw body, checks x-sume-webhook-signature with the signing secret, rejects an empty secret, and honors the 300 second replay window of verifyWebhook from the SDK. Then it looks up the hook for the request_id, which equals the run id.

Dedupe at this point. A delivery may repeat, and resuming a hook twice should be harmless. Sume sends the same request_id each time, so the second resume finds nothing waiting.

What if the webhook never arrives?

Add a fallback. Sume tries up to 10 times with backoff, but a misconfigured URL fails all of them. The receipt's webhook_delivery field shows status, attempts and url, and the POST /v1/format-runs/{run_id}/webhook/redeliver endpoint sends the event again once you fix the route. A second path in the workflow, a sleep followed by a status check, resolves the run even if no webhook shows up. The run expires on its own, since a non-terminal receipt carries an expires_at deadline of 90 minutes at most.

If you do not need a workflow engine, the same pattern works with a database row: write the run id, and let the webhook route update the row. A workflow earns its place when the steps after the render are many, such as upscaling, captioning and posting, and each deserves its own retries.

Sources

Related posts

More in Integrations

All Integrations posts

Written by Sume