Public reference
Webhooks
Every endpoint in this group. Open one for its parameters and a worked example.
Webhooks
9GET /api/v1/admin/webhooks/deliveries Read the delivery log
One page of delivery attempts, newest first, without the payload bodies. This is where you diagnose an integration that is not receiving events.
- Authentication
- Staff token or session
- Requires permission
-
prm_notifications_manageManage notification channels & templates
failed and dead are different. failed means it will be retried, and next_attempt_at says when; dead means the attempt budget is spent and nothing further will happen without a replay. An integration that went quiet has rows in dead, not failed.
Parameters
| Parameter | Description |
|---|---|
filter[endpoint_id]
query · integer
|
Narrow to one endpoint. Also accepted as a bare endpoint_id parameter. |
filter[state]
query · enum
|
queued, sending, sent, failed or dead. An unknown value is a 400. |
sort
query · string
|
queued_at, state, attempts or id. Defaults to queued_at descending. |
{
"data": [
{
"id": 77120,
"endpoint_id": 4,
"event_type": "user.created",
"state": "failed",
"attempts": 3,
"max_attempts": 6,
"response_code": 502,
"response_ms": 1204,
"last_error": "upstream returned 502",
"url": "https://hooks.acme.example/xradius",
"queued_at": "2026-09-20 09:00:00",
"sent_at": "2026-09-20 09:04:11",
"next_attempt_at": "2026-09-20 09:20:00"
}
],
"meta": { "page": 1, "page_size": 50, "total": 4102, "has_next": true }
}
POST /api/v1/admin/webhooks/deliveries/{id}/replay Replay a delivery
Re-queues a past delivery, which is how a dead one is recovered after the receiving side is fixed.
- Authentication
- Staff token or session
- Requires permission
-
prm_notifications_manageManage notification channels & templates - Rate limit
t_egress
Your receiver will see the same event twice if the original eventually landed. Webhook receivers have to be idempotent on the event id; this endpoint is one of the reasons why.
Parameters
| Parameter | Description |
|---|---|
idrequired
path · integer
|
Delivery id. |
GET /api/v1/admin/webhooks/endpoints List webhook endpoints
Every configured endpoint for the tenant, with its subscription set. Un-paginated: the whole set is page 1 and has_next is always false.
- Authentication
- Staff token or session
- Requires permission
-
prm_notifications_manageManage notification channels & templates
{
"data": [
{
"id": 4,
"name": "billing-sync",
"url": "https://hooks.acme.example/xradius",
"events": ["user.created", "user.disconnected"],
"all_events": false,
"enabled": true,
"created_at": "2026-06-11 14:20:00",
"updated_at": "2026-09-02 08:31:12"
}
],
"meta": { "page": 1, "page_size": 1, "total": 1, "has_next": false }
}
POST /api/v1/admin/webhooks/endpoints Create a webhook endpoint
Registers a URL and the events it should receive. Set all_events to subscribe to everything, present and future, instead of naming keys.
- Authentication
- Staff token or session
- Requires permission
-
prm_notifications_manageManage notification channels & templates - Rate limit
t_mutate
Answers 200, not 201, despite creating a record. Do not gate your client on the status code here.
Parameters
| Parameter | Description |
|---|---|
namerequired
body · string
|
A label for the endpoint. |
urlrequired
body · string
|
Where deliveries are POSTed. Validated on save. |
events
body · array
|
Event keys from the catalogue. Ignored when all_events is true. |
all_events
body · boolean
|
Subscribe to every event, including ones added in later releases. |
enabled
body · boolean
|
Defaults to true on create. |
POST /api/v1/admin/webhooks/endpoints/bulk-delete Manage notification channels & templates
- Authentication
- Staff token or session
- Requires permission
-
prm_notifications_manageManage notification channels & templates - Rate limit
t_mutate
Read straight from the router that serves this instance. A hand-written description of this endpoint has not been added yet.
DELETE /api/v1/admin/webhooks/endpoints/{id} Delete a webhook endpoint
Removes the endpoint. Queued deliveries for it stop.
- Authentication
- Staff token or session
- Requires permission
-
prm_notifications_manageManage notification channels & templates - Rate limit
t_mutate
Parameters
| Parameter | Description |
|---|---|
idrequired
path · integer
|
Endpoint id. |
PATCH /api/v1/admin/webhooks/endpoints/{id} Update a webhook endpoint
Replaces name, url, events and all_events outright, and patches enabled only when it is present. Send the full object, because a missing events array clears the subscription rather than leaving it alone.
- Authentication
- Staff token or session
- Requires permission
-
prm_notifications_manageManage notification channels & templates - Rate limit
t_mutate
This is a PATCH that behaves as a replace for four of its five fields. An update that sends only url wipes the events list.
Parameters
| Parameter | Description |
|---|---|
idrequired
path · integer
|
Endpoint id. |
POST /api/v1/admin/webhooks/endpoints/{id}/test Send a test delivery
Queues one synthetic delivery to the endpoint and returns its id so you can follow it in the log.
- Authentication
- Staff token or session
- Requires permission
-
prm_notifications_manageManage notification channels & templates - Rate limit
t_egress
The delivery is QUEUED, not sent. A 200 here says the job was created, not that your endpoint answered. Poll the delivery log for the outcome. It is also on the per-tenant egress budget, which is 5 a minute on a standard licence.
Parameters
| Parameter | Description |
|---|---|
idrequired
path · integer
|
Endpoint id. |
{
"data": { "delivery_id": 77120 }
}
GET /api/v1/admin/webhooks/event-catalog List subscribable event keys
Every event an endpoint may subscribe to, with its category. The create and update endpoints validate the events array against exactly this set, so read it before writing one. Static for the life of the release, so fetch it once and cache it.
- Authentication
- Staff token or session
- Requires permission
-
prm_notifications_manageManage notification channels & templates
{
"data": [
{ "key": "user.created", "category": "lifecycle" },
{ "key": "user.disconnected", "category": "lifecycle" },
{ "key": "usage.threshold", "category": "usage" }
],
"meta": { "page": 1, "page_size": 3, "total": 3, "has_next": false }
}
No endpoint matches that search.
Written to be read by machines too
The reference is public and needs no account, so a tool that has never seen X-Radius can reach a correct first call on its own.
- /llms.txt
- An index of every page, with one-line summaries.
- /llms-full.txt
- The whole reference as one Markdown file, with no navigation to crawl.
- /openapi.json
- OpenAPI 3.1, generated from the router that serves this instance.
- /skill.md
- A ready-made skill file for an assistant: authentication, the response envelope and the error codes in one page.
<page-url>.md- Append .md to any reference URL for the same page as Markdown.
Accept: text/markdown- Send this header on the ordinary URL and the answer comes back as Markdown instead.
Read https://x-radius.com/llms.txt, then fetch the endpoint you need as Markdown by appending .md to its URL.