Python SDK
Drive autonomous pentests, stream agent activity and triage findings from Python with the rank-sdk package.
The rank-sdk package is the official Python library for the Rank API. It gives you
synchronous and asynchronous clients, typed resources for every part of the platform, and
first-class Server-Sent Events streaming so you can run a full penetration test — and watch
the agents work in real time — without writing any HTTP plumbing. Source code and issue
tracking live in the Rank-python repository on GitHub.
Install
The package is published on PyPI as rank-sdk and supports Python 3.8 and newer. Once
installed, you import it as rank. The full source is on GitHub.
pip install rank-sdk
import rank
client = rank.Rank(api_key="rk_live_xxxxxxxxxxxxxxxx")
If you prefer not to hard-code the key, set the RANK_API_KEY environment variable and call
rank.Rank() with no arguments. See Client setup for every constructor option.
Quick example
The snippet below creates an automatic web pentest, activates a Rules of Engagement, and
streams execution to the terminal. The run is fail-closed: without an active RoE the
orchestrator will not start (no_active_roe). Creating the pentest is not enough — every
asset must fall inside the allow-list, and activate=True is what authorizes the launch.
In automatic mode the agents run every phase end-to-end and process the findings inside the
same stream, so by the time the complete event arrives the vulnerabilities are already
stored.
import rank
from rank import AgentEvent
with rank.Rank() as client:
chat = client.chats.create(nombre="Web scan - example.com")
pentest = client.pentests.create(
name="Web scan",
type="web",
mode="automatic",
assets=[
{"asset_type": "url", "asset_value": "https://example.com", "is_primary": True},
],
)
client.pentests.roe.create(
pentest.id,
allowed_domains=["example.com"],
authorization_ref="ENG-2026-0042",
escalation_contacts=[{"type": "email", "value": "secops@example.com"}],
activate=True,
)
client.pentests.agents.default(pentest.id)
with client.ai.chat.stream(
user_prompt="Start the pentest on the configured targets",
pentest_id=pentest.id,
mode="automatic",
chat_id=chat.id,
) as stream:
for event in stream:
if event.type == "content":
print(event.content, end="", flush=True)
elif event.is_agent_event and event.agent_event.event_type == AgentEvent.TOOL_CALL:
print(f"\n[tool] {event.agent_event.data['tool_name']}")
elif event.type == "complete":
print(f"\nDone — {event.metadata.get('vulnerabilities_stored', 0)} findings stored")
finished = client.pentests.finish(pentest.id)
print(finished.message) curl https://api.aleex-rank.ai/api/v2/pentests \
-H "X-API-Key: rk_live_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"name": "Web scan",
"type": "web",
"mode": "automatic",
"assets": [{"asset_type": "url", "asset_value": "https://example.com", "is_primary": true}]
}'
curl https://api.aleex-rank.ai/api/v2/pentests/42/roe \
-H "X-API-Key: rk_live_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"allowed_domains": ["example.com"],
"authorization_ref": "ENG-2026-0042",
"escalation_contacts": [{"type": "email", "value": "secops@example.com"}],
"activate": true
}' Create outbound integrations before you create and launch pentests if you want Jira, GitHub or Slack tickets to open from live findings. Connecting them afterwards does not backfill events that already fired.
Client namespaces
A rank.Rank (or rank.AsyncRank) client exposes these resource namespaces:
ai, auth, pentests, teams, agents, chats, tiers, invitations, permissions,
tickets, usage, billing, catalogs, webhooks (tenant), integrations,
report_profiles, remediation_policy and evidence (retention).
Sub-resources nest off pentests — client.pentests.roe, approvals, evidence (artifacts),
reports, report_settings, retests, and the per-pentest legacy client.pentests.webhooks.
See Resources for the full tour.
The dual-backend model
A single Rank client talks to two backends behind one API key. The SDK routes each call to the right one for you, but it helps to know which is which when you override URLs or read the default configuration.
| Backend | Constructor option | Environment variable | Default | Handles |
|---|---|---|---|---|
| PHP REST API | base_url | RANK_BASE_URL | https://api.aleex-rank.ai | CRUD for pentests, vulnerabilities, agents, teams, chats, usage, auth |
| Go agent backend | agent_base_url | RANK_AGENT_BASE_URL | https://aleex.aleex-rank.ai | AI chat streaming, pentest execution and control, report generation |
Both backends authenticate with the same API key, sent in the X-API-Key header. The PHP
backend is reached under the /api/v2 prefix automatically.
Use the client as a context manager
rank.Rank and rank.AsyncRank are context managers. Entering the with block returns the
client; leaving it closes the underlying HTTP connections to both backends. This is the
recommended pattern for short-lived scripts and request handlers.
import rank
with rank.Rank() as client:
me = client.auth.me()
print(me.username, me.email) import asyncio
import rank
async def main():
async with rank.AsyncRank() as client:
me = await client.auth.me()
print(me.username, me.email)
asyncio.run(main()) If you keep a long-lived client instead, call client.close() (or await client.close() on
the async client) when you are done.
Where to go next
Constructor options, environment variables, timeouts, retries, custom headers and webhook signatures.
ResourcesPentests, RoE, vulnerabilities, evidence, reports, retest, tenant webhooks and integrations.
StreamingConsume Server-Sent Events, follow agent activity and attach files.
Errors & paginationThe exception hierarchy, control-plane conflicts, automatic retries and paging.
CookbookEnd-to-end recipes that combine these building blocks.
Engagement, RoE & kill switchFail-closed scope, approvals, time windows and the kill switch.