HTTP API and WebSocket

The Domscribe relay server exposes a REST API for annotation management and manifest queries, plus a WebSocket server for real-time events. The relay runs on localhost and is accessed by both the browser overlay and coding agents.

The default base URL is http://127.0.0.1:<port>/api where the port is dynamically assigned (or configured via the relay.port option).


HTTP API Routes

Health and Status

GET /api/health

Health check endpoint. Returns 200 if the relay is running.

GET /api/status

Returns relay status including manifest statistics and annotation queue counts.

Response:

{
  "status": "ok",
  "uptime": 3600,
  "manifest": {
    "entryCount": 142,
    "fileCount": 28,
    "componentCount": 35
  },
  "annotations": {
    "queued": 2,
    "processing": 1,
    "processed": 5,
    "failed": 0,
    "archived": 3
  },
  "browserConnected": true
}

Annotations

POST /api/annotations

Create a new annotation. Typically called by the browser overlay when a user clicks an element and submits a description.

Request body:

{
  "interaction": {
    "mode": "ELEMENT_CLICK",
    "elementId": "A1B2C3D4",
    "selector": "main > div > button",
    "boundingRect": { "x": 100, "y": 200, "width": 80, "height": 32 }
  },
  "context": {
    "url": "http://localhost:3000/dashboard",
    "viewport": { "width": 1920, "height": 1080 },
    "userAgent": "Mozilla/5.0 ...",
    "manifestSnapshot": { "..." },
    "runtimeContext": { "..." }
  },
  "message": "Make this button use the primary color"
}

Response: The created annotation object with status QUEUED.

GET /api/annotations/:id

Get a single annotation by ID.

Parameters:

ParameterTypeDescription
idstringAnnotation ID (ann_* format)

PATCH /api/annotations/:id

Update an annotation. Used by agents to claim (atomically transition from QUEUED to PROCESSING).

Request body:

{
  "status": "PROCESSING"
}

GET /api/annotations

List annotations with optional filters.

Query parameters:

ParameterTypeDescription
statusstringFilter by status: QUEUED, PROCESSING, PROCESSED, FAILED, ARCHIVED

DELETE /api/annotations/:id

Delete an annotation by ID.

PATCH /api/annotations/:id/respond

Attach the agent's response to an annotation and transition it to PROCESSED.

Request body:

{
  "response": "Updated the button to use the primary color from the design system tokens."
}

PATCH /api/annotations/:id/status

Manually update an annotation's status.

Request body:

{
  "status": "ARCHIVED"
}

POST /api/annotations/search

Full-text search across annotation content.

Request body:

{
  "query": "button color"
}

Manifest

GET /api/manifest

Query manifest entries by file path, component name, or element ID.

Query parameters:

ParameterTypeDescription
filestringFilter by file path
componentNamestringFilter by component name
idstringLook up a specific entry ID

GET /api/manifest/:id

Resolve a single manifest entry by its data-ds ID.

POST /api/v1/manifest/resolve-by-source

Query the manifest by source file and line number, optionally including live runtime context from the browser.

Request body:

{
  "file": "src/components/Button.tsx",
  "line": 12,
  "column": 4,
  "tolerance": 0,
  "includeRuntime": true
}
FieldTypeRequiredDefaultDescription
filestringYes--Absolute file path as stored in the manifest
linenumberYes--Line number (1-indexed)
columnnumberNo--Column number (0-indexed)
tolerancenumberNo0Max line distance to consider a match
includeRuntimebooleanNotrueQuery live runtime context via WebSocket

Response:

{
  "found": true,
  "entryId": "A1B2C3D4",
  "sourceLocation": {
    "file": "src/components/Button.tsx",
    "start": { "line": 12, "column": 4 },
    "end": { "line": 12, "column": 42 },
    "tagName": "button",
    "componentName": "Button"
  },
  "runtime": {
    "rendered": true,
    "componentProps": { "variant": "secondary", "onClick": "[Function]" },
    "componentState": { "hook_0": false, "hook_1": "idle" },
    "domSnapshot": {
      "tagName": "button",
      "attributes": { "class": "btn-secondary", "type": "submit" },
      "innerText": "Save changes"
    }
  },
  "browserConnected": true
}

When includeRuntime is true and a browser is connected via WebSocket, the relay sends a CONTEXT_REQUEST to the overlay client and includes the live runtime context in the response.


WebSocket Events

Connect to the WebSocket at /api/ws for real-time event streaming.

Connection Lifecycle

EventDirectionDescription
CONNECTClient to ServerInitial connection request
CONNECTEDServer to ClientConnection established
DISCONNECTEDServer to ClientConnection closed
ERRORServer to ClientConnection error

Annotation Events

EventDirectionPayloadDescription
ANNOTATION_CREATEDServer to ClientAnnotationA new annotation was created
ANNOTATION_UPDATEDServer to ClientAnnotationAn annotation's status or response changed

These events are broadcast to all connected clients. The overlay uses them to update annotation status in real time -- for example, showing the agent's response as soon as it is submitted.

Manifest Events

EventDirectionPayloadDescription
MANIFEST_UPDATEDServer to Client{ entryCount }The manifest file changed on disk

Context Query Events

EventDirectionDescription
CONTEXT_REQUESTServer to ClientRelay asks the browser for live runtime context
CONTEXT_RESPONSEClient to ServerBrowser responds with captured props, state, and DOM

These events power the domscribe.query.bySource MCP tool. When an agent queries a source location, the relay forwards a CONTEXT_REQUEST to the connected browser overlay. The overlay queries the runtime adapter (React fiber or Vue VNode) and sends the captured context back as a CONTEXT_RESPONSE.

WebSocket Message Format

{
  "type": "ANNOTATION_CREATED",
  "payload": { "..." },
  "timestamp": "2026-03-15T10:30:00.000Z"
}

Clients can subscribe to specific events:

{
  "type": "subscribe",
  "events": ["ANNOTATION_CREATED", "ANNOTATION_UPDATED", "MANIFEST_UPDATED"]
}