Webhooks
Inbound webhook receivers, secret rotation, and delivery history.
Webhooks in Alumia are inbound receivers: each webhook resource owns a public URL that third-party systems can POST to. Alumia validates the signature, records the event, and routes it to org-level handlers. The same record also stores an optional outbound url so the platform can forward events to your service.
Inbound webhook POST bodies are capped at 256 KB by default (lib/api/request-body-limits.ts). Management routes (POST / PATCH / DELETE on /webhooks and /webhooks/:id, plus test/retry/rotate) require a stepped-up browser session and use the standard 128 KB JSON cap. API keys are rejected with 403 "Webhook management requires a browser session".
Endpoints
| Method | Path | Description |
|---|---|---|
GET | /api/v1/webhooks | List webhooks in the org. |
POST | /api/v1/webhooks | Create a webhook and receive its plaintext secret. |
GET | /api/v1/webhooks/:id | Fetch one webhook. |
PATCH | /api/v1/webhooks/:id | Update name, URL, source, description, events, status. |
DELETE | /api/v1/webhooks/:id | Hard-delete a webhook. |
POST | /api/v1/webhooks/:id/rotate | Rotate the signing secret; returns the new plaintext once. |
GET | /api/v1/webhooks/:id/events | List recorded events for one webhook. |
GET | /api/v1/webhooks/:id/deliveries | List outbound delivery attempts. |
GET | /api/v1/webhooks/events | Recent events across all webhooks in the org. |
GET | /api/v1/webhooks/event-types | Supported event types (project, agent, task, file, session, billing). |
POST | /api/v1/webhooks/events/:eventId/retry | Re-queue a failed delivery for retry. |
POST | /api/v1/webhooks/test | Send a synthetic event for testing. |
POST | /api/v1/webhooks/verify | Validate a signed payload. |
POST | /api/v1/webhooks/receive/:webhookId | Public receive endpoint (no auth header). |
POST | /api/v1/webhooks/linear | Built-in Linear receiver. |
List
GET /api/v1/webhooks returns webhook records ordered by createdAt desc. Each item:
{
"id": "uuid",
"name": "string",
"url": "https://...",
"source": "custom",
"description": "string|null",
"events": ["..."],
"status": "active",
"enabled": true,
"deliveryCount": 0,
"lastDeliveryAt": null,
"createdAt": "...",
"updatedAt": "...",
"receiveUrl": "https://alumia.com/api/v1/webhooks/receive/<id>"
}
receiveUrl is computed from the request origin and is the URL third parties should POST to.
Create
POST /api/v1/webhooks
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | 1–120 chars. |
url | string | null | no | Outbound forwarding URL. Must be a public HTTP(S) URL; SSRF-protected. Defaults to receiveUrl if omitted. |
events | string[] | no | Event-type allowlist; normalized server-side. |
source | string | no | Up to 100 chars. Defaults to custom. |
description | string | no | Up to 2,000 chars. |
The response includes the plaintext secret once. Store it securely; the server only retains an encrypted copy and a hash.
Create and rotate webhooks from the dashboard or another browser-session flow after step-up. API-key curl requests cannot create or rotate webhook secrets.
Update
PATCH /api/v1/webhooks/:id accepts any subset of name, url, source, description, events, enabled, status ("active" or "paused"/"disabled"). Setting url to null or "" resets it to the receive URL. Setting status keeps enabled in sync.
Delete
DELETE /api/v1/webhooks/:id performs a hard delete. Returns { "deleted": true }.
Rotate secret
POST /api/v1/webhooks/:id/rotate generates a new secret pair, persists the encrypted form and hash, and returns the new plaintext once. Old signatures stop verifying immediately.
Events and deliveries
GET /api/v1/webhooks/:id/events— Events recorded for this webhook.GET /api/v1/webhooks/:id/deliveries— Outbound delivery attempts (status, retry count, response).GET /api/v1/webhooks/events— Recent events across all webhooks in the org (up to 100), joined to webhook name.
Receiving and verification
POST /api/v1/webhooks/receive/:webhookId accepts the third-party payload, verifies the signature using the stored hash, and stores the event. This route does not require an Alumia API key — authentication is signature-based.
POST /api/v1/webhooks/verify lets you check a signed payload independently of the receive endpoint.
POST /api/v1/webhooks/test posts a synthetic event so you can wire end-to-end without involving the upstream provider.
Errors
| Code | When |
|---|---|
UNAUTHORIZED | Missing API key on management routes. |
BAD_REQUEST | Missing/oversized name, non-public url, invalid status. |
NOT_FOUND | Webhook does not belong to the caller's org. |