Resources

A tour of the SDK resource namespaces — pentests, vulnerabilities, agents, teams, chats, usage and more — with realistic method calls.

Every part of the Rank API is exposed as a resource hanging off the client (client.pentests, client.agents, client.teams, …). Sub-resources nest naturally, for example client.pentests.vulnerabilities or client.agents.tools. All examples below use the synchronous client; the asynchronous client has the same shape — just await each call.

The namespaces available on a client are: ai, auth, pentests, teams, agents, chats, tiers, invitations, permissions, tickets, usage and billing.

Pentests

The client.pentests resource covers the full lifecycle: CRUD, execution control and the nested sub-resources for agents, assets, vulnerabilities and more.

# List (paginated, filterable)
pentests = client.pentests.list(status="running", type="web")
for p in pentests.items:
    print(p.id, p.name, p.status)

# Create — at least one asset is required
pentest = client.pentests.create(
    name="Web scan",
    type="web",
    mode="automatic",
    assets=[{"asset_type": "url", "asset_value": "https://example.com", "is_primary": True}],
)

# Retrieve, update, delete
pentest = client.pentests.retrieve(pentest.id)
client.pentests.update(pentest.id, name="Web scan v2")
client.pentests.delete(pentest.id)

Lifecycle and control

# Mark a pentest as completed (after phases / processing)
client.pentests.finish(pentest.id)

# Cancel a running pentest (Go backend)
client.pentests.cancel(pentest.id)

# Process raw agent output into vulnerabilities with AI (guided mode)
client.pentests.process_vulnerabilities(pentest.id, model_alias="gemini-2.5-flash")

# Generate a PDF report and email it
client.pentests.generate_report(
    pentest.id,
    recipient_email="security@example.com",
    extended=1,  # 0 = summary, 1 = full report with evidence
)

# Operation evidences and global quality gate
client.pentests.evidences(pentest.id)
client.pentests.quality_gate(max_open_critical=0, max_open_high=5, min_resolution_rate=80.0)

Launching a pentest and reconnecting to a running one are streaming operations covered in Streaming: use client.ai.chat.stream(...) to start one and client.pentests.stream(pentest_id) to reattach.

Pentest sub-resources

Sub-resourcePurpose
client.pentests.vulnerabilitiesTriage findings (see below)
client.pentests.agentsAssign and inspect the agents on a pentest
client.pentests.assetsManage targets attached to a pentest
client.pentests.phasesInspect the phases of a pentest
client.pentests.methodologiesList available methodologies
client.pentests.commentsRead and post pentest comments
client.pentests.webhooksConfigure pentest webhooks
client.pentests.scheduledManage scheduled pentests
# Methodologies are needed to create a guided pentest
methodologies = client.pentests.methodologies.list()
for m in methodologies.items:
    print(m.id, m.name)

# Assign agents to a phase (guided mode: minimum 3, maximum 4)
client.pentests.agents.assign(
    pentest.id,
    agents=[
        {"agent_id": 10, "phase_id": 1, "execution_order": 1},
        {"agent_id": 11, "phase_id": 1, "execution_order": 2},
        {"agent_id": 12, "phase_id": 1, "execution_order": 3},
    ],
)

# Automatic mode auto-assigns the default agents across all phases
defaults = client.pentests.agents.default(pentest.id)
print(f"Auto-assigned {defaults.assigned_count} agents")

Scheduled pentests

Re-run a completed pentest on a recurring schedule with client.pentests.scheduled:

schedule = client.pentests.scheduled.create(
    pentest_id=pentest.id,
    schedule_type="weekly",   # once | daily | weekly | monthly
    schedule_time="02:00",
    schedule_day="monday",
)
client.pentests.scheduled.list()
client.pentests.scheduled.update(schedule.id, schedule_time="03:30")
client.pentests.scheduled.delete(schedule.id)

Vulnerabilities

Vulnerabilities are nested under a pentest and offer a rich triage workflow. Every method takes the pentest_id as its first argument.

# List and inspect
vulns = client.pentests.vulnerabilities.list(pentest.id, severity="critical")
for v in vulns.items:
    print(v.severity, v.vulnerability, v.status)

vuln = client.pentests.vulnerabilities.retrieve(pentest.id, vulnerability_id=42)

# Edit fields (use the dedicated transitions for status changes)
client.pentests.vulnerabilities.update(
    pentest.id, 42, severity="high", priority="urgent", due_date="2026-07-15",
)

# Aggregated stats and export
client.pentests.vulnerabilities.summary(pentest.id)
client.pentests.vulnerabilities.export(pentest.id)

Status transitions

Each transition is a dedicated method rather than a free-form status write.

client.pentests.vulnerabilities.resolve(
    pentest.id, 42, resolution_type="evidenced", comment="Patched in v2.3.1",
)
client.pentests.vulnerabilities.reopen(pentest.id, 42, reason="Regression in v2.3.2")
client.pentests.vulnerabilities.false_positive(pentest.id, 42, reason="Not reachable in prod")
client.pentests.vulnerabilities.accept_risk(pentest.id, 42, reason="Low impact, next quarter")

# Generic transitions are limited to "open" / "in_progress"
client.pentests.vulnerabilities.change_status(pentest.id, 42, status="in_progress")
client.pentests.vulnerabilities.change_priority(pentest.id, 42, priority="urgent")

Assignment, comments, evidence and history

# Assignment to a team member
client.pentests.vulnerabilities.assign(pentest.id, 42, user_id=7, comment="Please investigate")
client.pentests.vulnerabilities.unassign(pentest.id, 42)

# Comments
client.pentests.vulnerabilities.add_comment(pentest.id, 42, comment="Confirmed in staging")
client.pentests.vulnerabilities.list_comments(pentest.id, 42)
client.pentests.vulnerabilities.update_comment(pentest.id, 42, comment_id=15, comment="Updated")
client.pentests.vulnerabilities.delete_comment(pentest.id, 42, comment_id=15)

# Evidence files (httpx multipart tuples)
files = [("files", ("screenshot.png", open("screenshot.png", "rb"), "image/png"))]
client.pentests.vulnerabilities.upload_evidence_files(pentest.id, 42, files=files)
client.pentests.vulnerabilities.list_evidence_files(pentest.id, 42)
client.pentests.vulnerabilities.get_evidence_file(pentest.id, 42, file_id=5)
client.pentests.vulnerabilities.delete_evidence_file(pentest.id, 42, file_id=5)

# Original operation evidence and change history
client.pentests.vulnerabilities.evidence(pentest.id, 42)
client.pentests.vulnerabilities.history(pentest.id, 42)

Bulk and quality gate

# Bulk status change (targets limited to "open" / "in_progress")
result = client.pentests.vulnerabilities.bulk_update_status(
    pentest.id, vulnerability_ids=[42, 43, 44], status="in_progress", comment="Batch triage",
)

# Per-pentest quality gate
client.pentests.vulnerabilities.quality_gate(
    pentest.id,
    rules=[
        {"severity": "critical", "max_open": 0},
        {"severity": "high", "max_open": 5},
        {"min_resolution_rate": 0.8},
    ],
)

# Global summary across all pentests
client.pentests.vulnerabilities.global_summary()

Agents

Agents are the AI workers that run pentests and power chat. The client.agents resource manages them, their tools, the AI models they run on, and the MCP servers they connect to.

# List agents (filterable by type and phase)
client.agents.list(type="pentest")
client.agents.list(type="pentest", phase_id=1)
client.agents.list(type="general")

# Create, update, clone, delete
agent = client.agents.create(
    name="Custom Recon Agent",
    instructions="Enumerate subdomains, scan ports and fingerprint technologies.",
    agent_type="pentest",
    phase_id=1,
    model_id=6,
)
client.agents.update(agent.agent.id, name="Recon Agent v2")
client.agents.clone(agent.agent.id)
client.agents.delete(agent.agent.id)

Models, tools and MCP servers

# AI models — list the catalog, assign to your account, then use them on agents
client.agents.models.list()
client.agents.models.assign(model_ids=[5, 6, 12])
client.agents.models.mine()
client.agents.models.remove(model_id=5)

# Tools assigned to an agent
client.agents.tools.list(agent_id=10)
client.agents.tools.available(agent_id=10)
client.agents.tools.assign(agent_id=10, tool_ids=[1, 2, 3])
client.agents.tools.remove(agent_id=10, tool_id=3)

# MCP servers
server = client.agents.mcps.create(
    name="Internal Tooling MCP", transport_type="streamable_http", url="https://mcp.internal.example.com",
)
client.agents.mcps.assign(agent_id=10, mcp_server_ids=[server.id])
client.agents.mcps.list(agent_id=10)

Teams

Teams are the collaboration layer. Roles and permissions gate access to shared pentests, agents and chats, so set those up before inviting members.

team = client.teams.create(name="Security Team", description="Red team operations")

# Roles and permissions
role = client.teams.roles.create(team.id, role_name="Pentester")
client.teams.roles.add_permissions(team.id, role.id, permission_ids=[1, 2, 3])

# Invitations and members
client.teams.invitations.create(team.id, email="pentester@example.com", role_id=role.id)
client.teams.members.list(team.id)
client.teams.roles.assign_to_member(team.id, role.id, user_id=5)

# Shared resources and usage
client.teams.agents.create(team.id, agent_id=10)
client.teams.usage.summary(team.id)

The platform-wide permission catalog used to build roles lives on client.permissions.list().

Chats

A chat session provides persistence and conversation context for AI interactions, including the phases of a pentest.

chat = client.chats.create(name="Security research")
client.chats.retrieve(chat.id)
client.chats.update(chat.id, name="Renamed session")
client.chats.list()
client.chats.mine()
client.chats.shared()

# Archive / share lifecycle
client.chats.archive(chat_id=chat.id)
client.chats.unarchive(chat_id=chat.id)
client.chats.share(chat_id=chat.id, team_id=4)
client.chats.unshare(chat_id=chat.id, team_id=4)
client.chats.unshare_all(chat_id=chat.id)

# Operations (message history) and operation logs
client.chats.operations.list(chat_id=chat.id)
client.chats.operations.assign(chat_id=chat.id, operations=[101, 102])
client.chats.operations.delete(chat_id=chat.id, operation_id=101)
client.chats.operation_logs.list()

client.chats.delete(chat.id)

The chat resource manages the conversation container; the messages themselves are produced over the streaming backend (see Streaming). The matching HTTP routes are in the Chats API.

Usage and billing

Monitor consumption and control spend.

# Current billing period, or filter by month / date range
client.usage.summary()
client.usage.summary(month="2026-06")

# Daily and hourly breakdowns, and the full operation history
client.usage.daily(period="7d")
client.usage.daily(date="2026-06-20")
client.usage.history(page=1, per_page=50)

# On-demand spending
client.usage.toggle_on_demand(enabled=True, limit_usd=50.0)

# Subscription, trial and invoices (personal)
client.billing.status()
client.billing.trial_status()
client.billing.invoices()

# Team billing (read-only views)
client.billing.team_status(team_id=4)
client.billing.team_trial_status(team_id=4)
client.billing.team_invoices(team_id=4)

client.tiers.list()

Auth and account

# The authenticated user and profile
client.auth.me()
client.auth.update_profile(country="ES", language="es")

# Account changes
client.auth.update_email(email="new@example.com")
client.auth.update_username(username="new-handle")
client.auth.update_password(current_password="...", new_password="...")

# Sessions
client.auth.sessions()
client.auth.active_sessions()
client.auth.revoke_session(session_id=88)

# API tokens — programmatic management
client.auth.api_tokens.available_permissions()
client.auth.api_tokens.list()
created = client.auth.api_tokens.create(
    name="CI/CD pipeline", permission_ids=[12, 13], tags=["pentest"], team_ids=[4],
)
print(created.token)  # plaintext rk_... value — shown only once
client.auth.api_tokens.update(token_id=created.id, name="CI/CD pipeline v2")
client.auth.api_tokens.revoke(token_id=created.id)

The full HTTP surface, including two-factor authentication, is documented in the Authentication & account API.

Tickets

Push findings to Jira through the client.tickets resource. A Jira integration must be configured for your account or team first.

ticket = client.tickets.create(
    summary="XSS in login form",
    description="Reflected XSS via the redirect_url parameter",
    issue_type="Bug",
)
client.tickets.list()
client.tickets.retrieve(ticket.id)

# Comments and attachments
client.tickets.add_comment(ticket.id, comment="Confirmed in staging")
client.tickets.update_comment(ticket.id, comment_id="10001", comment="Confirmed in prod too")
client.tickets.delete_comment(ticket.id, comment_id="10001")
client.tickets.add_attachment(ticket.id, file=("poc.png", open("poc.png", "rb"), "image/png"))

# Pull the latest state from Jira, then delete
client.tickets.sync(ticket.id)
client.tickets.delete(ticket.id)

The matching HTTP routes are in the Tickets API.

For real-time work — launching pentests, following agent activity and chatting with general agents — head to Streaming. For typed errors and paging through list responses, see Errors & pagination.