Technical Specifications
Overview
This document defines the technical specifications for CalcBridge, including API contracts, data models, performance benchmarks, and integration standards.
API Contract Specifications
API Design Principles
| Principle | Description |
| REST Architecture | All APIs follow REST conventions with proper HTTP methods and status codes |
| JSON Format | Request and response bodies use JSON with consistent formatting |
| Versioning | API versioning via URL path (/api/v1/, /api/v2/) |
| Pagination | Collection endpoints support cursor-based pagination |
| Filtering | Query parameters for filtering, sorting, and field selection |
| HATEOAS | Responses include hypermedia links for navigation |
Base URL Structure
Production: https://api.calcbridge.io/api/v1/
Staging: https://api.staging.calcbridge.io/api/v1/
Development: http://localhost:8000/api/v1/
Authentication
JWT Token Authentication
| Header | Value |
| Authorization | Bearer <jwt_token> |
| Content-Type | application/json |
| X-Tenant-ID | <tenant_uuid> |
Token Structure
{
"sub": "user_uuid",
"tenant_id": "tenant_uuid",
"roles": ["analyst", "viewer"],
"permissions": ["read:workbooks", "write:scenarios"],
"exp": 1706227200,
"iat": 1706140800
}
HTTP Status Codes
| Code | Meaning | Usage |
| 200 | OK | Successful GET, PUT, PATCH |
| 201 | Created | Successful POST creating resource |
| 204 | No Content | Successful DELETE |
| 400 | Bad Request | Invalid request body or parameters |
| 401 | Unauthorized | Missing or invalid authentication |
| 403 | Forbidden | Insufficient permissions |
| 404 | Not Found | Resource does not exist |
| 409 | Conflict | Resource state conflict (duplicate, etc.) |
| 422 | Unprocessable Entity | Validation errors |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Unexpected server error |
| 503 | Service Unavailable | Maintenance or overload |
Core API Endpoints
Workbooks API
| Method | Endpoint | Description |
| GET | /workbooks | List all workbooks |
| POST | /workbooks | Upload new workbook |
| GET | /workbooks/{id} | Get workbook details |
| PUT | /workbooks/{id} | Update workbook metadata |
| DELETE | /workbooks/{id} | Delete workbook |
| GET | /workbooks/{id}/sheets | List workbook sheets |
| GET | /workbooks/{id}/holdings | Get holdings data |
| GET | /workbooks/{id}/metrics | Get aggregated metrics |
Workbook Upload Request
POST /api/v1/workbooks
Content-Type: multipart/form-data
{
"file": "<binary_data>",
"name": "CLO_Portfolio_2026_01.xlsx",
"mapping_profile_id": "uuid",
"tags": ["monthly", "CLO-1"],
"metadata": {
"report_date": "2026-01-25",
"source": "Bloomberg"
}
}
Workbook Response
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "CLO_Portfolio_2026_01.xlsx",
"status": "processed",
"created_at": "2026-01-25T10:30:00Z",
"updated_at": "2026-01-25T10:30:45Z",
"sheets": [
{
"id": "sheet_uuid",
"name": "Holdings",
"row_count": 1500,
"column_count": 45
}
],
"metrics": {
"total_par": 500000000,
"total_mv": 485000000,
"holding_count": 150
},
"links": {
"self": "/api/v1/workbooks/550e8400-e29b-41d4-a716-446655440000",
"holdings": "/api/v1/workbooks/550e8400-e29b-41d4-a716-446655440000/holdings",
"compliance": "/api/v1/workbooks/550e8400-e29b-41d4-a716-446655440000/compliance"
}
}
Compliance API
| Method | Endpoint | Description |
| GET | /workbooks/{id}/compliance | Get all compliance test results |
| GET | /workbooks/{id}/compliance/{test_id} | Get specific test details |
| POST | /workbooks/{id}/compliance/run | Execute compliance tests |
| GET | /compliance/tests | List available test definitions |
| GET | /compliance/history | Get compliance test history |
Compliance Test Results Response
{
"workbook_id": "550e8400-e29b-41d4-a716-446655440000",
"executed_at": "2026-01-25T10:31:00Z",
"summary": {
"total_tests": 52,
"passed": 50,
"failed": 1,
"warning": 1
},
"tests": [
{
"id": "oc_senior",
"name": "Senior OC Test",
"category": "overcollateralization",
"status": "passed",
"current_value": 125.5,
"trigger_level": 115.0,
"target_level": 120.0,
"cushion": 10.5,
"cushion_pct": 8.75,
"trend": "stable"
},
{
"id": "warf_test",
"name": "WARF Test",
"category": "credit_quality",
"status": "warning",
"current_value": 2850,
"trigger_level": 3000,
"target_level": 2800,
"cushion": 150,
"cushion_pct": 5.0,
"trend": "deteriorating"
}
]
}
Scenarios API
| Method | Endpoint | Description |
| GET | /workbooks/{id}/scenarios | List scenarios for workbook |
| POST | /workbooks/{id}/scenarios | Create new scenario |
| GET | /scenarios/{id} | Get scenario details |
| PUT | /scenarios/{id} | Update scenario |
| DELETE | /scenarios/{id} | Delete scenario |
| POST | /scenarios/{id}/calculate | Execute scenario calculations |
| GET | /scenarios/{id}/compare | Compare scenario to base |
Create Scenario Request
POST /api/v1/workbooks/{workbook_id}/scenarios
{
"name": "Add ABC Corp Position",
"description": "Evaluate adding $5M ABC Corp senior secured",
"changes": [
{
"type": "add_position",
"data": {
"issuer": "ABC Corporation",
"cusip": "000361105",
"par_amount": 5000000,
"price": 98.5,
"spread": 425,
"rating_moodys": "B2",
"rating_sp": "B",
"maturity_date": "2029-06-15",
"industry": "Healthcare"
}
},
{
"type": "remove_position",
"data": {
"cusip": "123456789",
"par_amount": 3000000
}
}
]
}
Scenario Comparison Response
{
"scenario_id": "scenario_uuid",
"workbook_id": "workbook_uuid",
"calculated_at": "2026-01-25T10:35:00Z",
"comparison": {
"metrics": [
{
"name": "Total Par",
"base_value": 500000000,
"scenario_value": 502000000,
"delta": 2000000,
"delta_pct": 0.4
},
{
"name": "WAL",
"base_value": 4.25,
"scenario_value": 4.31,
"delta": 0.06,
"delta_pct": 1.41
},
{
"name": "WARF",
"base_value": 2850,
"scenario_value": 2865,
"delta": 15,
"delta_pct": 0.53
}
],
"compliance": {
"base": {
"passed": 50,
"failed": 1,
"warning": 1
},
"scenario": {
"passed": 51,
"failed": 0,
"warning": 1
},
"changes": [
{
"test_id": "ccc_bucket",
"base_status": "failed",
"scenario_status": "passed",
"reason": "Reduced CCC exposure from 8.2% to 7.4%"
}
]
}
}
}
Mappings API
| Method | Endpoint | Description |
| GET | /mappings/profiles | List mapping profiles |
| POST | /mappings/profiles | Create mapping profile |
| GET | /mappings/profiles/{id} | Get profile details |
| PUT | /mappings/profiles/{id} | Update profile |
| DELETE | /mappings/profiles/{id} | Delete profile |
| POST | /mappings/auto-detect | Auto-detect column mappings |
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": [
{
"field": "changes[0].data.par_amount",
"message": "Par amount must be positive",
"code": "POSITIVE_NUMBER_REQUIRED"
}
],
"request_id": "req_abc123",
"timestamp": "2026-01-25T10:30:00Z",
"documentation_url": "https://docs.calcbridge.io/errors/VALIDATION_ERROR"
}
}
Request Parameters
| Parameter | Type | Default | Description |
cursor | string | null | Pagination cursor from previous response |
limit | integer | 50 | Items per page (max 200) |
sort | string | created_at | Sort field |
order | string | desc | Sort order (asc/desc) |
{
"data": [...],
"pagination": {
"cursor": "eyJpZCI6MTAwfQ==",
"has_more": true,
"total_count": 1500
}
}
Rate Limiting
| Tier | Requests/Second | Requests/Hour | Burst |
| Standard | 10 | 5,000 | 50 |
| Professional | 50 | 25,000 | 200 |
| Enterprise | 200 | 100,000 | 500 |
X-RateLimit-Limit: 5000
X-RateLimit-Remaining: 4985
X-RateLimit-Reset: 1706227200
Data Model Specifications
Entity Relationship Diagram
Tenant (1) ──────────────── (N) User
│
└─────────────────────── (N) Workbook
│
┌──────────────┼──────────────┐
│ │ │
(N) (N) (N)
Sheet Scenario ComplianceRun
│ │ │
(N) (N) (N)
Holding ScenarioChange ComplianceResult
Core Entities
Tenant
| Field | Type | Constraints | Description |
| id | UUID | PK | Unique identifier |
| name | VARCHAR(255) | NOT NULL | Tenant display name |
| slug | VARCHAR(100) | UNIQUE, NOT NULL | URL-safe identifier |
| status | ENUM | NOT NULL | active, suspended, archived |
| settings | JSONB | | Tenant configuration |
| created_at | TIMESTAMP | NOT NULL | Creation timestamp |
| updated_at | TIMESTAMP | NOT NULL | Last update timestamp |
User
| Field | Type | Constraints | Description |
| id | UUID | PK | Unique identifier |
| tenant_id | UUID | FK, NOT NULL | Parent tenant |
| email | VARCHAR(255) | UNIQUE, NOT NULL | User email |
| name | VARCHAR(255) | NOT NULL | Display name |
| role | ENUM | NOT NULL | admin, analyst, viewer |
| status | ENUM | NOT NULL | active, inactive, locked |
| last_login_at | TIMESTAMP | | Last login timestamp |
| created_at | TIMESTAMP | NOT NULL | Creation timestamp |
Workbook
| Field | Type | Constraints | Description |
| id | UUID | PK | Unique identifier |
| tenant_id | UUID | FK, NOT NULL | Parent tenant |
| name | VARCHAR(255) | NOT NULL | Workbook name |
| status | ENUM | NOT NULL | pending, processing, processed, failed |
| file_path | VARCHAR(500) | NOT NULL | Storage path |
| file_size | BIGINT | NOT NULL | File size in bytes |
| checksum | VARCHAR(64) | NOT NULL | SHA-256 checksum |
| metadata | JSONB | | User-provided metadata |
| processing_stats | JSONB | | Processing metrics |
| created_by | UUID | FK, NOT NULL | Creator user |
| created_at | TIMESTAMP | NOT NULL | Creation timestamp |
| updated_at | TIMESTAMP | NOT NULL | Last update timestamp |
Sheet
| Field | Type | Constraints | Description |
| id | UUID | PK | Unique identifier |
| workbook_id | UUID | FK, NOT NULL | Parent workbook |
| name | VARCHAR(255) | NOT NULL | Sheet name |
| index | INTEGER | NOT NULL | Sheet index |
| row_count | INTEGER | NOT NULL | Total rows |
| column_count | INTEGER | NOT NULL | Total columns |
| data | JSONB | NOT NULL | Cell data |
| formulas | JSONB | | Formula definitions |
| created_at | TIMESTAMP | NOT NULL | Creation timestamp |
Holding
| Field | Type | Constraints | Description |
| id | UUID | PK | Unique identifier |
| workbook_id | UUID | FK, NOT NULL | Parent workbook |
| sheet_id | UUID | FK, NOT NULL | Source sheet |
| row_index | INTEGER | NOT NULL | Source row |
| cusip | VARCHAR(9) | | CUSIP identifier |
| isin | VARCHAR(12) | | ISIN identifier |
| issuer_name | VARCHAR(255) | | Issuer name |
| par_amount | DECIMAL(18,2) | | Par/Face value |
| market_value | DECIMAL(18,2) | | Market value |
| price | DECIMAL(10,6) | | Current price |
| spread | DECIMAL(10,4) | | Spread (bps) |
| rating_moodys | VARCHAR(10) | | Moody's rating |
| rating_sp | VARCHAR(10) | | S&P rating |
| rating_fitch | VARCHAR(10) | | Fitch rating |
| maturity_date | DATE | | Maturity date |
| industry | VARCHAR(100) | | Industry classification |
| country | VARCHAR(100) | | Country |
| is_defaulted | BOOLEAN | DEFAULT FALSE | Default flag |
| raw_data | JSONB | NOT NULL | All original fields |
| created_at | TIMESTAMP | NOT NULL | Creation timestamp |
Scenario
| Field | Type | Constraints | Description |
| id | UUID | PK | Unique identifier |
| workbook_id | UUID | FK, NOT NULL | Parent workbook |
| name | VARCHAR(255) | NOT NULL | Scenario name |
| description | TEXT | | Scenario description |
| status | ENUM | NOT NULL | draft, calculated, archived |
| created_by | UUID | FK, NOT NULL | Creator user |
| calculated_at | TIMESTAMP | | Last calculation time |
| results | JSONB | | Calculation results |
| created_at | TIMESTAMP | NOT NULL | Creation timestamp |
| updated_at | TIMESTAMP | NOT NULL | Last update timestamp |
ScenarioChange
| Field | Type | Constraints | Description |
| id | UUID | PK | Unique identifier |
| scenario_id | UUID | FK, NOT NULL | Parent scenario |
| change_type | ENUM | NOT NULL | add_position, remove_position, modify_position, price_change, rating_change |
| target_cusip | VARCHAR(9) | | Target CUSIP (for modify/remove) |
| change_data | JSONB | NOT NULL | Change details |
| order_index | INTEGER | NOT NULL | Execution order |
| created_at | TIMESTAMP | NOT NULL | Creation timestamp |
ComplianceTest
| Field | Type | Constraints | Description |
| id | VARCHAR(50) | PK | Test identifier |
| name | VARCHAR(255) | NOT NULL | Display name |
| category | ENUM | NOT NULL | oc, ic, concentration, quality, other |
| description | TEXT | | Test description |
| formula | TEXT | NOT NULL | Calculation formula |
| trigger_type | ENUM | NOT NULL | min, max, range |
| is_active | BOOLEAN | DEFAULT TRUE | Active flag |
| created_at | TIMESTAMP | NOT NULL | Creation timestamp |
ComplianceRun
| Field | Type | Constraints | Description |
| id | UUID | PK | Unique identifier |
| workbook_id | UUID | FK, NOT NULL | Target workbook |
| scenario_id | UUID | FK | Target scenario (null for base) |
| run_type | ENUM | NOT NULL | manual, automatic, scheduled |
| status | ENUM | NOT NULL | pending, running, completed, failed |
| started_at | TIMESTAMP | | Execution start |
| completed_at | TIMESTAMP | | Execution end |
| triggered_by | UUID | FK | User who triggered |
| created_at | TIMESTAMP | NOT NULL | Creation timestamp |
ComplianceResult
| Field | Type | Constraints | Description |
| id | UUID | PK | Unique identifier |
| run_id | UUID | FK, NOT NULL | Parent run |
| test_id | VARCHAR(50) | FK, NOT NULL | Test definition |
| status | ENUM | NOT NULL | passed, failed, warning, error |
| current_value | DECIMAL(18,6) | | Calculated value |
| trigger_level | DECIMAL(18,6) | | Trigger threshold |
| target_level | DECIMAL(18,6) | | Target threshold |
| cushion | DECIMAL(18,6) | | Distance from trigger |
| details | JSONB | | Additional details |
| created_at | TIMESTAMP | NOT NULL | Creation timestamp |
JSONB Schemas
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"report_date": { "type": "string", "format": "date" },
"source": { "type": "string" },
"deal_name": { "type": "string" },
"reporting_period": { "type": "string" },
"tags": { "type": "array", "items": { "type": "string" } }
}
}
Holding Raw Data Schema
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"additionalProperties": true,
"description": "Preserves all original fields from source"
}
Response Time Targets
| Operation | P50 Target | P95 Target | P99 Target | Current |
| List Workbooks | 50ms | 100ms | 200ms | 45ms |
| Get Workbook | 30ms | 80ms | 150ms | 28ms |
| Upload Workbook (10MB) | 3s | 5s | 8s | 2.8s |
| List Holdings | 100ms | 200ms | 400ms | 95ms |
| Run Compliance Tests | 1s | 2s | 3s | 1.2s |
| Create Scenario | 50ms | 100ms | 200ms | 48ms |
| Calculate Scenario | 1.5s | 3s | 5s | 2.1s |
| Compare Scenarios | 200ms | 400ms | 800ms | 180ms |
Throughput Targets
| Metric | Target | Current |
| API Requests/Second | 1,000 | 1,200 |
| Concurrent Users | 500 | 600 |
| Workbook Uploads/Minute | 10 | 12 |
| Compliance Runs/Minute | 100 | 120 |
Resource Utilization
| Resource | Target | Alert Threshold |
| CPU Utilization | < 70% avg | > 80% |
| Memory Utilization | < 80% | > 90% |
| Database Connections | < 80% pool | > 90% |
| Disk I/O | < 70% capacity | > 85% |
Integration Specifications
Geneva Integration
| Aspect | Specification |
| Protocol | SFTP / HTTPS |
| Format | XML (Geneva Portfolio Export) |
| Frequency | Daily / On-demand |
| Authentication | Certificate-based |
Geneva XML Schema (Simplified)
<Portfolio>
<Header>
<PortfolioName>CLO-2024-1</PortfolioName>
<ReportDate>2026-01-25</ReportDate>
</Header>
<Holdings>
<Holding>
<CUSIP>000361105</CUSIP>
<Issuer>ABC Corporation</Issuer>
<ParAmount>5000000</ParAmount>
<MarketValue>4925000</MarketValue>
</Holding>
</Holdings>
</Portfolio>
Webhook Specifications
Event Types
| Event | Description | Payload |
| workbook.uploaded | Workbook upload completed | workbook object |
| workbook.processed | Processing completed | workbook + metrics |
| compliance.completed | Compliance run finished | run + results summary |
| compliance.failed | Test failure detected | test details |
| scenario.calculated | Scenario calculation done | scenario + comparison |
{
"event": "compliance.failed",
"timestamp": "2026-01-25T10:30:00Z",
"data": {
"workbook_id": "uuid",
"test_id": "oc_senior",
"current_value": 114.5,
"trigger_level": 115.0,
"status": "failed"
},
"metadata": {
"tenant_id": "uuid",
"webhook_id": "uuid",
"delivery_attempt": 1
}
}
Error Handling Standards
Error Codes
| Code | HTTP Status | Description |
| AUTH_INVALID_TOKEN | 401 | Invalid or expired JWT |
| AUTH_INSUFFICIENT_PERMISSIONS | 403 | User lacks required permission |
| RESOURCE_NOT_FOUND | 404 | Requested resource does not exist |
| VALIDATION_ERROR | 422 | Request validation failed |
| RATE_LIMIT_EXCEEDED | 429 | Too many requests |
| PROCESSING_ERROR | 500 | Internal processing failure |
| SERVICE_UNAVAILABLE | 503 | Service temporarily unavailable |
| WORKBOOK_INVALID_FORMAT | 422 | Invalid Excel file format |
| WORKBOOK_TOO_LARGE | 413 | File exceeds size limit |
| MAPPING_INCOMPLETE | 422 | Required columns not mapped |
| CALCULATION_ERROR | 500 | Formula evaluation failed |
Retry Policy
| Error Type | Retry | Backoff | Max Attempts |
| 5xx Errors | Yes | Exponential | 3 |
| 429 Rate Limit | Yes | Respect Retry-After | 3 |
| 4xx Client Errors | No | N/A | 1 |
| Network Errors | Yes | Exponential | 3 |
Idempotency
| Endpoint | Idempotent | Key |
| GET | Yes | N/A |
| POST /workbooks | No | Use Idempotency-Key header |
| POST /scenarios | No | Use Idempotency-Key header |
| PUT | Yes | Resource ID |
| DELETE | Yes | Resource ID |
Idempotency-Key: unique-client-generated-uuid
API Versioning Strategy
Version Lifecycle
| Version | Status | Support End Date |
| v1 | Stable | 2027-01-01 |
| v2 | Beta | N/A |
Breaking Change Policy
- Breaking changes only in major versions
- 12-month deprecation notice
- Backward compatible changes in minor versions
- Security fixes may break compatibility with notice
Deprecation: true
Sunset: Sat, 01 Jan 2027 00:00:00 GMT
Link: </api/v2/workbooks>; rel="successor-version"
Last Updated: 2026-01-25 | Version 1.0.0