# ADR-0014: No webhooks on synchronous /api/chat **Status:** Accepted -- 2026-05-23 ## Context The `state_webhook_url` field exists on the async `POST /jobs` surface to notify callers of state transitions. When Phase 3 promoted `/api/chat` to route through the internal job queue, the question arose: should webhook events also fire for synchronous chat requests? ## Decision **`state_webhook_url` is only honored on `POST /jobs`.** Synchronous `/api/chat` requests do not fire webhooks, even though they internally create job rows. ### Rationale - The `/api/chat` caller holds an open HTTP connection and blocks until the response is ready. Webhooks would be redundant: the caller already gets the result directly. - Adding webhook delivery on the sync path would double the webhook volume with no consumer benefit. - The sync path is the go-llm target; webhook handling would add latency and complexity to the critical hot path. - Callers who want webhooks should use `POST /jobs` explicitly. ## Consequences - `POST /jobs` is the only entry point that supports `state_webhook_url`. - `/api/chat` job rows are created without a webhook URL and produce no webhook traffic. - This keeps the webhook dispatcher's load proportional to async job volume only. ## Alternatives considered - **Fire webhooks on both paths.** Adds webhook traffic for every go-llm request with no consumer; rejected. - **Optional opt-in header on /api/chat.** Over-engineered for a passthrough endpoint; rejected.