Webhooks
Overview
Firework Webhooks notify your application in real time when events occur on the platform. Instead of polling for changes, your server receives HTTP POST callbacks as events happen.
How It Works
┌──────────────┐ Event occurs ┌──────────────┐
│ Firework │ ──────────────────────────▶ │ Your Server │
│ Platform │ HTTP POST with signed JSON │ (Webhook │
│ │ │ Endpoint) │
│ │ ◀────────────────────────── │ │
│ │ 2xx response │ │
└──────────────┘ └──────────────┘An event occurs on Firework (e.g., video finishes processing)
Firework sends an HTTP POST request to your configured callback URL
The request includes a JSON payload describing the event and an HMAC signature for verification
Your server processes the event and responds with a 2xx status code
Available Event Types
This document covers video-related events only. Additional event types (e.g., livestream) may be documented separately.
video_created
Video created — transcoding complete or failed
video_updated
Video metadata or state changed after creation
video_import_failed
Async URL import failed (download error, validation error)
Configuration
Webhook endpoints are not self-service at this time. To set up webhooks for your business:
Contact the Firework IS team and provide:
Callback URL
The HTTPS endpoint on your server that will receive webhook events
https://yourapp.com/webhooks/firework
Event types
Which event types you want to subscribe to
video_created, video_updated, video_import_failed
Business ID
Your Firework business identifier
AbCdEfG
After configuration, the IS team will provide you with:
Endpoint secret — Used to verify webhook signatures (see Signature Verification)
Important: Store your endpoint secret securely. If you suspect it has been compromised, contact the IS team to rotate it.
Delivery
Delivery Mechanics
HTTP Method
POST
Content-Type
application/json
Timeout
30 seconds per delivery attempt
Signature
HMAC-SHA256 in FW-Webhooks-Signature header
Success Criteria
A delivery is considered successful when your server responds with:
200
OK
202
Accepted
204
No Content
Any other status code (or a timeout) is treated as a failure and triggers a retry.
Retry Policy
Failed deliveries are retried with increasing backoff:
1–3
1 hour
4–6
24 hours
Maximum 6 attempts per event delivery. After all attempts are exhausted, the event is dropped.
Signature Verification
Every webhook request includes an FW-Webhooks-Signature header. You must verify this signature before processing the payload to ensure the request is authentic.
Header Format
t
Unix timestamp in milliseconds when the signature was generated
v1
Base64-encoded HMAC-SHA256 signature
Verification Steps
Extract the
t(timestamp) andv1(signature) values from the headerConstruct the signed payload string:
{t}.{raw_request_body}Compute HMAC-SHA256 of the signed payload using your endpoint secret
Base64-encode the result
Compare your computed signature with
v1using a constant-time comparison
Worked Example
Given:
Endpoint secret (provided by IS team):
a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2Signature header received:
Raw request body received:
Step 1 — Parse the header:
Step 2 — Concatenate t + . + raw request body:
Step 3 — HMAC-SHA256 this string using your endpoint secret as the key.
Step 4 — Base64-encode the HMAC result.
Step 5 — Compare your Base64 result with v1. If they match, the webhook is authentic.
Important: Use the raw request body exactly as received (do not re-serialize the JSON). JSON key ordering and whitespace must match exactly for the signature to verify.
Tip: Optionally check the timestamp
tto reject stale requests (e.g., older than 5 minutes) to prevent replay attacks.
Example: Python
Example: Node.js
Example: Elixir
Event Payload
Envelope Schema
All webhook events share the same envelope structure:
event_type
string
Event type identifier (e.g., "video_created")
version
string
Payload schema version (currently "2023-06-06")
created
integer
Unix timestamp (seconds) when the event was generated
business_id
string
Encoded ID of the business that owns the resource
data
object
Event-specific payload — varies by event type (see Section 6)
Video Data Object
Used by video_created and video_updated events. The payload mirrors GET /api/v1/videos/{id} with additional webhook-specific fields (status, import_id), so consumers do not need a follow-up GET call.
id
string
❌
Encoded video ID
status
string
❌
Current video status (see status values below)
import_id
string
✅
Encoded import job ID. Present only for videos created via async URL import.
access
string
❌
Video visibility: "public" or "private"
audio_disabled
boolean
❌
Whether the video audio is muted
caption
string
✅
Video title/caption
description
string
✅
Video description
hashtags
string[]
❌
List of hashtags (empty array if none)
archived_at
string
✅
ISO 8601 timestamp if archived, null otherwise
product_ids
string[]
❌
List of encoded product IDs tagged on the video (empty array if none)
custom_fields
object
❌
Key-value map of custom metadata fields (empty object if none)
display_social_attributions
boolean
✅
Whether to display social attribution overlays
external_media
object
✅
External media source info (see below), or null
External Media Object
Present only when the video was imported from an external source.
source
string
Platform name (e.g., "instagram")
username
string
Original creator's username
url
string
Original content URL
Video Status Values
pending
Video is being transcoded — not yet ready
approved
Transcoding complete — video is ready for playback
errored
Transcoding failed
Note:
video_createdfires with"approved"status on successful transcoding, or"errored"status on transcoding failure.video_updatedonly fires for videos that have already received avideo_createdevent.
Import Data Object
Used by video_import_failed events. No video record exists when this event fires. Use GET /api/v1/videos/imports/{import_id} to fetch import job details.
import_id
string
❌
Encoded import job ID
reason
string
❌
Machine-readable failure code (see table below)
Import Failure Reason Values
download_failed
Could not download the file (timeout, 404, network error)
invalid_format
File is not a supported video format
duration_out_of_range
Video shorter than 3s or longer than 1h
file_size_exceeded
File exceeds 5GB limit
internal_error
Unexpected server-side error
Video Events
video_created
video_createdFired when a video's transcoding completes (successfully or with failure). The data field contains the full video resource (same fields as GET /api/v1/videos/{id}).
When it fires:
After transcoding completes and the video status transitions to
"approved"— the video is ready for playbackAfter transcoding fails and the video status transitions to
"errored"
Example — file upload / S3 key:
Example — async URL import:
If the status is
"approved", the video is ready for playback. If the status is"errored", transcoding failed. Ifimport_idis present, you can also checkGET /api/v1/videos/imports/{import_id}for import job details.
Example — transcoding failed:
video_updated
video_updatedFired when a video's state or metadata changes after a video_created event has been sent. The data field contains the full video resource after the update (same fields as GET /api/v1/videos/{id}), so consumers do not need a follow-up GET call.
When it fires:
After a metadata update (caption, description, access, hashtags, products, poster, etc.)
After any other video state change (admin actions, automations, AICC, etc.)
This event only fires for videos that have already received a
video_createdevent (i.e., videos with"approved"status). It does not fire for transcoding failures — those are covered byvideo_createdwith"errored"status.
Example — metadata update via PATCH:
If
import_idis present, you can also checkGET /api/v1/videos/imports/{import_id}for import job details.
video_import_failed
video_import_failedFired when an async URL import fails before a video record is created. This covers failures during download, URL validation, or file validation.
When it fires:
Download from the source URL fails (timeout, 404, network error)
Downloaded file fails validation (invalid format, duration out of range, file size exceeded)
This event only applies to async URL imports (
POST /api/v1/videoswith"async": true). It does not fire for transcoding failures — those are covered byvideo_createdwith"errored"status.
Example — download failed:
Example — invalid file:
Use
GET /api/v1/videos/imports/{import_id}to fetch the import job details.
Best Practices
Respond Quickly
Your webhook endpoint should return a 2xx response within 30 seconds. If you need to perform lengthy processing, acknowledge the webhook immediately and process asynchronously.
Verify Signatures
Always verify the FW-Webhooks-Signature header before processing webhook payloads. This protects against spoofed requests. See Section Signature Verification for implementation details.
Handle Duplicates
In rare cases, the same event may be delivered more than once. Design your handler to be idempotent — processing the same event twice should not cause issues.
Deduplication key: event_type + data.id + created (for video_import_failed, use data.import_id instead of data.id)
Use HTTPS
Always use an HTTPS callback URL. Firework will not deliver webhooks to plain HTTP endpoints.
Last updated
Was this helpful?