Skip to main content

Overview

The Risk Legion API is a RESTful API built with FastAPI, providing comprehensive access to all platform features including BRA management, control assurance, governance, and administration.

Base URLs

EnvironmentBase URL
Productionhttps://api.risklegion.com
Staginghttps://api-test.risklegion.com
Local Developmenthttp://localhost:8000
All API endpoints are prefixed with /api/v1.

Authentication

All API endpoints (except /health) require authentication using JWT Bearer tokens.
curl -X GET "https://api.risklegion.com/api/v1/bras" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json"
See Authentication for details on obtaining and using tokens.

Response Format

Success Responses

All successful responses follow this structure:
{
  "data": { ... },
  "message": "Operation successful"
}

Paginated Responses

List endpoints return paginated data:
{
  "data": [ ... ],
  "message": "Items retrieved successfully",
  "pagination": {
    "page": 1,
    "page_size": 25,
    "total": 150,
    "total_pages": 6,
    "has_next": true,
    "has_prev": false
  }
}

Error Responses

Error responses include:
{
  "error": "Descriptive error message",
  "code": "ERROR_CODE",
  "request_id": "uuid-for-tracking",
  "details": { ... }
}

HTTP Status Codes

CodeMeaningWhen Used
200OKSuccessful GET, PATCH, DELETE
201CreatedSuccessful POST
400Bad RequestValidation error, invalid input
401UnauthorizedMissing or invalid token
403ForbiddenInsufficient permissions
404Not FoundResource doesn’t exist
422Unprocessable EntityValidation error (Pydantic)
429Too Many RequestsRate limit exceeded
500Internal Server ErrorServer error

Pagination

Query Parameters

ParameterTypeDefaultMaxDescription
pageinteger1-Page number (1-indexed)
page_sizeinteger25100Items per page

Example

GET /api/v1/bras?page=2&page_size=10

Filtering

Most list endpoints support filtering:
# Filter BRAs by status
GET /api/v1/bras?status=in_progress

# Filter by legal entity
GET /api/v1/bras?legal_entity_id=uuid

# Multiple filters
GET /api/v1/bras?status=approved&legal_entity_id=uuid

Rate Limiting

The API implements rate limiting to ensure fair usage:
LimitValue
Requests per minute100
Requests per hour1,000
Rate limit headers are included in responses:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1705123456
When rate limited, you’ll receive:
{
  "error": "Rate limit exceeded",
  "code": "RATE_LIMIT_EXCEEDED",
  "retry_after": 60
}

API Versioning

The current API version is v1. The version is included in the URL path:
/api/v1/bras
/api/v1/controls
/api/v1/governance

API Reference

Core Endpoints

Quick Reference

ResourceEndpoints
BRAsGET, POST, PATCH /api/v1/bras
ScenariosGET, POST /api/v1/bras/{id}/scenarios
RatingsGET, POST /api/v1/bras/{id}/ratings
ControlsGET, POST, PATCH /api/v1/controls/*
ActionsGET, POST, PATCH /api/v1/mitigation-actions
GovernanceGET, POST /api/v1/governance/*
AdminGET, POST, PATCH /api/v1/admin/*

Interactive Documentation

When running locally, access the interactive API documentation:
ToolURL
Swagger UIhttp://localhost:8000/docs
ReDochttp://localhost:8000/redoc
OpenAPI JSONhttp://localhost:8000/openapi.json

SDKs and Tools

cURL

# Set token as environment variable
export TOKEN="your-jwt-token"

# Make requests
curl -X GET "https://api.risklegion.com/api/v1/bras" \
  -H "Authorization: Bearer $TOKEN"

JavaScript/TypeScript

import axios from 'axios';

const apiClient = axios.create({
  baseURL: 'https://api.risklegion.com/api/v1',
  headers: {
    'Content-Type': 'application/json'
  }
});

// Add auth interceptor
apiClient.interceptors.request.use((config) => {
  const token = getAuthToken();
  config.headers.Authorization = `Bearer ${token}`;
  return config;
});

// Get BRAs
const response = await apiClient.get('/bras');
const bras = response.data.data;

Python

import httpx

API_BASE = "https://api.risklegion.com/api/v1"
TOKEN = "your-jwt-token"

headers = {
    "Authorization": f"Bearer {TOKEN}",
    "Content-Type": "application/json"
}

async with httpx.AsyncClient() as client:
    response = await client.get(f"{API_BASE}/bras", headers=headers)
    bras = response.json()["data"]

Error Handling Best Practices

try {
  const response = await apiClient.get('/bras');
  return response.data.data;
} catch (error) {
  if (axios.isAxiosError(error)) {
    const status = error.response?.status;
    const errorData = error.response?.data;
    
    switch (status) {
      case 401:
        // Token expired - refresh or redirect to login
        await refreshToken();
        return retry();
      case 403:
        // Permission denied
        showError('You do not have permission for this action');
        break;
      case 404:
        showError('Resource not found');
        break;
      case 429:
        // Rate limited - wait and retry
        const retryAfter = error.response?.headers['retry-after'];
        await sleep(retryAfter * 1000);
        return retry();
      default:
        showError(errorData?.error || 'An error occurred');
    }
  }
}

Need Help?