Skip to content
BreachPilot

API Integration

SPA targets same /api/v1 REST + WebSocket as docs/api.md. Base http://127.0.0.1:8765, dev vite.config.ts:22 /api proxy (VITE_API_URL override). All routes except GET /health require Authorization: Bearer (api/client.ts:75).

Client core (api/client.ts:69)

SymbolDetail
get/set/clearStoredTokensessionStorage breachpilot.apiToken.v1, defensive try/catch, removeItem when empty
ApiError extends Error (client.ts:29){status,code,details,requestId,raw} + isAuth(401) isNotFound(404) isConflict(409)
apiFetch<T>(path, {method,body,signal,headers,raw})injects Accept: application/json + bearer + Content-Type on writes; prefixes /api/v1 unless http or /api/; 204→undefined; fetch throws → ApiError status0 network; else read content-type + json/text; on !oknormalizeError, on raw blob mode returns Blob; normalizeError(status,body) (client.ts:125): if body.error→ from envelope, if body.detailhttp_error, else responseStatusText(map 400/401/403/404/409/422/500/502/503/504)

Prefix constant API_PREFIX="/api/v1" (client.ts:67).

Types (api/types.ts:879)

ExportShape
ConnectionStatus `activestale
RunState`draft
DecisionKind/Status/RiskTag/RunMode/RunKind/SkillsMode/ObserverMode`"start_confirm"
CampaignCheckpointKind `accessno_path+CampaignNextStepOption {action,label,goals?:{name,desc}[]}`
Capabilities{api_version, features[], constraints{max_concurrent_runs,loopback_only,manual_tool_calls}, run_options{modes,kinds,flags}}
GoalPreset {name,description,risk,compatible} + SuggestedGoal + ReconAssessment {target_ip,os_verdict,open_ports,services,cve_findings,overall_risk_score} + ModelInfo/ChatgptModelsBlock/ModelRegistryInfo/LiveModelsResponse/ChatgptProviderStatus/ProvidersResponse/ChatgptLoginResponse/ChatgptProxyResponse + SkillSummary/Detail/SearchResult/AttackModuleSummary/PluginSummary/SecretsStatus/SecretWriteResult/ConfigSchema
RunCreateRequest {target,mode,goal,custom_goal,recon_first,model,swarm,parallel_swarm,critic,reflection,adaptive_exploits,long_session,multi_model_consult,observer_mode,ultrathink,skills,skills_include/exclude,resume,kind,yes}POST /runs body
RunPreview {run_id,target_ip,original_target,resolved_*,mode,goal_name/model_alias/transport_summary/permission/attack_mode/destructive/required_confirmation_text/budgets/swarm/…} + CreateRunResponse {run_id,preview,state,decision?} + RunListRow/Response + RUN_SORT_OPTIONS + RunDetail {id,state,created_at,updated_at,request:RunDetailRequest,preview,result:RunResult,error,title,cancelled_at,decisions:DecisionListRow[]} + RunResult {run_id,target_ip,mode,goal_name,total_actions,workspace,audit_path,outcome_summary,telemetry:RunResultTelemetry,active_skills,safety_review,swarm_result,…}
DecisionListRow/DecisionOut/DecisionAnswerResponse + ArtifactSummary/Response + ChainEntry/ExploitationChain/CVSSScore/TechnicalFinding/EnhancedReport (exploitation_chains+technical_findings for AttackGraph) + AuditResponse/SwarmState/CampaignState/LogResponse/CredentialRecord/LootItem/ToolSchema/ToolsResponse/DeleteRunResponse
EventType`state
RunEvent {sequence,timestamp,run_id,type,payload} + EventReplayResponse {run_id,events,oldest/latest_sequence,has_more_before}events replay
TelemetrySummary/Record/Response, MemoryLesson/Confidence/AttackMemoryItem/MemoryResponse, WorkspaceFile/Response, ConfigPatchResponse/ConfigValidationErrorResponse/ApiErrorEnvelope/Shape, ACTIVE_RUN_STATES/TERMINAL_RUN_STATES, isActiveState/isTerminalState/stateCategory, GraphNode/Edge/RunGraphResponse, WitnessFlag/Response

Hook → endpoint map (api/hooks.ts:63 + docs/api.md)

HookMethodURL patternDocs ref
useCapabilitiesGET/capabilitiesdocs/api.md: GET /capabilities
useConfig / useConfigSchema / usePatchConfigGET/PATCH/config, /config/schema, PATCH /config body patch mergedPATCH /config atomic + allowed_origins loopback validate
useSecrets / usePutSecretsGET / PUT/secrets, PUT /secrets {secrets} write-only, redactedGET /secrets vs PUT /secrets
useModels / useLiveModels / useAddModel / useRemoveModel / useSetModelProviderGET/POST/DELETE/models, /models/live (503 payload swallowed), /models POST {alias,model}, DELETE /models/<alias>, POST /models/provider {provider}GET /models, /models/live branches ollama/chatgpt
useProviders (+ chatgpt login/proxy)GET/POST/providers, POST /providers/chatgpt/login, POST /providers/chatgpt/proxy/{start,stop}docs/api.md: GET/POST /providers/*
useSystemInfo / useTelemetry / useMemoryGET/system/info, /system/telemetry, /system/memorySystem routes
usePlugins / useAttackModules / useGoalsGET/plugins, /attack/modules, /goalsGET /plugins def [] on error; goals stale Infinity
useSkills / useSkillSearch / useSkillDetail / useInstallSkill / useRemoveSkillGET/POST/DELETE/skills, /skills/search?q, /skills/<name>, POST /skills {name,markdown}, DELETE /skills/<name>
useDiagnostics / useResetSystemPOST/diagnostics/{doctor,self-test}, POST /system/reset invalidates runs/telemetry/memory
useRunsGET/runs?limit&offset&sort&q&state limit 1-200docs/api.md: GET /runs
useRun / useCreateRun / useCancelRun / useResumeRun / useDeleteRun / useRetitleRunGET/POST/DELETE/runs/<id>, POST /runs body RunCreateRequest, POST /runs/<id>/{cancel,resume,title} title POST {title regen}docs/api.md: POST /runs, POST /runs/*
useDecisions / useDecision / useAnswerDecisionGET/POST/runs/<id>/decisions, POST /runs/<id>/decisions/<decId> {answer} invalidates runDecisions+run+runsdocs/api.md: Decision Routes
useRunTools / useCallToolGET / POST/runs/<id>/tools, POST /runs/<id>/tools/<name>/calls {arguments} policy-gated via tool_lock, 403 tool_denieddocs/api.md: GET /runs/<id>/tools, POST …/tools/<name>/calls
useArtifacts / useAudit / useSwarmState / useCampaignState / useRunLogGET/runs/<id>/artifacts 30s while active, /audit, /swarm & /campaign 404 no retry, /logs/<name>?tail&attempt_id&target_ipdocs/api.md: Artifacts/Audit/Logs
useCredentials / useRevealCredential / useConfirmCredential / useLootGET/POST/runs/<id>/credentials, POST /credentials/<i>/reveal, POST …/confirm, GET /…/lootcred masked
useWorkspace / useWorkspaceFileUrl / useFetchWorkspaceFileGET raw/runs/<id>/workspace, /workspace/<path> raw:true Blob
useArtifactUrl / useFetchArtifactBlobraw/runs/<id>/artifacts/<name> raw Blobdownload
useConnections / useConnection / useConnectionListenerGET 10-15s poll/connections?status&target, /connections/<id>, /connections/<id>/listener?lines 1-500 boundeddocs/api.md: Connections ConnectionManager source of truth
useCheckConnection / useRemoveConnectionPOST invalidates lists/connections/<id>/check updates last_check/check_output/status, /connections/<id>/remove graceful mark_removed + best-effort listener stopdocs/api.md: POST /connections/*
useRunGraph / useWitnessGET 404 no retry/runs/<id>/graph, /witnessdocs/api.md: Graph Explorer Routes when gated
Graph explorer (graphApi.ts)GET/graph/runs/<id>, /…/summary, /…/conflicts, /…/nodes/<nid>, /…/nodes/<nid>/neighbors?max_hops&max_nodes, /…/paths?start&end&max_length&max_pathsdocs/api.md: Graph Explorer Routes bounds limit≤500 caps

Real-time transport

TransportURL pattern (from ws.ts:239, sse.ts:195)AuthRoute
WebSocket (primary)ws(s)://<host>/api/v1/ws/v1/runs/<runId> then send {auth:token, after:N}first message auth + hmac.compare_digestdocs/api.md: WS /ws/v1/runs/<runId> heartbeats every 30s
SSE fallback (after 3 WS failures)<origin>/api/v1/runs/<runId>/events/stream?after=<seq> + Authorization: Bearer header (sse.ts:200)header bearerGET /runs/<id>/events/stream (SSE)
ReplayGET /runs/<id>/events?tail=MAXbearerdocs/api.md: GET /runs/<id>/events?after

Close codes handled in ws.ts:275: 4400 invalid cursor, 4401 auth, 4403 origin, 4404 run not found, 1011 server not configured. SSE status 401/403 → fatal authError. Reconnect backoff min(10000, 1000*2**attempt) + on attempts both layers.

defaultQueryOptions (hooks.ts:107) polling

useRuns adaptive 5s active vs 60s idle; useRun 5s while running|queued|cancelling; useDecisions 5s while pending; useArtifacts 30s while active reading qc.getQueryData(run). useConnections adaptive 12s active / 15s stale / 30s idle; useConnection 10s while active/stale else 30s (removed → no poll); useConnectionListener 3s while drawer open + active, staleTime 2s.

Deserialization notes

  • useLiveModels catches ApiError status 503 && raw and returns raw as LiveModelsResponse instead of throwing so UI can show daemon error payload (hooks.ts:205) with LiveModelsResponse.source ∈ {ollama,registry,chatgpt}.
  • Graph explorer 404 (disabled route or no graph) disables retry (ApiError.isNotFound guard).
  • Swarm/Campaign 404 similarly gated as optional artifacts.
  • apiFetch raw:true path returns Blob for workspace/artifact download; non-JSON non-raw returns text (client.ts:121).

Where consumers use it

FrontendConsumes
TokenGateuseCapabilities verify token
OnboardingGateuseSecrets keys status
ProviderSettingsuseModels/useLiveModels/useProviders + chatgpt login/proxy mutations
RunWizarduseCapabilities flags + useGoals/useSkills/useDefaultModel + useCreateRun
RunPageuseRun/useDecisions/useRunEvents/useArtifacts/useAudit/useSwarmState/useCampaignState/useWitness/useRunTools/useCallTool/useFetchArtifactBlob/useCapabilities/useConfig
AttackGraphPagefeatures/graph/graphApi explorer hooks (not api/hooks graph)
RunListPageuseRuns (50), useDeleteRun/useResumeRun/useRetitleRun/useCapabilities
StatsPageuseRuns(200)+useTelemetry aggregations
MemoryPageuseMemory
LootPageuseLoot + CredentialTableuseCredentials/useRevealCredential
ArtifactsPageuseArtifacts/useWorkspace/useAudit/useRunLog
SkillsPageuseSkills/useSkillSearch/useSkillDetail/useConfig/usePatchConfig/useInstallSkill/useRemoveSkill
GoalsPage/AttackModulesPageuseGoals/useAttackModules
ConnectionsPageuseConnections/useConnection/useConnectionListener/useCheckConnection/useRemoveConnection — KPI + filter/search/sort table (responsive cards on mobile) + details drawer with listener output (Live 3s poll, bounded monospace) + health-check + removal confirm; ConnectionManager source of truth
source: repo docs (build sync)Edit this page on GitHub →