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.
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. |
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.
curl -X POST https://alumia.com/api/v1/webhooks \
-H "Authorization: Bearer alm_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{ "name": "Stripe events", "events": ["payment_intent.succeeded"] }'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. |