Is there an Instagram webhook when a Reel finishes processing?
Instagram's webhook field list has no Reel-finished event, so poll status_code. Sume job webhooks are signed; verify them with a secret that cannot be empty.

The Instagram webhooks page we read lists no field for a Reel container finishing, so poll GET /<IG_CONTAINER_ID>?fields=status_code until it returns FINISHED. Sume is different on its own side: job webhooks fire on job.completed, job.failed and job.canceled, and you should verify their signature before trusting them.
Instagram facts come from Meta's webhooks page and publishing guide, read 2026-10-02. Sume facts come from the webhooks docs. The absence of an event is our reading of that page's list, not a statement from Meta.
Which fields can an Instagram webhook subscribe to?
Meta's page lists these fields: comments, live_comments, mentions, messages, message_echoes, message_reactions, messaging_handover, messaging_postbacks, messaging_seen and story_insights. None of them is about publishing a Reel.
Setup is an HTTPS endpoint, webhooks configured in the App Dashboard, subscriptions enabled through /me/subscribed_apps, and a test. Verification is a GET carrying hub.mode=subscribe, hub.challenge and hub.verify_token; you check the token and echo the challenge back. Payloads are signed with SHA256 in X-Hub-Signature-256, prefixed sha256=.
- Subscribe to comments, mentions or messages if you need them.
- Do not wait for a publish-finished push; there is none on the list.
- Poll status_code and handle ERROR and EXPIRED.
How do I poll a container without hammering it?
Poll the container on a gentle interval and stop on a terminal state. Meta's status codes are EXPIRED, ERROR, FINISHED, IN_PROGRESS and PUBLISHED. Only call media_publish after FINISHED. The details of backoff are covered in container status polling.
| status_code | Meaning for your code | Action |
|---|---|---|
| IN_PROGRESS | Still processing | Wait and poll again |
| FINISHED | Ready | Call media_publish |
| PUBLISHED | Already published | Stop; do not publish twice |
| ERROR | Processing failed | Log it, fix the file, create a new container |
| EXPIRED | Container no longer usable | Create a new container |
What do Sume webhooks send, and how do I verify them?
With mode: "webhook" and a public HTTPS webhook_url, Sume sends terminal events only. When signing is configured it signs <timestamp>.<raw_body> with HMAC SHA 256 and sends x-sume-webhook-timestamp and x-sume-webhook-signature: sume-v1=<hex>. During a secret rotation the header can carry several comma-separated entries; accept any match. The docs suggest rejecting timestamps outside about five minutes.
This verifier refuses an empty secret, checks the timestamp window and compares in constant time.
import hashlib, hmac, time
def verify(raw: bytes, ts: str, header: str, secret: str,
tolerance: int = 300) -> bool:
if not secret:
return False # never verify against an empty secret
try:
t = int(ts)
except ValueError:
return False
if abs(int(time.time()) - t) > tolerance:
return False
mac = hmac.new(secret.encode(), f"{t}.".encode() + raw,
hashlib.sha256).hexdigest()
want = f"sume-v1={mac}"
ok = False
for entry in header.split(","):
ok |= hmac.compare_digest(entry.strip(), want)
return okWhat should I still keep as a fallback?
Keep polling GET /v1/jobs/:id/status as the fallback for Sume, as the docs advise alongside webhooks. Read your signing secret from the dashboard's Webhooks tab or GET /v1/webhooks/signing-secret; never hard-code it. If a signature fails, compare x-sume-webhook-secret-fingerprint with the fingerprint in the dashboard instead of sending the secret anywhere.
A clean pipeline is: Sume webhook says the MP4 is ready, you create the Instagram container, you poll status_code, then publish. Two different signals, two different mechanisms.
What mistakes should I avoid?
Do not publish on a timer. Waiting a fixed 60 seconds and calling media_publish works until the day processing takes longer. Poll the status instead and give up after a deadline you choose, then log the container id.
Do not skip the empty-secret check. A verifier that hashes with an empty key accepts forged requests whenever the environment variable is missing, which is a quiet failure. The version above fails closed. Also parse the raw body, not re-serialised JSON, because the signature covers the exact bytes.
Sources
Related posts
More in Developers
- Instagram Reels resumable upload (rupload) vs a public video_url
Instagram Reels can publish from a public video_url or a resumable rupload. Resumable is Facebook Login only; check your Sume media link is reachable first.
- reels_skip_rate: what the 3-second metric means and how to test hooks
reels_skip_rate is the share of Reel views that skipped in the first 3 seconds. Pull the opening frames and words with Sume video inspect to compare hooks.
- Reels views vs crossposted_views vs facebook_views: which to report
Instagram Reels insights list views, crossposted_views and facebook_views separately. Which to report, and how to trace Sume-made variants.
- Clickable transcript from Sume STT word timestamps in Python
Turn a Sume speech-to-text result into HTML where each word seeks the audio player to its start time. Runnable Python, with the result envelope handled safely.
Written by Sume