Skip to content

WebSocket API

The WebSocket API gives you a persistent connection to the Prefactor platform API. The same operations as the HTTP API are available over the socket, and the socket can also receive server-pushed notifications when agent instances change. This page lists the connection details, message format, methods, and error and close codes; Stream agent instance updates walks through a working subscription.

The TypeScript and Python SDKs speak HTTP, not WebSocket — this API is for when you’re writing your own client.

The endpoint is wss://app.prefactorai.com/api/v1/ws. Authenticate by sending an Authorization: Bearer <token> header on the upgrade request, using an API token — create one from the Account › API tokens tab. Both account tokens and deployment tokens work; the token’s scope decides what you can call and subscribe to.

The browser WebSocket API cannot set request headers, so browser code cannot authenticate directly. Use a client that can, such as the ws package in Node.js, or put a proxy in front that adds the header.

A failed upgrade returns a plain HTTP response instead of opening the socket:

StatusCause
400Not a WebSocket upgrade request, or a malformed Authorization header.
401Missing, invalid, or expired token.

The socket speaks JSON-RPC 2.0 over text frames. Each request carries an id, which the response echoes back:

{"jsonrpc": "2.0", "id": 1, "method": "agents/list", "params": {}}
{"jsonrpc": "2.0", "id": 1, "result": {"status": "success", "summaries": []}}

Prefactor also sends notifications, which have no id — see Notifications:

{"jsonrpc": "2.0", "method": "agent_instances/updated", "params": {"status": "success", "details": {"id": "01J..."}}}

Three rules to know:

  • Send text frames only. Binary frames are rejected with an invalid_request error.
  • JSON-RPC batch requests are not supported.
  • A message without an id is treated as a notification and ignored — no response, no effect.

Method names follow the resources: agents/list, agent_instances/register, risk_profiles/show, and so on. Params and results match the corresponding HTTP operations in the OpenAPI spec; the OpenRPC spec lists every method name with its schema. Two methods are worth knowing on their own:

MethodDescription
bulk/executeRuns several operations in one request. Params and result match POST /bulk.
pingReturns details of the token you’re authenticated with. Also useful as a keepalive — see Connection lifecycle.

One method is only available over WebSocket:

MethodParamsResult
agent_instances/subscribeagent_instance_id (required), idempotency_key (optional)refs — the records the connection is now subscribed to.

After a successful agent_instances/subscribe, Prefactor pushes a notification each time the instance changes. Notifications are JSON-RPC messages with no id:

MethodSent whenParams
agent_instances/insertedThe instance is created.details — the full instance, in the same shape as GET /agent_instance/{agent_instance_id}.
agent_instances/updatedThe instance changes — status, span counts, and so on.details, as above.
agent_instances/deletedThe instance is deleted.id of the deleted instance; the record itself no longer exists.
errorYour token stops being valid.code and message describing the failure. Prefactor closes the connection right after sending this — see Connection lifecycle.

Notifications are filtered by the token’s permissions: if the token cannot see the instance, the notification is dropped rather than sent. Pushed notifications are not rate limited.

Errors come back as JSON-RPC error objects. The top-level code is a JSON-RPC code; data carries the Prefactor error, in the same shape as an HTTP error response:

{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32602,
"message": "Agent instance not found",
"data": {"status": "error", "code": "not_found", "message": "Agent instance not found"}
}
}
CodeMeaning
-32700Parse error — the frame was not valid JSON. The connection is then closed with code 1007.
-32600Invalid request — malformed JSON-RPC, a binary frame, or a batch request.
-32601The operation is not implemented.
-32602Invalid params, an unknown method name, or an application error such as not_found. data.code names the specific error.
-32603Internal server error.
-32000Rate limited. data.retry_after_ms says how long to wait before retrying — see Rate limits.
-32001Temporarily unavailable.

Prefactor does not send heartbeats. If you need to detect a dead connection, call ping on your own schedule.

Close codeMeaningWhat to do
1000Normal close.Reconnect if you still need the stream.
1007A frame contained malformed JSON.Fix the payload, then reconnect.
1008Authentication is no longer valid — the token was revoked, suspended, or expired, or the account, environment, or deployment it belongs to was deleted. Prefactor sends an error notification before closing.Re-authenticate with a valid token before reconnecting.

Nothing persists across connections. To resume after a reconnect, open a new socket and send agent_instances/subscribe again.

Calls over the socket count against the same rate limits as HTTP requests — Rate limits covers how they are applied.

The machine-readable spec for the WebSocket API is at https://app.prefactorai.com/api/v1/openrpc. It lists every JSON-RPC method with its params and result schemas, including the WebSocket-only subscription and the server-pushed notifications.

  • API Reference — the section overview: transports, rate limits, and the operation reference.
  • HTTP API — base URL, authentication, and error shapes for plain HTTPS calls.
  • Rate limits — how limits are applied, and the shape of a limited response.
  • API token — account tokens and deployment tokens, and where to manage them.
  • Instance — what an agent instance is.
  • Stream agent instance updates — subscribe to an instance and handle the notifications.