API Reference
Complete reference for the XnoleX REST API. All endpoints return JSON and acceptapplication/json request bodies unless otherwise noted.
Base URL
All API requests should be directed to the following base URLs:
Development: http://localhost:8000
Production: https://api.xnolex.comAll endpoints are prefixed with /api/v1.
Authentication
The API supports two authentication methods:
Bearer Token: Include the JWT access token in the Authorization header.
curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
http://localhost:8000/api/v1/targetsAPI Key: Include your API key in the X-API-Key header. Available on Monthly and Yearly plans.
curl -H "X-API-Key: xnk_your_api_key_here" \
http://localhost:8000/api/v1/targetsRate Limiting
Rate limits are applied per user based on subscription tier. Limits are measured in requests per minute (RPM).
| Tier | RPM Limit |
|---|---|
| Demo (Free) | 10 |
| Monthly Pro | 60 |
| Yearly Pro | 120 |
| Admin | 200 |
When the rate limit is exceeded, the API returns a 429 Too Many Requests status. Rate limit headers are included in all responses to help you track your usage.
Authentication
POST /api/v1/auth/login
Authenticate with email and password. No prior authentication required.
// Request
POST /api/v1/auth/login
Content-Type: application/json
{
"email": "user@example.com",
"password": "your_password"
}
// Response 200
{
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"refresh_token": "eyJhbGciOiJSUzI1NiIs...",
"token_type": "bearer",
"user": {
"id": "usr_abc123",
"email": "user@example.com",
"full_name": "John Doe",
"role": "user",
"tier_slug": "demo"
}
}POST /api/v1/auth/refresh
Exchange a refresh token for a new token pair. The old refresh token is invalidated.
// Request
POST /api/v1/auth/refresh
Content-Type: application/json
{
"refresh_token": "eyJhbGciOiJSUzI1NiIs..."
}
// Response 200
{
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"refresh_token": "eyJhbGciOiJSUzI1NiIs..."
}POST /api/v1/auth/logout
Revoke the current refresh token session. Requires Bearer authentication.
// Request
POST /api/v1/auth/logout
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json
{
"refresh_token": "eyJhbGciOiJSUzI1NiIs..."
}
// Response 200
{
"message": "Logged out successfully"
}GET /api/v1/auth/me
Get the current authenticated user's profile. Requires Bearer authentication.
PUT /api/v1/auth/me
Update the current user's profile. Requires Bearer authentication. Accepts full_name query parameter.
PUT /api/v1/auth/me/password
Change the current user's password. Requires Bearer authentication.
// Request
PUT /api/v1/auth/me/password
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json
{
"current_password": "old_password",
"new_password": "new_secure_password"
}
// Response 200
{
"message": "Password updated successfully"
}Targets
GET /api/v1/targets
List all targets for the authenticated user. Requires Bearer authentication.
POST /api/v1/targets
Create a new target. Requires Bearer authentication.
// Request
POST /api/v1/targets
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json
{
"domain": "example.com",
"organization": "Example Corp"
}
// Response 201
{
"id": "tgt_abc123",
"domain": "example.com",
"organization": "Example Corp",
"created_at": "2026-01-15T10:30:00Z"
}DELETE /api/v1/targets/{target_id}
Delete a target and all associated scan data. Requires Bearer authentication. User must own the target.
POST /api/v1/targets/import
Bulk import multiple targets. Requires Bearer authentication.
// Request
POST /api/v1/targets/import
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json
{
"domains": ["example.com", "test.org", "sample.net"]
}
// Response 200
{
"imported": 3,
"failed": 0,
"targets": [
{ "id": "tgt_a1", "domain": "example.com" },
{ "id": "tgt_a2", "domain": "test.org" },
{ "id": "tgt_a3", "domain": "sample.net" }
]
}Scans
GET /api/v1/scans
List all scans. Optional query parameters: target_id and status. Requires Bearer authentication.
POST /api/v1/scans
Start a new scan. Requires Bearer authentication. The engine parameter defaults to full.
// Request
POST /api/v1/scans
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json
{
"target_id": "tgt_abc123",
"engine": "full"
}
// Response 201
{
"id": "scn_xyz789",
"target_id": "tgt_abc123",
"engine": "full",
"status": "queued",
"created_at": "2026-01-15T10:35:00Z"
}GET /api/v1/scans/{scan_id}
Get detailed results for a specific scan. Requires Bearer authentication.
// Request
GET /api/v1/scans/scn_xyz789
Authorization: Bearer ACCESS_TOKEN
// Response 200
{
"id": "scn_xyz789",
"target_id": "tgt_abc123",
"domain": "example.com",
"engine": "full",
"status": "completed",
"started_at": "2026-01-15T10:35:01Z",
"completed_at": "2026-01-15T10:42:30Z",
"findings": [
{
"id": "fnd_001",
"severity": "high",
"title": "SQL Injection in login form",
"path": "/login",
"tool": "nuclei",
"description": "The login form is vulnerable to SQL injection..."
}
],
"summary": {
"total_findings": 12,
"critical": 1,
"high": 3,
"medium": 5,
"low": 3,
"info": 0
}
}POST /api/v1/scans/{scan_id}/stop
Stop a running scan. Requires Bearer authentication. User must own the scan.
GET /api/v1/scans/{scan_id}/intel
Get correlated intelligence data for a scan. Returns findings enriched with context from multiple tools. Requires Bearer authentication.
GET /api/v1/scans/{scan_id}/report
Generate and retrieve a formatted report for a scan. Available on Monthly and Yearly plans. Requires Bearer authentication.
Dashboard
GET /api/v1/dashboard/summary
Get aggregate dashboard summary including total targets, scans, findings, and recent activity. Requires Bearer authentication.
GET /api/v1/dashboard/charts
Get chart data for the last 30 days including scan counts, finding severity distribution, and trends. Requires Bearer authentication.
Schedules
GET /api/v1/schedules
List all scheduled scans. Requires Bearer authentication.
POST /api/v1/schedules
Create a new scheduled scan. Requires Bearer authentication.
// Request
POST /api/v1/schedules
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json
{
"target_id": "tgt_abc123",
"engine": "full",
"cron_expression": "0 2 * * *"
}
// Response 201
{
"id": "sch_def456",
"target_id": "tgt_abc123",
"engine": "full",
"cron_expression": "0 2 * * *",
"enabled": true,
"next_run": "2026-01-16T02:00:00Z"
}PUT /api/v1/schedules/{schedule_id}
Update an existing scheduled scan. Requires Bearer authentication. User must own the schedule.
DELETE /api/v1/schedules/{schedule_id}
Delete a scheduled scan. Requires Bearer authentication. User must own the schedule.
POST /api/v1/schedules/{schedule_id}/run-now
Immediately trigger a scheduled scan without waiting for the next cron interval. Requires Bearer authentication.
Notifications
GET /api/v1/notifications
List all notifications for the authenticated user. Requires Bearer authentication.
PUT /api/v1/notifications/{notification_id}/read
Mark a single notification as read. Requires Bearer authentication.
POST /api/v1/notifications/read-all
Mark all unread notifications as read. Requires Bearer authentication.
GET /api/v1/notifications/unread-count
Get the count of unread notifications. Requires Bearer authentication.
API Keys
POST /api/v1/api-keys
Create a new API key. Requires Bearer authentication. The raw key is only returned once at creation time.
// Request
POST /api/v1/api-keys
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json
{
"name": "CI/CD Pipeline",
"permissions": ["read", "scan"],
"expires_in_days": 90
}
// Response 201
{
"id": "key_abc123",
"name": "CI/CD Pipeline",
"key": "xnk_a1b2c3d4e5f6...",
"permissions": ["read", "scan"],
"expires_at": "2026-04-15T10:30:00Z",
"created_at": "2026-01-15T10:30:00Z"
}GET /api/v1/api-keys
List all API keys for the authenticated user. Key values are masked. Requires Bearer authentication.
DELETE /api/v1/api-keys/{key_id}
Revoke and delete an API key. Requires Bearer authentication. User must own the key.
Subscriptions
GET /api/v1/subscriptions/tiers
List all available subscription tiers with their features and pricing. No authentication required.
GET /api/v1/subscriptions/current
Get the current user's active subscription details. Requires Bearer authentication.
POST /api/v1/subscriptions/checkout
Create a Stripe checkout session for a new subscription. Requires Bearer authentication.
// Request
POST /api/v1/subscriptions/checkout
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json
{
"tier_slug": "monthly"
}
// Response 200
{
"checkout_url": "https://checkout.stripe.com/pay/cs_...",
"session_id": "cs_abc123"
}POST /api/v1/subscriptions/upgrade
Upgrade to a different tier. Handled via Stripe with proration. Requires Bearer authentication.
POST /api/v1/subscriptions/cancel
Cancel the current subscription. Takes effect at the end of the billing period. Requires Bearer authentication.
GET /api/v1/subscriptions/usage
Get current usage statistics including scans used and targets used against tier limits. Requires Bearer authentication.
WebSocket
WS /api/v1/ws/scans/{scan_id}?token={jwt}
Connect to live scan progress via WebSocket. The JWT access token must be provided as a query parameter. Messages are sent as JSON with real-time progress updates.
// Connect to scan progress
const ws = new WebSocket(
'ws://localhost:8000/api/v1/ws/scans/scn_xyz789?token=eyJhbGciOi...'
);
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log('Progress:', data.progress);
console.log('Current tool:', data.current_tool);
console.log('Findings so far:', data.findings_count);
};
ws.onclose = () => {
console.log('Scan completed or connection closed');
};