QuickDesk endpoints live on the unified webhook plane. The console screen creates them with vertical: 'quickdesk', so they receive the QuickDesk event catalogue: signed POSTs when remote-desktop peers come online or go offline, and when remote-control sessions connect or get denied. Signing, retry behaviour and the delivery log are shared across every ClutchCall vertical — see Webhooks. This page covers what is specific to QuickDesk: which event tokens exist, how the group picker maps onto them, and what a handler sees.

Event groups and types

The Event groups checklist on the webhooks screen is rendered from webhooks.catalog, the control-plane registry, not from a hardcoded list in the console. That is deliberate: the picker can never offer a token that no producer emits, and webhooks.create / webhooks.update reject unknown tokens outright (assertKnownEventTypes). The registry is therefore the authoritative list; the table below is the QuickDesk slice of it. Each group in the picker carries its own label and description straight from the registry, plus the list of types it expands to. Ticking a group subscribes the endpoint to every type in that group. test.ping is not part of any group. The Test button on each endpoint row calls webhooks.sendTest, which delivers a signed test.ping to that endpoint immediately and reports the HTTP status it got back. Use it to prove your signature check works before real traffic arrives.

How event types are matched

An endpoint stores an array of patterns in event_types. The dispatcher matches a fired event against those patterns three ways, and the console applies the identical contract when it decides which group badges to show on a row:
  • exact match — session.denied matches only session.denied
  • * — matches every event type
  • prefix glob x.* — peer.* matches peer.online and peer.offline
Two consequences worth knowing before you save an endpoint:
  • Selecting every group collapses to *. The screen sends eventTypes: ['*'] when all groups are ticked, which means the endpoint also receives event types added to the registry later. If you want a frozen contract, tick only the groups you handle.
  • Selecting nothing also stores *. The screen falls back to ['*'] rather than creating an endpoint that can never fire.
To narrow or widen an existing endpoint, call webhooks.update with a new eventTypes array; it is validated against the registry the same way as on create.

Wiring a handler for peer presence

Subscribe to the peer presence group only, and your endpoint sees peer.online and peer.offline and nothing else — no session traffic, and no future tokens from other groups. Every delivery is a POST with a JSON body and a signature header. Verify it over the raw request body, before parsing:
The signed value is t and the raw body joined with a ., HMAC-SHA256 with the endpoint’s signing secret, hex encoded. The secret is returned once — by webhooks.create at creation, and by webhooks.rotateSecret on rotation. After that the console only shows signing_secret_preview. Rotation takes effect immediately: the previous secret stops verifying as soon as webhooks.rotateSecret returns, so deploy the new secret on your side first, or pause the endpoint while you swap it.

Session connected and denied

session.connected and session.denied are the two terminal outcomes of a remote-control session request against a peer. Treat them as a pair:
  • session.connected — the session was established. This is the token to drive “session in progress” state, audit records, or an operator notification.
  • session.denied — the request was refused instead of connecting. Nothing was established, so do not expect a later session.connected for the same request.
If you subscribe to the session group but not peer presence, your handler sees session outcomes without presence churn — useful when a middleware service only needs to record who connected to what.

Reading the exact payload of an event

This page names the event tokens; the field set inside each payload comes from the producer and is recorded verbatim on the delivery. Rather than coding against a guess, read a real one:
  1. Create the endpoint with the groups you care about.
  2. Press Test on the endpoint row to confirm signature verification works end to end (webhooks.sendTest reports the HTTP status your server returned).
  3. Trigger the real event, then open Recent deliveries and click into the row. The delivery detail carries the full stored payload; the list view carries only the metadata (event_type, created_at, status, attempts, last_status_code, last_error).
Clicking an endpoint row filters the delivery log to that endpoint; otherwise the log shows deliveries for this vertical’s endpoints. Rows in delivered or dead state can be replayed with Redeliver, which queues the same payload again — a convenient way to re-run a handler you have just fixed.

Endpoint state you will see on the screen

Pressing Resume sets status: 'active' through webhooks.update, which also clears the consecutive-failure counter and the failing auto-pause. Delivery rows themselves move through pending, delivering, delivered and dead.

On-prem and private-network endpoints

By default an endpoint URL must be https:// and must resolve to a publicly deliverable address — webhooks.create runs a deliverability check and rejects anything else with BAD_REQUEST. Tick On-prem / private-network endpoint to set allowPrivateEgress, which permits RFC1918 targets and http:// URLs. A plain http:// URL without that flag is rejected on both create and update, and the flag stored on the row — not the flag in the form — decides what a later URL change may point at.
  • Webhooks — signing, retries, and the delivery log shared by all verticals
  • Authentication — API keys for the control-plane procedures behind this screen
  • Telemetry — metrics and traces for the same events