Local URL target

View as Markdown

A local URL target is the HTTP-webhook side of Dial’s fan-out. You register a loopback URL with the listen daemon and, for every account event, the daemon POSTs the event JSON to that URL. Long-lived services on the same machine (an agent runtime, a workflow engine, a queue) pick the event up like any other webhook.

When to use it

  • The receiver is a process that’s already running and listens on a loopback port.
  • You want HMAC signing or a bearer token to authenticate Dial’s POSTs.
  • You’re wiring into a product that already understands webhooks — most agent frameworks fall here.

If the receiver is a script you’d normally spawn from a shell, the CLI command target is simpler and avoids running an HTTP server.

Prerequisites

$dial listen install

The listen daemon owns the fan-out queue and is what makes the outgoing POSTs. See Listen service.

Loopback only

The URL must be http:// or https:// and resolve to a local loopback host — 127.0.0.1, 0.0.0.0, localhost, ::1, or [::1]. Public URLs are rejected. This is intentional: Dial events stay on the machine the daemon runs on; cross-network delivery is a job for our forthcoming durable webhooks.

Register

$dial local-target add url http://127.0.0.1:8787/dial-events

For each event, the daemon issues:

POST http://127.0.0.1:8787/dial-events
Content-Type: application/json
<event_json>

See dial local-target add url for the full reference.

Authenticate the receiver

By default the POST has no auth — fine on loopback for casual setups, but most receivers want at least one of:

HMAC signing

$dial local-target add url http://127.0.0.1:8787/dial-events \
> --secret "$(cat ~/.config/my-receiver/dial.secret)" \
> --signature-header "X-My-Receiver-Signature"

The daemon computes HMAC-SHA256(secret, body) per request and puts the hex digest in the header named by --signature-header (defaults to X-Dial-Signature). The receiver recomputes the digest from the raw body and rejects mismatches. Good fit for systems that expect a per-subscription HMAC, like Hermes Agent.

Bearer token

$dial local-target add url http://127.0.0.1:8787/dial-events \
> --bearer "$(cat ~/.config/my-receiver/dial.token)"

The daemon sends Authorization: Bearer <token> on every POST. Good fit for systems that gate the endpoint with a shared static token, like OpenClaw.

You can also combine --bearer with --secret if the receiver wants both.

Delivery semantics

  • 2xx — treated as delivered.
  • Non-2xx, connection error, or timeout — the daemon retries the request once. If the retry also fails, the event is logged and dropped; nothing is queued for later.
  • Timeout--timeout <seconds> per attempt, defaulting to 5.
  • Concurrency — requests to the same target run independently; the daemon doesn’t serialize them, so make your handler safe to run twice in close succession (the once-retry can produce that).
  • The event stream the daemon consumes is presence-based (not at-least-once), so an event the daemon never received cannot be recovered from the server side. For guaranteed delivery, register an at-least-once webhook.

Verify, list, remove

$dial local-target list
$# url http://127.0.0.1:8787/dial-events
$# cmd /usr/local/bin/handle-dial-event
$
$dial local-target remove http://127.0.0.1:8787/dial-events

No daemon restart is required for any of these — the fan-out registry updates on the fly.

See also