API reference
All Pwnkemon endpoints live under https://pwnkemon.com/api/. Authenticate with an API token or a Clerk session JWT.
Authentication
Every endpoint except /health requires:
Authorization: Bearer <token>token may be a pt_ API token (machine-to-machine) or a Clerk session JWT (browser session). Invalid tokens return 401 with {"detail": "Invalid or expired token"}.
Targets
List verified targets
GET /api/targetsReturns an array of targets owned by the authenticated user.
Create a target
POST /api/targets
{
"target": "example.com",
"method": "dns_txt" // or "http_file"
}Returns the target record including a unique verification_token and step-by-step instructions for completing the challenge.
Verify a target
POST /api/targets/<id>/verifyPwnkemon performs a live DNS or HTTP lookup and confirms the challenge token is present. On success, the target is marked verified and can be scanned. On failure, returns 400 with the reason.
Delete a target
DELETE /api/targets/<id>Removes the target immediately. Scan history is retained.
Scans
List scans
GET /api/scansReturns the authenticated user's scans, newest first.
Get a single scan
GET /api/scans/<id>Full scan record including findings, agent_steps (the audit trail), and the executive summary.
Launch a scan
POST /api/scans
{
"target": "example.com",
"scan_type": "full", // full | network | web | vuln | ssl
"tier": "standard", // quick | standard | deep
"callback_url": "...", // optional
"max_credits": 20, // optional, capped at the tier ceiling
"options": {} // optional, reserved
}The scan is queued and runs asynchronously. The response includes the scan's id — poll GET /api/scans/<id> for status, or wait for the webhook if callback_url was set.
Cancel a scan
DELETE /api/scans/<id>Sets a cooperative cancellation flag. The agent checks this between tool calls and exits cleanly when it sees it. Already-running LLM requests complete first; the scan typically aborts within 30 seconds.
Reports
Four format endpoints, each returning the raw file with the appropriate Content-Type. See reports for plan availability.
GET /api/scans/<id>/report.md -> text/markdown
GET /api/scans/<id>/report.html -> text/html
GET /api/scans/<id>/report.pdf -> application/pdf
GET /api/scans/<id>/findings.csv -> text/csv403 if the format is not available on your plan, 409 if the scan hasn't completed yet, 410 if the report has expired (Free plan, >7 days old).
API tokens
POST /api/tokens to create, GET /api/tokens to list, DELETE /api/tokens/<id> to revoke. See the API tokens page for the full flow.
User
GET /api/auth/meReturns the authenticated user record: id, email, plan, is_admin.
Rate limits
Default rate limit is 60 requests per minute per user, with a separate 20-scan-creations-per-hour cap on POST /api/scans. Hitting the limit returns 429 Too Many Requests with a Retry-After header.
Errors
All errors return JSON in a consistent shape:
{
"detail": "Human-readable error message"
}Common status codes:
400— Bad input (invalid scan_type, malformed target, etc.)401— Missing or invalid auth token403— Authenticated but not authorised (target not verified, plan doesn't include feature)404— Resource not found, or belongs to a different user409— State conflict (e.g. requesting a report for a scan that hasn't completed)410— Resource expired (Free-plan report retention)429— Rate limit or quota hit500— Server error; if persistent, contact support