fal webhook status OK or ERROR vs the Sume job webhook
fal posts a webhook with status OK or ERROR, separate from queue status. Sume's job webhook uses the same words plus an event name. One handler for both.

fal's webhook payload carries a status of OK or ERROR, and Sume's job webhook payload does too, but they sit in different places in the lifecycle. On fal, OK/ERROR is a webhook-only outcome, distinct from the queue statuses IN_QUEUE, IN_PROGRESS and COMPLETED. On Sume, status: "OK" rides next to an event name (job.completed, job.failed, job.canceled) and the job's own status stays completed, failed or canceled.
If you are porting a fal handler, the field name matches but you should branch on event, not only on status.
What does fal's webhook say?
Per the fal queue page, passing webhook_url to submit() makes fal post the result automatically on completion. The page says the webhook body has status "OK" for success or "ERROR" for failure, and that this is distinct from the three request lifecycle states. This page does not describe signature verification, which is covered separately by fal's other docs and by our fal signature comparison.
What does Sume's job webhook look like?
Sume sends terminal job events only: no progress or partial deliveries. Submit with mode: "webhook" and a public HTTPS webhook_url (callback_url is an alias, and sending either without a mode gives you webhook mode). The envelope carries event, request_id, job_id, status and payload.artifacts[], and two rules follow from it:
- The asymmetry that matters: on Sume a canceled job also arrives with
status: "ERROR". - If your fal code treats
ERRORas a failure to alert on, canceled Sume jobs will page you. Branch oneventfirst.
| Question | fal | Sume |
|---|---|---|
| Outcome field | status: OK or ERROR | status: OK; failed and canceled use ERROR with an error object |
| Event name | Not described on the queue page | job.completed, job.failed, job.canceled |
| Job status vocabulary | IN_QUEUE, IN_PROGRESS, COMPLETED | queued, processing, completed, failed, canceled |
| Progress events | Not described on the queue page | None, terminal events only |
| Result location | Result stored, retrievable from the result URL | payload.artifacts[] with media URLs |
How do I write one handler that reads both?
Keep the verification step provider specific and normalize after it. This Python function refuses an empty secret and checks the Sume signature (sume-v1= HMAC SHA 256 over timestamp.raw_body, five minute tolerance as the docs suggest), then maps the event to your own state.
import hashlib, hmac, json, time
def verify_sume(raw: bytes, ts: str, header: str, secret: str) -> bool:
if not secret:
return False
try:
t = int(ts)
except ValueError:
return False
if abs(time.time() - t) > 300:
return False
mac = hmac.new(secret.encode(), ts.encode() + b"." + raw, hashlib.sha256)
want = "sume-v1=" + mac.hexdigest()
return any(hmac.compare_digest(want, e.strip()) for e in header.split(","))
def normalize(raw: bytes) -> str:
body = json.loads(raw)
return {"job.completed": "done", "job.failed": "failed",
"job.canceled": "canceled"}.get(body.get("event"), "ignore")What should I keep as a fallback?
Sume's docs recommend keeping a polling path alongside webhooks: GET /v1/jobs/{id}/status until terminal: true, then GET /v1/jobs/{id}/result. During a signing-secret rotation the signature header carries one sume-v1= entry per live secret, newest first, which the loop above handles with any.
Sume also exposes x-sume-webhook-secret-fingerprint on every delivery so you can compare it with the dashboard when a signature fails, without sending the secret anywhere. Read the delivery details in Sume webhooks, and the broader differences in Sume vs fal.
Sources
Related posts
More in Comparisons
- Fastest AI image model API: what the October 2026 claims say
Flare says half the latency of GPT Image 2, MAI-Image-2.6-Flash says 2.8x faster than GPT-Image-2-Medium. None are comparable. A timing script for Sume models.
- FFmpeg whisper filter vs a hosted transcript call for video
FFmpeg's whisper filter needs whisper.cpp and a model file you manage. Sume's video-inspect transcribe returns words and sentence segments for $0.01 a minute.
- FFmpeg xfade has 59 transitions: which does Sume Timeline take?
FFmpeg's xfade page lists 59 transition values, including custom. Sume Timeline 1.0 accepts six: fade, wipeleft, wiperight, slideup, slidedown and dissolve.
- Flow Agent makes several video variations at once: the API way
Google Flow's Agent toggle can create multiple variations of a video in one ask. Sume has no agent toggle in its API; it has queued jobs and Format bulk runs.
Written by Sume