Webhooks
Configure inbound HTTP webhooks that create inbox items or trigger workspace runs when an external event fires.
Webhooks give your workspace an inbound HTTP endpoint so external systems — price alerts, news feeds, portfolio risk monitors — can drop items into your inbox or kick off an agent run the moment something worth acting on happens.
How webhooks work
Each workspace can expose one or more named webhook endpoints through the qoc daemon. Incoming POST requests are authenticated with an HMAC-SHA256 signing secret and then dispatched to a handler you define in desk.toml.
A handler maps an incoming payload to one of two actions: `inbox` (write a formatted inbox item to inbox/) or `run` (queue an agent run for a named issue or task). Both actions are non-blocking from the caller's perspective — Qoc acknowledges the webhook with HTTP 202 and processes the action asynchronously.
Configuring a webhook in desk.toml
[[webhook]]
name = "price-alert"
secret = "env:WEBHOOK_SECRET_PRICE_ALERT" # reads from environment variable
action = "inbox" # write to inbox/
[[webhook]]
name = "risk-breach"
secret = "env:WEBHOOK_SECRET_RISK"
action = "run"
task = "risk-review" # triggers issues/risk-review.mdEndpoint URL
Once configured, each webhook endpoint is available at:
http://localhost:PORT/webhook/<workspace-name>/<webhook-name>
Replace PORT with the port your qoc daemon is listening on (default 7430) and <workspace-name> with the name field from your desk.toml header. The <webhook-name> matches the name field in the [[webhook]] block.
If you expose the daemon behind a reverse proxy or tunnel for external access, the same path applies on your public host.
Example webhook payload
{
"event": "price_alert",
"symbol": "MSFT",
"trigger_price": 420.00,
"current_price": 421.35,
"direction": "above",
"alert_name": "MSFT 420 break",
"timestamp": "2026-07-05T13:45:00Z"
}Signing requests
# The signature is sent in the X-Qoc-Signature header.
# Format: sha256=<hex-digest>
# Body is the raw request body bytes.
BODY='{"event":"price_alert","symbol":"MSFT",...}'
SECRET="your-signing-secret"
SIGNATURE=$(echo -n "$BODY" | openssl dgst -sha256 -hmac "$SECRET" | awk '{print $2}')
curl -X POST "http://localhost:7430/webhook/equity-desk/price-alert" -H "Content-Type: application/json" -H "X-Qoc-Signature: sha256=$SIGNATURE" -d "$BODY"Handler action reference
| action value | Effect | Required extra fields |
|---|---|---|
inbox | Writes a formatted inbox item to inbox/TIMESTAMP-WEBHOOK-NAME.md | None |
run | Queues an agent run for the named task | task — name of the issue or task to run |
Always use a signing secret
Never expose a webhook endpoint without setting a signing secret. Qoc rejects any request whose X-Qoc-Signature header does not match the expected HMAC. Store the secret value in an environment variable and reference it with the env:VAR_NAME syntax in desk.toml — never hard-code it in the file.
Webhook-triggered runs are subject to the same limits
A webhook that triggers a run action follows the same context injection, scoped command surface, and human-approval flow as a scheduled or manual run. Draft orders still require your approval before execution.