Webhooks
Receive and verify export start, completion, and failure events on your server.
Use webhooks to receive export events without continuously polling. You can still fetch the task to confirm its latest state.
Configure a callback
Configure a webhook secret in Indream before creating an export with a callbackUrl. Include an HTTPS URL your server can receive requests at. callbackHeaders optionally adds static headers to the callback.
Both stateless and project export requests accept these fields. Export creation fails if a callback is requested without a configured webhook secret.
Handle events
eventType | Meaning |
|---|---|
EXPORT_STARTED | Processing has started. |
EXPORT_COMPLETED | The export completed successfully. |
EXPORT_FAILED | The export failed. |
Completion and failure are alternative outcomes, not successive steps. There is no cancellation event; use the cancel response or GET /v1/exports/{taskId} to observe cancellation.
Each payload contains eventType, occurredAt, and task. The task has the same public fields as the export detail response, including projectId, filename, output information, and billing usage.
{
"eventType": "EXPORT_COMPLETED",
"occurredAt": "2026-09-25T10:00:05.000Z",
"task": {
"taskId": "565693ff-e120-4326-94f8-5ffe17543101",
"projectId": null,
"createdByApiKeyId": "e356f320-bf36-45a4-afae-96bacaab6a45",
"clientTaskId": null,
"status": "COMPLETED",
"progress": 100,
"error": null,
"outputUrl": "https://example.com/hello-indream.mp4",
"filename": "hello-indream.mp4",
"durationSeconds": 5,
"billedStandardSeconds": 5,
"chargedCredits": "8.333333333333",
"callbackUrl": "https://example.com/indream-events",
"createdAt": "2026-09-25T10:00:00.000Z",
"completedAt": "2026-09-25T10:00:05.000Z"
}
}Verify the signature
Callbacks include X-Indream-Timestamp (Unix seconds) and X-Indream-Signature (a lowercase hexadecimal HMAC-SHA256 signature).
The signed input is the timestamp, a period, and the exact raw request body. Verify it with the webhook secret before parsing or processing the payload. Do not reserialize JSON for verification.
This JavaScript handler uses the SDK's verification and parsing helpers:
import { parseExportWebhookEvent, verifyExportWebhookRequest } from '@indreamai/client'
export async function receiveExport(request, webhookSecret, saveEvent) {
const rawBody = await request.text()
const valid = await verifyExportWebhookRequest({
webhookSecret,
rawBody,
headers: request.headers,
maxSkewSeconds: 300,
})
if (!valid) return new Response('Invalid webhook signature.', { status: 401 })
let event
try {
event = parseExportWebhookEvent(JSON.parse(rawBody))
} catch {
return new Response('Invalid webhook payload.', { status: 400 })
}
await saveEvent(event)
return new Response(null, { status: 204 })
}Provide webhookSecret from your server's secret manager and a saveEvent function that durably records or enqueues the event. The Python SDK includes the equivalent verify_export_webhook_request helper.
Process deliveries reliably
Treat deliveries as potentially repeated. Verify the signature and timestamp window, persist or enqueue the event durably, and then return a 2xx response. Make business processing idempotent for the same task and event type.
Keep your receiver fast and process expensive work separately. Before a consequential action, fetch the latest task if you need its current status rather than the event's snapshot. Download and save completed files you need to retain.
Last updated on