Authentication Flow

RiskSage uses a two-step authentication flow: credential exchange followed by an MFA challenge. Every subsequent request uses the resulting Bearer JWT.

Step 1 — Login with credentials

Submit your email and password to the login endpoint. On success, the API returns an MFA challenge token.

// Step 1: Exchange credentials for MFA challenge
POST /auth/login
Content-Type: application/json

{
  "email":    "analyst@acme-bank.in",
  "password": "********"
}

// Response 200
{
  "mfaChallengeToken": "eyJhbGciOi...",
  "mfaMethod":         "TOTP",
  "expiresIn":         300
}

Step 2 — Complete MFA challenge

Submit the TOTP code from your authenticator app along with the challenge token. The response contains your Bearer JWT and a refresh token.

// Step 2: Complete MFA challenge
POST /auth/mfa/challenge
Content-Type: application/json

{
  "mfaChallengeToken": "eyJhbGciOi...",
  "totpCode":          "482901"
}

// Response 200
{
  "accessToken":  "eyJhbGciOiJSUzI1NiIs...",
  "refreshToken": "dGhpcyBpcyBhIHJlZnJl...",
  "expiresIn":    3600,
  "tokenType":    "Bearer"
}

Using the token

Include the access token as a Bearer token in the Authorization header of every subsequent request:

GET /incidents
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...
X-Tenant-Id: acme-bank
Token Lifecycle Access tokens expire after 60 minutes. Use the POST /auth/refresh endpoint with your refresh token to obtain a new access token without re-authenticating. Refresh tokens expire after 7 days of inactivity.

Tenant-Scoped Endpoints

RiskSage is a multi-tenant platform. Every API request must include the X-Tenant-Id header. The JWT encodes the user's tenant membership, and requests to a tenant the user does not belong to will return 403 Forbidden.

// All data endpoints require tenant scoping
GET /incidents
Authorization: Bearer <token>
X-Tenant-Id: acme-bank

// Omitting X-Tenant-Id returns:
// 400 { "error": "MISSING_TENANT", "message": "X-Tenant-Id header is required" }

Key Route Groups

The RiskSage API is organised into five primary route groups. All routes are prefixed with /api/v1 in production.

Route GroupBase PathDescription
Incidents/incidentsCERT-In incident lifecycle, multi-regulator deadline tracking, AI-drafted 9-field reports
VAPT/vaptVulnerability assessments, report ingestion (Nessus, Burp, OpenVAS, Qualys), finding management
CRQ/crqCyber Risk Quantification — FAIR v3.0, FAIR-MAM, NIST 800-30/ALE, Probabilistic VaR analyses
Threat Models/threat-modelsSTRIDE + PASTA threat modelling, DFD components, regulatory mapping (RBI TRA, SEBI CSCRF, IRDAI)
Dashboard/dashboardAggregated risk posture, compliance status, widget data for executive and operational views

Rate Limits

RiskSage enforces per-tenant rate limits to ensure fair usage across the platform. Limits are applied using a sliding window algorithm.

TierLimitWindowApplies To
Standard120 requests1 minuteAll authenticated endpoints
Auth10 requests1 minute/auth/* endpoints
AI-Assisted20 requests1 minuteAI report drafting, /crq/use-cases/:id/suggest-inputs
Bulk Upload5 requests1 minuteVAPT report parsing, bulk import

Rate limit status is returned in response headers:

X-RateLimit-Limit: 120
X-RateLimit-Remaining: 87
X-RateLimit-Reset: 1712467200
429 Too Many Requests When rate-limited, the API returns a 429 status with a Retry-After header (in seconds). Implement exponential backoff in your integration. Do not retry immediately.

Error Handling Patterns

All RiskSage API errors follow a consistent JSON envelope. Every error response includes a machine-readable error code and a human-readable message.

// Standard error envelope
{
  "error":   "VALIDATION_ERROR",
  "message": "Field 'severity' must be one of: CRITICAL, HIGH, MEDIUM, LOW, INFO",
  "field":   "severity",
  "status":  422
}
StatusError CodeMeaning
400MISSING_TENANTX-Tenant-Id header not provided
401TOKEN_EXPIREDAccess token has expired — refresh or re-authenticate
403FORBIDDENUser does not have access to the requested tenant or resource
404NOT_FOUNDResource does not exist within the tenant scope
422VALIDATION_ERRORRequest body failed schema validation
429RATE_LIMITEDToo many requests — check Retry-After header
500INTERNAL_ERRORUnexpected server error — include the X-Request-Id when contacting support
Best Practice Always log the X-Request-Id response header. When contacting CreativeCyber support, include this ID for fast issue resolution. Every request generates a unique trace ID that maps to our internal observability stack.

Next Steps

With authentication working and an understanding of the route structure, explore the detailed guides for each module: