fal vs OpenRouter vs Sume: three webhook shapes for one Sora port
Porting a Sora worker? fal takes webhook_url on a queued request, OpenRouter signs t=,v1= with a 5 minute window, Sume signs sume-v1 over timestamp.body.

fal, OpenRouter and Sume all replace Sora's video.completed callback with a signed or queued delivery, but each has a different shape. fal takes a webhook_url when you submit to its queue. OpenRouter sends an X-OpenRouter-Signature header of the form t=timestamp,v1=hash. Sume sends x-sume-webhook-signature as sume-v1=hex over the timestamp and raw body.
What you are replacing
OpenAI's Sora guide, read 2026-10-07, described video.completed and video.failed events, and the Videos API was shut down on September 24, 2026. Whichever service you move to, rewrite three things: the event names, the signature check and the retry assumptions.
The status vocabularies differ too, which matters if one dashboard shows all three. fal uses upper case queue words, OpenRouter and Sume use lower case job words, and only Sume and OpenRouter name a cancelled state. Map them to one internal enum on arrival.
Three shapes
| Property | fal | OpenRouter | Sume |
|---|---|---|---|
| How to set it | webhook_url on submit | See OpenRouter's video guide | callback_url or webhook_url on the request |
| Status words | IN_QUEUE, IN_PROGRESS, COMPLETED | pending, in_progress, completed, failed | pending, in_progress, completed, failed, cancelled |
| Events | See fal's queue docs | video.generation.completed, failed, cancelled, expired | job.completed, job.failed, job.canceled |
| Signature | See fal's docs | X-OpenRouter-Signature: t=<ts>,v1=<hash> | x-sume-webhook-signature: sume-v1=<hex> |
| Signed string | See fal's docs | {timestamp},{raw_body} | <timestamp>.<raw_body> |
| Replay window | See fal's docs | 5 minutes | 5 minutes suggested |
fal
fal's queue guide says requests are never dropped and are retried automatically up to 10 times, and it offers an X-Fal-No-Retry header to turn that off. That describes request execution, so do not read it as a guarantee about how often your endpoint is called.
OpenRouter
OpenRouter's video route is POST /api/v1/videos with ids in org/slug form, plus GET routes for status, content and models. Its signed webhook adds expired as a fourth event, which has no counterpart in Sume's three.
Sume
Sume gives up to 10 delivery attempts, 30 seconds apart, with a 10 second timeout each, then lets you redeliver a job's event on demand. Rotation is handled in the header, which may carry several comma-separated entries. See the webhook docs.
Test each adapter with a signed fixture, as in the Python signing example elsewhere in this series, before pointing real traffic at it.
One adapter per vendor
Write the receiver against an internal event type (completed, failed, canceled) and keep one small adapter per vendor. Compare event names in the OpenRouter post, and verify each signature over the raw body with an empty-secret check before parsing.
Sources
Related posts
More in Comparisons
- Wan 3.0 text-to-video: fal list price vs Sume per second
fal lists Wan 3.0 at $0.05, $0.10 and $0.20 per second (read 2026-10-07). Sume bills 25% on top: $0.0625, $0.125, $0.25. Cost of 10 seconds and a minute.
- FLUX.2 pro or flex for label text on a bottle: Sume ids
Black Forest Labs calls flex the typography and detail model and pro the affordable production model. How to compare them on Sume with one label prompt.
- FLUX 3 Image is on BFL's pricing page: which FLUX ids can Sume call?
bfl.ai/pricing lists FLUX 3 Image beside FLUX.2 pro, flex, max and klein. On Sume you can call FLUX.2 Pro and Flex today. A dated table and the migration rule.
- Gemini 3.5 Transcribe lists 85+ languages; Sume STT takes a hint
Google's changelog lists Gemini 3.5 Transcribe with 85+ languages and word timestamps. Sume STT returns words always and takes an optional language hint.
Written by Sume