Console
Webhooks
Signed HTTP callbacks, retried three times and logged. 4 event types are configurable and 1 of them still has an emitter.
/dashboard/webhooks registers endpoints for the runtime selected in the sidebar. Webhooks are per-runtime, not per-organization: two runtimes need two registrations, and up to ten endpoints can be attached to each.
Events
4 event types can be subscribed to. An endpoint receives only the ones on its list, and the column on the right says whether anything still sends it.
| Event | Fires when | data carries | Dispatched |
|---|---|---|---|
message.received | A message reached the runtime through the chat route, which no longer exists. | message, channel, session_id | No |
message.sent | The runtime answered, through that same removed route. | response, channel, session_id, token_usage | No |
agent.status_changed | The status column moves — in practice only when a row left mid-provision is closed out. | previous_status, new_status, and reason on a failure | Yes |
agent.health_check | Nothing dispatches this, and nothing ever did. | — | No |
agent.health_check never had a dispatcher. The two message events fired from the platform chat route; that route went with the agent-VM runtime. agent.status_changed is the one that still fires, and only when /api/agent/status closes out a row left mid-provision by that same removal — so an account created since will not see it either. Subscriptions to the dormant events are still accepted and stored, because an endpoint subscribed to one is not broken, just never called. Watch the request traces on the API monitor instead.Gateway traffic has never produced webhook events, and with the chat route gone nothing else does either. A Gateway integration should watch the request traces.
Payload
Every delivery is a POST with the same four top-level fields. Only data varies by event.
| Header | Value |
|---|---|
Content-Type | application/json |
X-Lobstack-Signature | sha256=<hex HMAC of the raw body> |
X-Lobstack-Event | The event name, so you can route before parsing. |
X-Lobstack-Delivery-Attempt | 1, 2 or 3. |
User-Agent | Lobstack-Webhooks/1.0 |
Signature verification
Signing is implemented. Each endpoint gets a 32-byte signing secret at creation, shown once and not retrievable afterwards, and every delivery carries an HMAC-SHA256 of the exact request body under that secret, hex-encoded, prefixed with sha256=.
Verify against the raw bytes you received, before any JSON parsing or re-serialisation, and compare in constant time.
timestamp field in the payload. The secret is also stored in plain text in our database, because computing an HMAC requires the original value.Retries
A delivery is attempted at most three times: immediately, then after 5 seconds, then after 30. Each attempt has a 10-second timeout.
| Your response | What happens |
|---|---|
| 2xx | Success. No further attempts. |
| 4xx other than 429 | Treated as permanent. No retry — a malformed request will not become valid. |
| 429 | Retried. |
| 5xx | Retried. |
| Timeout or connection failure | Retried. |
After three failed attempts the delivery is abandoned. There is no dead-letter queue and no manual redrive. Deliveries to different endpoints run concurrently, and one endpoint being down does not delay another.
Dispatch is fire-and-forget: it never blocks or fails the operation that triggered it. An event that fires while your endpoint is unreachable is lost after its third attempt.
Delivery history
Every attempt sequence is written to a delivery table with the event type, the full payload, the final status, the response code and the attempt count. The Console does not display it. There is no delivery log, no replay button and no failure alert in the UI today — the rows exist, but reading them means querying the database.
Managing endpoints
The list shows each endpoint's URL and its subscribed events, with a toggle and a delete. The toggle pauses delivery without losing the registration or its secret; a paused endpoint is skipped entirely rather than queued. Delete is immediate and takes the secret with it.
A URL must be http or https. Creating an endpoint with no events selected is rejected; creating one through the API with the field omitted subscribes it to all 4.