Skip to content

API Endpoints ​

All HTTP endpoints exposed by the protoPen server (default port 7870, mapped to 7872 in standard Docker Compose, 7870 in lab profile).

The REST surface below is generated from the OpenAPI spec at openapi.json by scripts/gen_api_docs.py. Regenerate the spec from the live app with python -m server --dump-openapi docs/public/openapi.json after changing a route; CI fails if this page drifts from the spec. The Agent-to-Agent (A2A) JSON-RPC surface is mounted separately and is not part of the OpenAPI schema, so it is documented by hand below — see the A2A Integration guide for worked examples.

Authentication: when PROTOPEN_API_KEY (or RESEARCHER_API_KEY) is set, every /api/* route requires a matching x-api-key header — a 401 drives the operator console's login gate. When unset (local dev) the routes are open. The universal x-api-key header is omitted from the per-endpoint parameter tables below.

Chat UI ​

GET / ​

Serves the Gradio chat UI (PWA-enabled). This is the primary user interface.


REST API ​

64 endpoints, generated from openapi.json (spec 3.1.0, protoPen — protoLabs 0.1.0) — do not edit by hand.

Chat ​

POST /api/chat ​

Chat (programmatic)

Request body (ChatRequest)

FieldTypeRequired
messagestringyes
session_idstringno

Responses: 200 Successful Response, 422 Validation Error

GET /api/chat/commands ​

List chat slash-commands

Responses: 200 Successful Response

POST /api/chat/sessions/{session_id}/steer ​

Queue a mid-turn steer message

Parameters

NameInRequiredTypeDefault
session_idpathyesstring

Request body

Responses: 200 Successful Response, 422 Validation Error

DELETE /api/chat/sessions/{session_id}/steer/{msg_id} ​

Cancel a pending steer

Parameters

NameInRequiredTypeDefault
session_idpathyesstring
msg_idpathyesstring

Responses: 200 Successful Response, 422 Validation Error

GET /api/chat/{session_id}/history ​

Chat session transcript

Parameters

NameInRequiredTypeDefault
session_idpathyesstring

Responses: 200 Successful Response, 422 Validation Error

OpenAI-Compatible API ​

POST /v1/chat/completions ​

OpenAI-compatible chat completions

Request body

Responses: 200 Successful Response, 422 Validation Error

GET /v1/models ​

List models (OpenAI-compatible)

Responses: 200 Successful Response

Runtime ​

GET /api/runtime/status ​

Runtime status

Responses: 200 Successful Response

Subagents ​

GET /api/subagents ​

List subagents

Responses: 200 Successful Response

POST /api/subagents/batch ​

Run subagents concurrently

Request body (SubagentBatchRequest)

FieldTypeRequired
session_idstringno
tasksobject[]yes

Responses: 200 Successful Response, 422 Validation Error

POST /api/subagents/run ​

Run a subagent

Request body (SubagentRunRequest)

FieldTypeRequired
session_idstringno
typestringno
descriptionstringno
promptstringyes
emit_skillbooleanno

Responses: 200 Successful Response, 422 Validation Error

Live Agents ​

GET /api/agents ​

List agent runs

Responses: 200 Successful Response

POST /api/agents/launch ​

Launch a tracked agent

Request body (SubagentRunRequest)

FieldTypeRequired
session_idstringno
typestringno
descriptionstringno
promptstringyes
emit_skillbooleanno

Responses: 200 Successful Response, 422 Validation Error

GET /api/agents/{task_id} ​

Get an agent run

Parameters

NameInRequiredTypeDefault
task_idpathyesstring

Responses: 200 Successful Response, 422 Validation Error

POST /api/agents/{task_id}/cancel ​

Cancel an agent run

Parameters

NameInRequiredTypeDefault
task_idpathyesstring

Responses: 200 Successful Response, 422 Validation Error

Engagement ​

GET /api/engagement ​

Engagement snapshot

Responses: 200 Successful Response

POST /api/engagement ​

Start / end / set-mode the engagement

Request body

Responses: 200 Successful Response, 422 Validation Error

GET /api/engagement/report ​

Read engagement report

Responses: 200 Successful Response

POST /api/engagement/report ​

Generate engagement report

Responses: 200 Successful Response

Knowledge ​

Search the knowledge store

Parameters

NameInRequiredTypeDefault
qqueryyesstring
kquerynointeger10
tablequerynostring

Responses: 200 Successful Response, 422 Validation Error

Audit ​

GET /api/audit/recent ​

Recent audit entries

Parameters

NameInRequiredTypeDefault
nquerynointeger50
session_idquerynostring

Responses: 200 Successful Response, 422 Validation Error

Scheduler ​

GET /api/scheduler/jobs ​

List scheduled jobs

Responses: 200 Successful Response

POST /api/scheduler/jobs ​

Schedule a job

Request body (ScheduleAddRequest)

FieldTypeRequired
promptstringyes
schedulestringyes
job_idstringno

Responses: 200 Successful Response, 422 Validation Error

DELETE /api/scheduler/jobs/{job_id} ​

Cancel a scheduled job

Parameters

NameInRequiredTypeDefault
job_idpathyesstring

Responses: 200 Successful Response, 422 Validation Error

Notes ​

GET /api/notes/workspace ​

Load notes workspace

Parameters

NameInRequiredTypeDefault
project_pathqueryyesstring

Responses: 200 Successful Response, 422 Validation Error

POST /api/notes/workspace ​

Save notes workspace

Request body (NotesSaveRequest)

FieldTypeRequired
project_pathstringyes
workspaceobjectyes

Responses: 200 Successful Response, 422 Validation Error

Beads ​

POST /api/beads/init ​

Initialize beads

Request body (BeadsInitRequest)

FieldTypeRequired
project_pathstringyes
prefixstringno

Responses: 200 Successful Response, 422 Validation Error

GET /api/beads/issues ​

List beads issues

Parameters

NameInRequiredTypeDefault
project_pathqueryyesstring

Responses: 200 Successful Response, 422 Validation Error

POST /api/beads/issues ​

Create a beads issue

Request body (BeadsCreateRequest)

FieldTypeRequired
project_pathstringyes
titlestringyes
typestringno
priorityintegerno
descriptionstringno
assigneestringno

Responses: 200 Successful Response, 422 Validation Error

DELETE /api/beads/issues/{issue_id} ​

Delete a beads issue

Parameters

NameInRequiredTypeDefault
issue_idpathyesstring
project_pathqueryyesstring

Responses: 200 Successful Response, 422 Validation Error

PATCH /api/beads/issues/{issue_id} ​

Update a beads issue

Parameters

NameInRequiredTypeDefault
issue_idpathyesstring

Request body (BeadsUpdateRequest)

FieldTypeRequired
project_pathstringyes
titlestringno
descriptionstringno
statusstringno
priorityintegerno
typestringno
assigneestringno

Responses: 200 Successful Response, 422 Validation Error

POST /api/beads/issues/{issue_id}/close ​

Close a beads issue

Parameters

NameInRequiredTypeDefault
issue_idpathyesstring

Request body (BeadsCloseRequest)

FieldTypeRequired
project_pathstringyes
reasonstringno

Responses: 200 Successful Response, 422 Validation Error

GET /api/beads/status ​

Beads status

Parameters

NameInRequiredTypeDefault
project_pathqueryyesstring

Responses: 200 Successful Response, 422 Validation Error

.Well-Known ​

GET /.well-known/agent-card.json ​

Get Agent Card

Responses: 200 Successful Response

A2A ​

POST /a2a ​

A2A JSON-RPC endpoint

Request body (A2ARequest)

FieldTypeRequired
jsonrpcstringyes
idstringinteger
methodstringyes
paramsSendMessageRequestGetTaskRequest

Responses: 200 Successful Response

Activity ​

GET /api/activity ​

Activity thread history (ADR 0003)

Responses: 200 Successful Response

Config ​

GET /api/config ​

Current agent config (UI-safe, no secrets)

Responses: 200 Successful Response

POST /api/config/models ​

Probe an OpenAI-compatible gateway for models

Request body

Responses: 200 Successful Response, 422 Validation Error

POST /api/config/oauth/cancel ​

Abandon an in-progress OAuth sign-in

Request body

Responses: 200 Successful Response, 422 Validation Error

POST /api/config/oauth/complete ​

Complete a paste-code OAuth flow (claude)

Request body

Responses: 200 Successful Response, 422 Validation Error

POST /api/config/oauth/disconnect ​

Disconnect a native OAuth provider

Request body

Responses: 200 Successful Response, 422 Validation Error

POST /api/config/oauth/poll ​

Poll a device-code OAuth flow (codex)

Request body

Responses: 200 Successful Response, 422 Validation Error

POST /api/config/oauth/start ​

Begin an OAuth sign-in flow

Request body

Responses: 200 Successful Response, 422 Validation Error

GET /api/config/oauth/status ​

Native OAuth sign-in status (safe to poll)

Responses: 200 Successful Response

GET /api/config/presets/{name} ​

Read a SOUL preset

Parameters

NameInRequiredTypeDefault
namepathyesstring

Responses: 200 Successful Response, 422 Validation Error

POST /api/config/setup ​

Write config + key and reload the agent

Request body

Responses: 200 Successful Response, 422 Validation Error

GET /api/config/setup-status ​

Setup wizard status

Responses: 200 Successful Response

Delegations ​

GET /api/delegations ​

List in-flight subagent delegations

Parameters

NameInRequiredTypeDefault
session_idquerynostring

Responses: 200 Successful Response, 422 Validation Error

POST /api/delegations/{tool_call_id}/cancel ​

Cancel one in-flight delegation

Parameters

NameInRequiredTypeDefault
tool_call_idpathyesstring

Responses: 200 Successful Response, 422 Validation Error

Engagements ​

GET /api/engagements ​

Engagement history

Responses: 200 Successful Response

Events ​

GET /api/events ​

Server→client event stream (SSE)

Responses: 200 Successful Response

Goal ​

DELETE /api/goal/{session_id} ​

Clear a goal

Parameters

NameInRequiredTypeDefault
session_idpathyesstring

Responses: 200 Successful Response, 422 Validation Error

POST /api/goal/{session_id}/detach ​

Detach a goal drive (run headless)

Parameters

NameInRequiredTypeDefault
session_idpathyesstring

Responses: 200 Successful Response, 422 Validation Error

Goals ​

GET /api/goals ​

List goals (autonomy layer)

Responses: 200 Successful Response

Intel ​

Unified intel search

Parameters

NameInRequiredTypeDefault
qqueryyesstring
kquerynointeger20

Responses: 200 Successful Response, 422 Validation Error

Memory ​

GET /api/memory/injections ​

Recent auto-injected memory (ADR 0069 forensics)

Parameters

NameInRequiredTypeDefault
nquerynointeger50
session_idquerynostring

Responses: 200 Successful Response, 422 Validation Error

Playbooks ​

GET /api/playbooks ​

List playbooks

Responses: 200 Successful Response

POST /api/playbooks/{name}/run ​

Run a playbook

Parameters

NameInRequiredTypeDefault
namepathyesstring

Request body

Responses: 200 Successful Response, 422 Validation Error

Skills ​

GET /api/skills ​

List/search learned skills

Parameters

NameInRequiredTypeDefault
qquerynostring

Responses: 200 Successful Response, 422 Validation Error

Targets ​

GET /api/targets ​

List discovered targets

Parameters

NameInRequiredTypeDefault
qquerynostring
device_typequerynostring
limitquerynointeger50

Responses: 200 Successful Response, 422 Validation Error

GET /api/targets/{host_id} ​

Target profile

Parameters

NameInRequiredTypeDefault
host_idpathyesinteger

Responses: 200 Successful Response, 422 Validation Error

Tools ​

GET /api/tools ​

Capabilities catalog (categorized tool registry)

Responses: 200 Successful Response

Workflows ​

GET /api/workflows ​

List workflow recipes (ADR 0002)

Responses: 200 Successful Response

POST /api/workflows/{name}/run ​

Run a workflow recipe (ADR 0002)

Parameters

NameInRequiredTypeDefault
namepathyesstring

Request body

Responses: 200 Successful Response, 422 Validation Error

The Targets / Intel / Playbooks / Workflows routes above are operator-key-gated (x-api-key). POST /api/playbooks/{name}/run returns 409 when the engagement/scope gate blocks an offensive fire — see Playbooks.

Agent-to-Agent (A2A) ​

All A2A tasks are fully async. message/send and POST /message:send return submitted in under a second; the LangGraph agent runs in the background. See the A2A Integration guide for full workflow examples.

Common headers:

HeaderRequiredDescription
Content-Typeyesapplication/json
x-api-keyconditionalRequired when PROTOPEN_API_KEY is set

GET /.well-known/agent.json ​

Returns the A2A agent card describing protoPen's capabilities and skills.

Response:

json
{
  "name": "protopen",
  "description": "Autonomous pen testing and security research agent...",
  "url": "http://steamdeck:7870",
  "provider": {"organization": "protoLabsAI"},
  "version": "2.0",
  "capabilities": {"streaming": true, "pushNotifications": true},
  "skills": [
    {"id": "passive_recon", "name": "Passive Reconnaissance", "...": "..."},
    {"id": "active_pentest", "name": "Active Penetration Test", "...": "..."},
    {"id": "security_report", "name": "Security Report", "...": "..."},
    {"id": "threat_intel", "name": "Threat Intelligence", "...": "..."},
    {"id": "summarize", "name": "Summarize", "...": "..."}
  ]
}

POST /a2a ​

JSON-RPC 2.0 envelope. Dispatches to the method named in "method".

The endpoint accepts two equivalent method-name sets (issue #322): the A2A-spec JSON-RPC names below (message/send, message/stream, tasks/get, tasks/cancel, agent/getAuthenticatedExtendedCard, …) and the gRPC-style proto names the console and scheduler use (SendMessage, SendStreamingMessage, GetTask, ListTasks, CancelTask, …). Both drive the same executor. External callers should prefer the spec names.

Methods:

MethodDescription
message/sendSubmit task — returns submitted immediately, runs in background
message/streamSubmit task and stream SSE events; first frame is always submitted

POST /message:send ​

REST alias for message/send. Returns HTTP 202 Accepted with the task record (no JSON-RPC wrapper).

Request body:

json
{
  "message": {"parts": [{"kind": "text", "text": "your prompt"}]},
  "contextId": "optional-session-id",
  "pushNotification": {"url": "https://...", "token": "optional-bearer-token"}
}

POST /message:stream ​

REST alias for message/stream. Returns text/event-stream. First SSE frame carries submitted state + task ID.


GET /tasks/{id} ​

Poll task status and retrieve artifacts once complete.

Response:

json
{
  "id": "3f8a1c2d-...",
  "contextId": "engagement-001",
  "status": {"state": "completed"},
  "artifacts": [{"parts": [{"kind": "text", "text": "..."}]}]
}

Status codes: 200 OK, 404 Not Found


GET /tasks/{id}:subscribe ​

Subscribe to a running task's SSE stream. Replays current state on connect and streams updates until the task reaches a terminal state. Use this to reconnect after a dropped stream.


POST /tasks/{id}:cancel ​

Request cancellation of a running task.

Status codes:

  • 200 OK — canceled
  • 409 Conflict — task already in terminal state
  • 404 Not Found — unknown task ID

POST /tasks/{id}/pushNotificationConfigs ​

Register a webhook URL to receive state-change POSTs (working, completed, failed). Delivery retried up to 3× with exponential backoff.

Request body:

json
{"url": "https://your-server.example.com/hook", "token": "optional-bearer-token"}

Observability ​

GET /metrics ​

Prometheus metrics endpoint (requires prometheus-client package).

Exposed metrics:

MetricTypeLabelsDescription
protopen_llm_calls_totalCountermodel, finish_reasonTotal LLM API calls
protopen_llm_latency_secondsHistogrammodelLLM call latency
protopen_llm_tokens_totalCountermodel, directionTokens consumed (input/output)
protopen_tool_calls_totalCountertool_name, successTotal tool executions
protopen_tool_latency_secondsHistogramtool_nameTool execution latency
protopen_active_sessionsGauge--Currently active chat sessions

Part of the protoLabs autonomous development studio.