Skip to main content
Instead of polling, configure a webhook endpoint once and TrueFan will POST to it whenever a request you submitted finishes — one delivery per request, regardless of how many rows it contained.

1. Create an endpoint

Response
secret is returned exactly once, in the create response — the same reveal-once posture as the API key itself. Store it now; you’ll need it to verify incoming deliveries.

2. Verify incoming requests

Every delivery is signed with HMAC-SHA256 over the raw request body, using the endpoint’s secret:
Compute the HMAC over the raw, unparsed request body — not a re-serialized version of the parsed JSON, which can differ in key order or whitespace and produce a mismatched signature.

Request format

header
sha256=<hex-encoded HMAC-SHA256 digest> of the raw body, using your endpoint’s secret.
header
The event type — same value as the event field in the body.

bulk_job.completed

Fired once every row in a request has reached a terminal state — whether you sent one row or a thousand, this fires exactly once per request, never once per row.
This payload is intentionally just the summary counts, not the full result list. Download the complete batch — every row’s result_video_url, external_id, and generation_id — from Download CSV export; csv_export_path above is that exact path, relative to your API host, ready to fetch as soon as this webhook arrives.

Delivery & retries

Your endpoint should return a 2xx status within 10 seconds. Anything else is treated as a failure:
  • Retried with exponential backoff — 30s, 60s, 120s, … up to a 1-hour cap — for up to 6 attempts.
  • After the final attempt fails, the delivery is marked dead and not retried again.
Check delivery history — including response codes and final status — via List webhook deliveries:
If a delivery shows as dead, your endpoint was unreachable or erroring for the entire retry window — check your own logs for that time range, then fall back to polling for that specific job to recover the result.

Removing an endpoint