Skip to main content

Application WebSocket API

Current routes, authentication boundary, message envelope, and recovery behavior for CodeGraph application WebSockets.

API Reference

This reference covers the three application WebSockets used for chat, job status, and notifications. Dashboard refresh events use a distinct authentication and message contract described in Dashboard WebSocket API.

Authentication boundary

Production clients must send an HTTP handshake header:

Authorization: Bearer <access-token>

A token in the URL is rejected. The server closes a connection containing a token query parameter with code 1008 and reason “Query token transport is not allowed”.

For project-bound access, also send the durable project identifier in the handshake:

X-Project-Id: <project-uuid>

The server verifies the current user state, token revocation, project access, job ownership where applicable, and connection/message quotas. A loopback client may omit credentials only when the explicit local-development unauthenticated-surface setting is enabled and both client and requested host are local.

The browser-native WebSocket constructor cannot set an Authorization header. For a browser application, use an authenticated same-origin gateway or the separate dashboard WebSocket contract. Do not move bearer credentials into a query string.

Routes

Routes
Route Client messages Server purpose
/api/v1/ws/chat chat.query, ping Stream chat scenario selection, chunks, final response, completion, and errors
/api/v1/ws/jobs/{job_id} ping Send current and subsequent status for an owned background job
/api/v1/ws/notifications ping Push notifications for the authenticated user

The job route sends code 4004 if the job does not exist. A job that exists but is outside the caller’s scope is denied with policy code 1008.

Message envelope

Every application message is JSON with this shape:

{
  "type": "chat.query",
  "payload": {},
  "timestamp": "2026-08-24T00:00:00Z",
  "request_id": "optional-correlation-id"
}

type and payload are required by the model. timestamp is generated by the server when omitted. request_id is optional and should be preserved when correlating streamed chat messages.

Current message types

Current message types
Type Typical direction Meaning
chat.query client → server Start a chat request
chat.scenario server → client Report selected scenario
chat.chunk server → client Stream a partial answer
chat.response server → client Return the assembled answer
chat.done server → client Finish the request
chat.error server → client Report a chat-specific failure
job.started server → client Return initial or started job state
job.progress server → client Report job progress
job.completed server → client Report successful completion
job.failed server → client Report failed or cancelled completion
notification server → client Push a user notification
error server → client Report an envelope, policy, or processing error
ping client → server Ask for an application-level keep-alive response
pong server → client Respond to ping
cpg.update.complete server → client Report completed CPG update
connected server → client Confirm connection and return its identifiers
disconnected server → client Indicate a managed disconnect
authenticated server → client Confirm a supported authentication transition
auth_required server → client Request a supported authentication transition

Not every message type is produced by every route. Consumers must ignore recognized messages that are irrelevant to their current workflow and must not treat an unknown message as success.

Chat request

Send chat.query only to the chat route:

{
  "type": "chat.query",
  "payload": {
    "query": "Show callers of the selected symbol",
    "session_id": "optional-session",
    "scenario_id": "optional-scenario",
    "language": "en"
  },
  "request_id": "req-123"
}

A normal stream may contain chat.scenario, one or more chat.chunk messages, chat.response, and chat.done. An error message terminates the successful interpretation of that request even if the socket remains open.

Job status

Connect to the exact job route with a job identifier owned by the authenticated user. The server sends job.started with the current status. For terminal states it follows with job.completed or job.failed. Keep the HTTP/REST job response as the durable source; WebSocket delivery is a notification channel and can be interrupted.

Notifications

The notifications route is receive-oriented. Send only ping messages. Notification payloads may contain title, message, level, and action_url. Validate an action URL against the application’s navigation policy before opening it.

Client handshake example

A service client must support custom handshake headers. The following Node.js example uses the ws package:

import WebSocket from "ws";

const socket = new WebSocket(
  "wss://codegraph.example/api/v1/ws/notifications",
  {
    headers: {
      Authorization: "Bearer " + process.env.CODEGRAPH_ACCESS_TOKEN,
      "X-Project-Id": process.env.CODEGRAPH_PROJECT_ID
    }
  }
);

socket.on("message", (raw) => {
  const message = JSON.parse(raw.toString());
  if (message.type === "notification") {
    console.log(message.payload);
  }
});

socket.on("open", () => {
  socket.send(JSON.stringify({ type: "ping", payload: {} }));
});

Never log the token or full Authorization header.

Close codes and recovery

Close codes and recovery
Code Meaning Recovery
1008 Query-token, authorization, ownership, project-scope, or rate-limit policy failure Correct policy/input; do not retry in a tight loop
4001 Missing, invalid, expired, or revoked access token Obtain a new access token and reconnect
4004 Job not found Verify the job identifier through the REST API before reconnecting

Use bounded exponential backoff with jitter for transient disconnects. Refresh credentials before reconnecting after 4001. Do not automatically retry 1008 until the rejected condition has changed.

Source contracts

  • src/api/websocket/routes.py — routes, bearer-header authentication, scope checks, and close behavior
  • src/api/websocket/models.py — envelope, payload models, and message enum
  • src/api/websocket/authorization.py — user, project, token, and job decisions
  • src/api/websocket/rate_limiter.py — connection and message quotas

WebSocket routes are not part of the REST OpenAPI operation set.