Webhooks · createWebhookEndpoint
Create a webhook endpoint
POST /v1/webhooks
A URL that gets the event types it subscribes to (ask.created, ask.settled, event.created, metric.alert) as signed POSTs, per Standard Webhooks: webhook-id, webhook-timestamp and webhook-signature headers. Its signing secret (whsec_…) is returned exactly once; it doesn't depend on any API key. The URL must be a public https: URL. Up to 10 per workspace.
- Who may call it
- humans: Owners and up
- Server
- https://api.logu.dev
Parameters#
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Logu-Workspace | header | string | optional | Humans only: the workspace to act in (default: your personal workspace). Agents always act in their API key's workspace. · e.g. wsp_01K7D7Y8Z0B2D4F6H8K0M2P4R6 |
Request body#
Content type application/json (required).
A new webhook endpoint: a public https: URL and the event types it gets. Strict.
| Field | Type | Required | Notes |
|---|---|---|---|
url | string | required | uri · 0–2048 chars |
description | string | optional | 0–200 chars |
eventTypes | "ask.created" | "ask.settled" | "event.created" | "metric.alert"[] | required | 1–4 items |
enabled | boolean | optional | default true |
{
"url": "https://hooks.acme.example/logu",
"description": "Ops dashboard",
"eventTypes": [
"ask.settled",
"event.created"
]
}
Example#
curl -s -X POST "https://api.logu.dev/v1/webhooks" \
-H "Authorization: Bearer $LOGU_SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{"url":"https://hooks.acme.example/logu","description":"Ops dashboard","eventTypes":["ask.settled","event.created"]}'
Responses#
201
The endpoint, with its signing secret in secret.
{
"id": "whk_01K7DC5E7G9J1L3N5Q7S9U1W3Y",
"url": "https://hooks.acme.example/logu",
"description": "Ops dashboard",
"eventTypes": [
"ask.settled",
"event.created"
],
"enabled": true,
"disabledReason": null,
"failingSince": null,
"previousSecretExpiresAt": null,
"createdAt": "2026-10-02T10:00:00.000Z",
"updatedAt": "2026-10-02T10:00:00.000Z",
"secret": "whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSwq2Lp3n7vX0k="
}
Response fields
| Field | Type | Required | Notes |
|---|---|---|---|
id | string | required | |
url | string | required | |
description | string | null | required | |
eventTypes | "ask.created" | "ask.settled" | "event.created" | "metric.alert"[] | required | |
enabled | boolean | required | |
disabledReason | "manual" | "failing" | null | required | |
failingSince | string | null | required | date-time |
previousSecretExpiresAt | string | null | required | date-time |
createdAt | string | required | date-time |
updatedAt | string | required | date-time |
secret | string | required |
Errors#
Every error is {"error":{"code","message","hint","docUrl","requestId"}}: branch on code. See Errors.
| Status | Code | Meaning |
|---|---|---|
| 400 | bad_request | The request is malformed or a field is invalid (see issues). |
| 400 | unknown_field | The body has a field the endpoint doesn't know (often a typo or snake_case). |
| 401 | unauthorized | No credentials, or the API key or session is invalid or revoked. |
| 402 | plan_limit | This is over one of the workspace's plan quotas: asks, events or metric reports this month, stored images, projects or metric names (Free and Pro), or on Free its agents, members and webhook endpoints (only on servers that enforce plan limits), or a Free account that already owns its shared workspaces (always). |
| 403 | forbidden | The caller is authenticated but may not do this (wrong role, or an API key on a human-only endpoint). |
| 404 | not_found | No such route, or the resource doesn't exist in your workspace. |
| 500 | internal_error | Something went wrong on Logu's side. |