Skip to navigation

Console API

The Console API functions are typed wrappers around the Pensar Console REST API. They’re what the pensar issues, pensar pentests, pensar apps, and related CLI commands call.

Every function authenticates with the credentials from pensar login (or PENSAR_API_KEY), and operates on the selected workspace. See Pensar Console authentication. They throw Error on non-2xx responses. See Console API errors.

Import
import { dispatchPentest, listIssues, updateIssue } from "@pensar/apex/core/api";

Functions that take an issueId accept either the issue UUID or its label, such as VULN-000123.

Pentests

FunctionReturnsDescription
dispatchPentest(opts?)DispatchPentestResultQueue a Console pentest of the workspace
listScans()ScanSummary[]List pentests
getScan(scanId)ScanDetailPentest status, issue count, and report readiness
listPentestTargets(pentestId)PentestTargetSummary[]Endpoints exercised by a pentest
dispatchPentest(opts)
{ branch?: string; scanLevel?: 'priority' | 'full'; endpointIds?: string[]; knowledgeEntryIds?: string[] }

scanLevel sets scan depth: priority (the server default) or full. Pass endpointIds (1–1000 endpoint UUIDs) to test specific existing endpoints. Endpoint launches run at full depth and can’t be combined with branch or priority depth. Pass knowledgeEntryIds to give agents specific knowledge entries. Resolves with { scanId, label, status: "queued", message }. See pensar pentests for details.

Issues

FunctionReturnsDescription
listIssues(filters?)IssueSummary[]List issues, filtered by scanId, status, severity, or branch
getIssue(issueId)IssueDetailFull issue detail, including CVSS, CWEs, and location
getIssueEvidence(issueId)IssueEvidencePOC, POC output, and reproduction steps
updateIssue(issueId, data)UpdateIssueResultChange status, close with a disposition, or flag a false positive
retestIssue(issueId)RetestIssueResultQueue a retest of the issue
listIssueRetests(issueId)IssueRetest[]Retest history
listIssueComments(issueId, options?)IssueCommentPagePaginated comments (page, pageSize)
createIssueComment(issueId, body)IssueCommentSummaryPost a comment
linkPullRequest(issueId, url)LinkPullRequestResultLink an external fix PR; the issue closes when it merges
listIssuePullRequests(issueId)PullRequestSummary[]PRs linked to an issue
updateIssue(issueId, data)
{ status?: 'open' | 'closed' | 'false-positive' | 'in-review'; closedDisposition?: 'resolved' | 'duplicate' | 'wont-fix' | 'out-of-scope' | 'risk-accepted'; duplicateOf?: string; closedReason?: string; closedComments?: string; userFlaggedFalsePositive?: boolean; userFlaggedFalsePositiveReason?: string }

duplicateOf (the UUID or label of the original) is only sent with the duplicate disposition. The accepted dispositions are exported as CLOSED_DISPOSITIONS.

Fixes

FunctionReturnsDescription
listFixes(issueId)FixSummary[]Fixes Pensar generated for an issue
getFix(fixId)FixDetailThe fix’s diff and explanation

Agent logs

FunctionReturnsDescription
listAgentLogs(issueId, opts?)ListAgentLogsResultLogs of the agent that found an issue
searchAgentLogs(issueId, query, opts?)SearchAgentLogsResultFull-text search over those logs, with contextLines
listTargetLogs(targetId, opts?)ListTargetLogsResultLogs for one pentest target
searchTargetLogs(targetId, query, opts?)SearchTargetLogsResultSearch one target’s logs

Filter options: level (debug, info, warn, error), role (assistant, user, system, tool-call, tool-result), and limit for list calls.

Apps and endpoints

FunctionReturnsDescription
listApps(opts?)ListAppsPageOne page of apps (limit default 100, max 200, plus offset)
listAppsAll()AppSummary[]Every app, fetched page by page
searchApps(query, opts?)SearchAppsResultSubstring search over apps
getApp(appId)AppDetailApp detail
createApp(data)AppDetailCreate an app (name and description required)
updateApp(appId, data)AppDetailUpdate an app
deleteApp(appId)DeleteResultDelete an app
listEndpoints(appId, filters?)ListEndpointsPageOne page of an app’s endpoints, filtered by type or minRiskScore
listEndpointsAll(appId, filters?)EndpointSummary[]Every endpoint, fetched page by page
searchEndpoints(query, opts?)SearchEndpointsResultSearch endpoints across the workspace or within one applicationId
getEndpoint(endpointId)EndpointDetailFull endpoint, including objectives, threat model, and risk breakdown
createEndpoint(appId, data)EndpointDetailAdd an endpoint (endpoint and description required)
updateEndpoint(endpointId, data)EndpointDetailUpdate or move an endpoint
deleteEndpoint(endpointId)DeleteResultDelete an endpoint

List and search responses return lean summaries. Call getApp or getEndpoint for the full record.

Knowledge

FunctionReturnsDescription
listKnowledge(filters?)KnowledgeEntry[]List entries, filtered by category, status, or tags
getKnowledge(id)KnowledgeEntryOne entry
createKnowledge(input)KnowledgeEntryAdd an entry agents can use in future pentests
updateKnowledge(id, input)KnowledgeEntryUpdate an entry
archiveKnowledge(id)KnowledgeEntryArchive an entry

Categories (KNOWLEDGE_CATEGORIES): false_positive_pattern, technology_context, testing_history, user_note, agent_learning. Statuses (KNOWLEDGE_STATUSES): active, stale, archived.

Domains

FunctionReturnsDescription
listDomains(){ domains: DomainSummary[] }Workspace domains, with verified status
createDomain({ url })DomainSummaryAdd a domain. Idempotent: the URL is canonicalized. New domains start unverified, and reconnaissance doesn’t start.

Example

Triage open critical issues
import {
createIssueComment,
getIssueEvidence,
listIssues,
updateIssue,
} from "@pensar/apex/core/api";
const issues = await listIssues({ status: "open", severity: "critical" });
for (const issue of issues) {
const evidence = await getIssueEvidence(issue.id);
if (!evidence.poc) {
await updateIssue(issue.id, {
status: "in-review",
});
await createIssueComment(issue.id, "No POC attached; needs manual verification.");
continue;
}
console.log(`${issue.issueLabel ?? issue.id}: ${issue.title} (${issue.url})`);
}