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

50 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

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

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

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

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".

Methods:

MethodDescription
message/sendSubmit task — returns submitted immediately, runs in background
message/sendStreamSubmit 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/sendStream. 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.