Webhooks
Webhooks deliver real-time events from Freedam to an HTTPS endpoint you control. Use them in place of polling — when an asset is uploaded, a share is created, or an operation finishes, Freedam will POST a JSON payload to your URL within seconds.
Lifecycle
- Register an endpoint with
POST /v1/webhooks. Freedam returns a signing secret (shown once). - Verify every incoming request using the
X-Freedam-SignatureHMAC header (see below). - Acknowledge with a
2xxresponse within 10 seconds. Anything else is treated as a failure. - Failed deliveries are retried with exponential back-off (1m, 5m, 30m, 2h, 12h). After repeated failures the endpoint is auto-disabled.
Endpoints
| Method | Path | Description |
|---|---|---|
GET |
/v1/webhooks |
List endpoints registered by the caller. |
POST |
/v1/webhooks |
Create an endpoint. |
GET |
/v1/webhooks/{id} |
Read endpoint config. |
PUT |
/v1/webhooks/{id} |
Update url, events, or active state. |
DELETE |
/v1/webhooks/{id} |
Permanently delete an endpoint. |
POST |
/v1/webhooks/{id}/test |
Send a synthetic webhook.test event. |
GET |
/v1/webhooks/{id}/deliveries |
List recent deliveries with status & latency. |
POST |
/v1/webhooks/{id}/rotate-secret |
Generate a new signing secret. |
Creating an endpoint
curl -X POST https://your-freedam-instance.com/api/v1/webhooks \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/freedam/webhook",
"events": ["asset.created", "asset.updated", "share.created"],
"description": "Production pipeline"
}'
The response includes the signing_secret field once. Store it server-side — it cannot be retrieved later. If you lose it, call POST /v1/webhooks/{id}/rotate-secret.
Event payload shape
{
"id": "evt_01HKAB...",
"type": "asset.created",
"created_at": "2026-05-06T10:00:00.000Z",
"data": {
"asset": {
"gaid": "ast_01HKAB...",
"title": "Hero shot Q3",
"mime_type": "image/jpeg",
"...": "..."
}
}
}
Verifying signatures
Every delivery includes:
X-Freedam-Signature: t=<unix-timestamp>,v1=<hex-hmac-sha256>X-Freedam-Event: <event-type>X-Freedam-Delivery: <delivery-uuid>
Compute HMAC-SHA256(secret, "{timestamp}.{raw-body}") and compare it to v1 in constant time. Reject the request if the timestamp is older than 5 minutes — this prevents replay attacks.
The TypeScript SDK ships a helper:
import { verifyWebhookSignature } from '@freedam/sdk';
const ok = verifyWebhookSignature({
payload: rawBodyString,
header: req.headers['x-freedam-signature'] as string,
secret: process.env.FREEDAM_WEBHOOK_SECRET!,
toleranceSeconds: 300,
});
if (!ok) {
return res.status(400).end();
}
Available events
| Event | Triggered by |
|---|---|
asset.created |
A new asset is ingested and ready. |
asset.updated |
Asset metadata changes. |
asset.deleted |
Asset is soft-deleted. |
asset.restored |
Soft-deleted asset is restored. |
collection.created |
A collection is created. |
collection.updated |
A collection's name/description changes. |
collection.deleted |
A collection is deleted. |
share.created |
A share link is created. |
share.revoked |
A share is revoked or expired. |
upload.batch.completed |
An ingestion batch finishes processing. |
operation.completed |
An async operation reaches a terminal state. |
webhook.test |
Manually triggered via POST /webhooks/{id}/test. |
Inspecting deliveries
GET /v1/webhooks/{id}/deliveries returns the most recent attempts (status code, latency, response excerpt) so you can debug your handler without grepping production logs. The same data is visible in the admin UI under API → Webhooks.
Disabling and rotating
Set is_active: false via PUT to silence an endpoint without losing its config. Rotate the secret when a teammate leaves or after a suspected leak — old signatures stop verifying immediately.