Webhooks API
These endpoints manage outbound webhooks: subscriptions that make Loha POST a
signed event to your URL when a build finishes. For the concepts, payload shape, and
signature verification, see the Outbound webhooks guide.
All requests authenticate with a workspace-scoped bearer token and are bound to that token's workspace.
Scopes
| Scope | Grants |
|---|---|
webhooks:read | List/read webhooks and their delivery history |
webhooks:write | Create, update, rotate, ping, delete, and redeliver |
webhooks:read is available to members and up; webhooks:write to admins/owners.
Endpoints
| Method | Path | Scope | Purpose |
|---|---|---|---|
| GET | /api/v1/webhooks | webhooks:read | List the workspace's webhooks |
| POST | /api/v1/webhooks | webhooks:write | Create a webhook (returns secret once) |
| GET | /api/v1/webhooks/{id} | webhooks:read | Inspect a webhook |
| PATCH | /api/v1/webhooks/{id} | webhooks:write | Update url/scope/status/enabled |
| DELETE | /api/v1/webhooks/{id} | webhooks:write | Delete a webhook |
| POST | /api/v1/webhooks/{id}/rotate-secret | webhooks:write | Rotate the signing secret (returns once) |
| POST | /api/v1/webhooks/{id}/ping | webhooks:write | Queue a synthetic ping delivery |
| GET | /api/v1/webhooks/{id}/deliveries | webhooks:read | Recent delivery attempts |
| POST | /api/v1/webhooks/{id}/deliveries/{deliveryId}/redeliver | webhooks:write | Re-queue a delivery |
| GET | /api/v1/triggers/{id}/webhooks | webhooks:read | List webhooks scoped to a trigger |
| POST | /api/v1/triggers/{id}/webhooks | webhooks:write | Create one bound to a trigger |
Create
curl -X POST https://app.loha.longtumlab.com/api/v1/webhooks \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/hooks/loha",
"triggerId": "trg_…",
"statusFilter": ["FAILED", "TIMEOUT", "CANCELLED"],
"description": "Page on-call when prod deploys break"
}'
| Field | Type | Required | Notes |
|---|---|---|---|
url | string | yes | Public HTTPS endpoint. Private/metadata addresses are rejected. |
triggerId | string | no | Scope to one trigger. Omit for workspace-wide. |
statusFilter | string[] | no | Subset of SUCCESS, FAILED, TIMEOUT, CANCELLED. Omit for all. |
eventTypes | string[] | no | Defaults to ["com.loha.build.completed.v1"]. |
description | string | no | Free-text label (≤ 280 chars). |
The response returns the created webhook plus the plaintext secret once. It is
never returned again:
{
"webhook": {
"id": "wh_…",
"triggerId": "trg_…",
"url": "https://example.com/hooks/loha",
"eventTypes": ["com.loha.build.completed.v1"],
"statusFilter": ["FAILED", "TIMEOUT", "CANCELLED"],
"enabled": true,
"createdAt": "2026-06-17T04:00:00.000Z"
},
"secret": "whsec_…"
}
Update
PATCH /api/v1/webhooks/{id} accepts any of url, triggerId (or null to clear the
scope), statusFilter (or null for all), description, and enabled. Disabling a
webhook stops deliveries without deleting its history.
Rotate the secret
curl -X POST https://app.loha.longtumlab.com/api/v1/webhooks/$ID/rotate-secret \
-H "Authorization: Bearer $TOKEN"
# → { "secret": "whsec_…" } (shown once; deliveries use it immediately)
Deliveries
curl https://app.loha.longtumlab.com/api/v1/webhooks/$ID/deliveries \
-H "Authorization: Bearer $TOKEN"
Returns recent attempts (newest first) with status
(pending · delivered · failed · dead), attempts, responseStatus,
lastError, and timestamps. Re-queue one with
POST /api/v1/webhooks/{id}/deliveries/{deliveryId}/redeliver.
See Errors for the shared status-code semantics. Webhook
endpoints add 400 for an invalid body or a URL that fails the security checks.