Webhooks
Manage a workspace's webhook endpoints with a key that holds webhook:write — every fl_live_… key holds it (API keys are full access); an MCP access token never can. For the event catalogue, payload shapes and how to verify a delivery's signature, see Webhooks.
secret (whsec_…) — store it then, it is never returned again.GET /v1/webhooks
/v1/webhooksscope: webhook:writeList the workspace's webhook endpoints. Never includes the signing secret.
curl https://buildonce.app/v1/webhooks \ -H "Authorization: Bearer fl_live_YOUR_API_KEY"
{
"items": [ {
"id": "whe_4hd9s0k2mq7z",
"url": "https://example.com/hooks/buildonce",
"description": "Production server",
"events": ["render.completed", "template.updated"],
"enabled": true,
"disabledReason": null,
"disabledAt": null,
"failureCount": 0,
"createdAt": "2026-08-01T12:00:00.000Z",
"updatedAt": "2026-08-01T12:00:00.000Z"
} /* … */ ]
}POST /v1/webhooks
/v1/webhooksscope: webhook:writeCreate an endpoint. Up to 10 per workspace (403 WEBHOOK_ENDPOINT_LIMIT beyond that).
| Param | Type | Notes |
|---|---|---|
| url | string (required) | https only, 1–2048 chars. Rejected if it resolves to a private/internal address (WEBHOOK_URL_BLOCKED). |
| description | string | Up to 200 chars. |
| events | string[] (required) | One or more event names from the catalogue — at least one, no duplicates. |
curl -X POST https://buildonce.app/v1/webhooks \
-H "Authorization: Bearer fl_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/hooks/buildonce",
"description": "Production server",
"events": ["render.completed", "template.updated"]
}'{
"id": "whe_4hd9s0k2mq7z",
"url": "https://example.com/hooks/buildonce",
"description": "Production server",
"events": ["render.completed", "template.updated"],
"enabled": true,
"disabledReason": null,
"disabledAt": null,
"failureCount": 0,
"createdAt": "2026-08-01T12:00:00.000Z",
"updatedAt": "2026-08-01T12:00:00.000Z",
"secret": "whsec_zx3k…9fq1"
}GET /v1/webhooks/:endpointId
/v1/webhooks/:endpointIdscope: webhook:writeGet one webhook endpoint. Never includes the signing secret.
curl https://buildonce.app/v1/webhooks/whe_4hd9s0k2mq7z \ -H "Authorization: Bearer fl_live_YOUR_API_KEY"
{
"id": "whe_4hd9s0k2mq7z",
"url": "https://example.com/hooks/buildonce",
"description": "Production server",
"events": ["render.completed", "template.updated"],
"enabled": true,
"disabledReason": null,
"disabledAt": null,
"failureCount": 0,
"createdAt": "2026-08-01T12:00:00.000Z",
"updatedAt": "2026-08-01T12:00:00.000Z"
}PATCH /v1/webhooks/:endpointId
/v1/webhooks/:endpointIdscope: webhook:writeChange the URL, description, subscribed events, or turn the endpoint on/off.
| Param | Type | Notes |
|---|---|---|
| url | string | Same validation as create. |
| description | string | An empty string clears it. |
| events | string[] | Replaces the full subscribed set. |
| enabled | boolean | Setting true clears an auto-disable and resets the failure count. Setting false records a reason and marks waiting deliveries dead. |
curl -X PATCH https://buildonce.app/v1/webhooks/whe_4hd9s0k2mq7z \
-H "Authorization: Bearer fl_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "events": ["render.completed", "render.failed"] }'{
"id": "whe_4hd9s0k2mq7z",
"url": "https://example.com/hooks/buildonce",
"description": "Production server",
"events": ["render.completed", "template.updated"],
"enabled": true,
"disabledReason": null,
"disabledAt": null,
"failureCount": 0,
"createdAt": "2026-08-01T12:00:00.000Z",
"updatedAt": "2026-08-01T12:00:00.000Z"
}DELETE /v1/webhooks/:endpointId
/v1/webhooks/:endpointIdscope: webhook:writeDelete an endpoint and its delivery log.
curl -X DELETE https://buildonce.app/v1/webhooks/whe_4hd9s0k2mq7z \ -H "Authorization: Bearer fl_live_YOUR_API_KEY"
POST /v1/webhooks/:endpointId/rotate-secret
/v1/webhooks/:endpointId/rotate-secretscope: webhook:writeReplace the signing secret. The new one is shown once, in this response only — switch your verification code to it before the old secret stops being useful.
curl -X POST https://buildonce.app/v1/webhooks/whe_4hd9s0k2mq7z/rotate-secret \ -H "Authorization: Bearer fl_live_YOUR_API_KEY"
{
"id": "whe_4hd9s0k2mq7z",
"secret": "whsec_pq8m…2zt7"
}POST /v1/webhooks/:endpointId/test
/v1/webhooks/:endpointId/testscope: webhook:writeSend a signed webhook.test event now, one attempt, no retry. Throttled to 10/min per caller.
curl -X POST https://buildonce.app/v1/webhooks/whe_4hd9s0k2mq7z/test \ -H "Authorization: Bearer fl_live_YOUR_API_KEY"
{
"id": "whd_6tq2k9m4xa1b",
"event": "render.completed",
"eventId": "evt_8m2kq4x7tb1c",
"status": "succeeded",
"attempt": 1,
"nextAttemptAt": null,
"responseStatus": 200,
"responseBody": "ok",
"error": null,
"durationMs": 143,
"deliveredAt": "2026-09-28T12:05:00.400Z",
"createdAt": "2026-09-28T12:05:00.000Z"
}GET /v1/webhooks/:endpointId/deliveries
/v1/webhooks/:endpointId/deliveriesscope: webhook:writeOne endpoint's delivery log, newest first — includes payload, response and timing for each attempt.
| Param | Type | Notes |
|---|---|---|
| page | number | Defaults to 1. |
| limit | number | Defaults to 20, max 100. |
| status | "pending" | "succeeded" | "failed" | "dead" | Restrict to one delivery status. |
curl "https://buildonce.app/v1/webhooks/whe_4hd9s0k2mq7z/deliveries?status=failed" \ -H "Authorization: Bearer fl_live_YOUR_API_KEY"
{
"items": [ {
"id": "whd_6tq2k9m4xa1b",
"event": "render.completed",
"eventId": "evt_8m2kq4x7tb1c",
"status": "succeeded",
"attempt": 1,
"nextAttemptAt": null,
"responseStatus": 200,
"responseBody": "ok",
"error": null,
"durationMs": 143,
"deliveredAt": "2026-09-28T12:05:00.400Z",
"createdAt": "2026-09-28T12:05:00.000Z"
} /* … */ ],
"total": 214,
"page": 1,
"limit": 20
}POST /v1/webhooks/:endpointId/deliveries/:deliveryId/redeliver
/v1/webhooks/:endpointId/deliveries/:deliveryId/redeliverscope: webhook:writeSend a delivery again — same delivery id, same signed bytes — as a fresh run of retries. Throttled to 10/min per caller.
curl -X POST https://buildonce.app/v1/webhooks/whe_4hd9s0k2mq7z/deliveries/whd_6tq2k9m4xa1b/redeliver \ -H "Authorization: Bearer fl_live_YOUR_API_KEY"
WEBHOOK_ENDPOINT_DISABLED while the endpoint is off — turn it back on first.Errors
| Param | Type | Notes |
|---|---|---|
| 403 WEBHOOK_ENDPOINT_LIMIT | The workspace already has 10 endpoints. | |
| 404 WEBHOOK_ENDPOINT_NOT_FOUND | Unknown id, or it belongs to another workspace. | |
| 400 WEBHOOK_URL_BLOCKED | The URL is not https, carries credentials, or resolves to a private/internal address. | |
| 409 WEBHOOK_ENDPOINT_DISABLED | Redeliver was called while the endpoint is turned off. |
Was this page helpful?