Skip to content

Scenarios API

The Scenarios API enables what-if trade simulation, allowing you to model the compliance impact of proposed trades before execution.


Overview

What-if scenarios allow portfolio managers to:

  • Simulate trades: Model buy/sell transactions against current portfolio
  • Analyze impact: See how trades affect compliance test results
  • Compare results: View before/after compliance status
  • Make decisions: Get data-driven insights for trade execution

Endpoints

List Scenarios

Get all scenarios for the current tenant.

GET /api/v1/scenarios

Query Parameters

Parameter Type Default Description
page integer 1 Page number
page_size integer 20 Items per page (max 100)
status_filter string - Filter by status (draft, calculating, completed, failed)

Example Request

curl -X GET "https://api.calcbridge.io/api/v1/scenarios?page=1&page_size=20" \
  -H "Authorization: Bearer $TOKEN"
import requests

response = requests.get(
    "https://api.calcbridge.io/api/v1/scenarios",
    headers={"Authorization": f"Bearer {token}"},
    params={"page": 1, "page_size": 20}
)
scenarios = response.json()
for scenario in scenarios["items"]:
    print(f"{scenario['name']}: {scenario['status']}")
const response = await fetch(
  'https://api.calcbridge.io/api/v1/scenarios?page=1&page_size=20',
  { headers: { 'Authorization': `Bearer ${token}` } }
);
const scenarios = await response.json();
scenarios.items.forEach(s => console.log(`${s.name}: ${s.status}`));

Response

{
  "items": [
    {
      "id": "990e8400-e29b-41d4-a716-446655440010",
      "name": "Q1 2026 Portfolio Optimization",
      "description": "Test impact of selling low-rated assets",
      "status": "completed",
      "base_workbook_id": "550e8400-e29b-41d4-a716-446655440000",
      "trade_count": 5,
      "created_by": "user@example.com",
      "created_at": "2026-01-25T09:00:00Z",
      "updated_at": "2026-01-25T10:30:00Z"
    }
  ],
  "total": 12,
  "page": 1,
  "page_size": 20,
  "pages": 1
}

Create Scenario

Create a new what-if scenario with optional initial trades.

POST /api/v1/scenarios

Request Body

Field Type Required Description
name string Yes Scenario name (1-200 chars)
description string No Scenario description (max 2000 chars)
base_workbook_id string (UUID) No Base workbook for calculations
trades array[Trade] No Initial trades to add

Trade Object

Field Type Required Description
trade_type string Yes "buy" or "sell"
cusip string No CUSIP identifier
borrower_name string No Borrower/obligor name
par_value number Yes Par value of the trade
price number No Trade price (percentage of par)
spread number No Interest rate spread
rating_moodys string No Moody's rating
rating_sp string No S&P rating
rating_fitch string No Fitch rating
industry string No Industry classification
maturity_date string (date) No Loan maturity date
loan_data object No Additional loan attributes

Example Request

curl -X POST https://api.calcbridge.io/api/v1/scenarios \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Q1 2026 Portfolio Optimization",
    "description": "Test impact of selling low-rated assets and buying high-quality loans",
    "base_workbook_id": "550e8400-e29b-41d4-a716-446655440000",
    "trades": [
      {
        "trade_type": "sell",
        "cusip": "OLD123ABC",
        "borrower_name": "Weak Corp",
        "par_value": 500000.00,
        "rating_moodys": "Caa2"
      },
      {
        "trade_type": "buy",
        "cusip": "NEW456DEF",
        "borrower_name": "Strong Corp",
        "par_value": 500000.00,
        "rating_moodys": "Ba2",
        "spread": 2.5
      }
    ]
  }'
import requests

response = requests.post(
    "https://api.calcbridge.io/api/v1/scenarios",
    headers={"Authorization": f"Bearer {token}"},
    json={
        "name": "Q1 2026 Portfolio Optimization",
        "description": "Test impact of selling low-rated assets",
        "base_workbook_id": "550e8400-e29b-41d4-a716-446655440000",
        "trades": [
            {
                "trade_type": "sell",
                "cusip": "OLD123ABC",
                "borrower_name": "Weak Corp",
                "par_value": 500000.00,
                "rating_moodys": "Caa2"
            },
            {
                "trade_type": "buy",
                "cusip": "NEW456DEF",
                "borrower_name": "Strong Corp",
                "par_value": 500000.00,
                "rating_moodys": "Ba2",
                "spread": 2.5
            }
        ]
    }
)
scenario = response.json()
print(f"Created scenario: {scenario['id']}")
const response = await fetch('https://api.calcbridge.io/api/v1/scenarios', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${token}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    name: 'Q1 2026 Portfolio Optimization',
    description: 'Test impact of selling low-rated assets',
    base_workbook_id: '550e8400-e29b-41d4-a716-446655440000',
    trades: [
      {
        trade_type: 'sell',
        cusip: 'OLD123ABC',
        borrower_name: 'Weak Corp',
        par_value: 500000.00,
        rating_moodys: 'Caa2'
      },
      {
        trade_type: 'buy',
        cusip: 'NEW456DEF',
        borrower_name: 'Strong Corp',
        par_value: 500000.00,
        rating_moodys: 'Ba2',
        spread: 2.5
      }
    ]
  })
});
const scenario = await response.json();
console.log('Created scenario:', scenario.id);

Response

{
  "id": "990e8400-e29b-41d4-a716-446655440010",
  "name": "Q1 2026 Portfolio Optimization",
  "description": "Test impact of selling low-rated assets and buying high-quality loans",
  "status": "draft",
  "base_workbook_id": "550e8400-e29b-41d4-a716-446655440000",
  "trade_count": 2,
  "created_by": "user@example.com",
  "created_at": "2026-01-25T09:00:00Z",
  "updated_at": "2026-01-25T09:00:00Z"
}

Get Scenario

Retrieve scenario details.

GET /api/v1/scenarios/{scenario_id}

Path Parameters

Parameter Type Description
scenario_id string (UUID) Scenario identifier

Example Request

curl -X GET https://api.calcbridge.io/api/v1/scenarios/990e8400-e29b-41d4-a716-446655440010 \
  -H "Authorization: Bearer $TOKEN"
import requests

response = requests.get(
    f"https://api.calcbridge.io/api/v1/scenarios/{scenario_id}",
    headers={"Authorization": f"Bearer {token}"}
)
scenario = response.json()
const response = await fetch(
  `https://api.calcbridge.io/api/v1/scenarios/${scenarioId}`,
  { headers: { 'Authorization': `Bearer ${token}` } }
);
const scenario = await response.json();

Response

{
  "id": "990e8400-e29b-41d4-a716-446655440010",
  "name": "Q1 2026 Portfolio Optimization",
  "description": "Test impact of selling low-rated assets",
  "status": "completed",
  "base_workbook_id": "550e8400-e29b-41d4-a716-446655440000",
  "trade_count": 2,
  "created_by": "user@example.com",
  "created_at": "2026-01-25T09:00:00Z",
  "updated_at": "2026-01-25T10:30:00Z"
}

Add Trade to Scenario

Add a trade to an existing scenario.

POST /api/v1/scenarios/{scenario_id}/trades

Path Parameters

Parameter Type Description
scenario_id string (UUID) Scenario identifier

Request Body

See Trade Object above.

Example Request

curl -X POST https://api.calcbridge.io/api/v1/scenarios/990e8400-e29b-41d4-a716-446655440010/trades \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "trade_type": "buy",
    "cusip": "ADD789GHI",
    "borrower_name": "Additional Corp",
    "par_value": 250000.00,
    "rating_moodys": "B1",
    "spread": 3.25,
    "industry": "Technology"
  }'
import requests

response = requests.post(
    f"https://api.calcbridge.io/api/v1/scenarios/{scenario_id}/trades",
    headers={"Authorization": f"Bearer {token}"},
    json={
        "trade_type": "buy",
        "cusip": "ADD789GHI",
        "borrower_name": "Additional Corp",
        "par_value": 250000.00,
        "rating_moodys": "B1",
        "spread": 3.25,
        "industry": "Technology"
    }
)
trade = response.json()
print(f"Added trade: {trade['id']}")
const response = await fetch(
  `https://api.calcbridge.io/api/v1/scenarios/${scenarioId}/trades`,
  {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      trade_type: 'buy',
      cusip: 'ADD789GHI',
      borrower_name: 'Additional Corp',
      par_value: 250000.00,
      rating_moodys: 'B1',
      spread: 3.25,
      industry: 'Technology'
    })
  }
);
const trade = await response.json();
console.log('Added trade:', trade.id);

Response

{
  "id": "aa0e8400-e29b-41d4-a716-446655440020",
  "scenario_id": "990e8400-e29b-41d4-a716-446655440010",
  "trade_type": "buy",
  "cusip": "ADD789GHI",
  "borrower_name": "Additional Corp",
  "par_value": 250000.00,
  "price": null,
  "spread": 3.25,
  "rating_moodys": "B1",
  "rating_sp": null,
  "rating_fitch": null,
  "industry": "Technology",
  "maturity_date": null,
  "created_at": "2026-01-25T09:15:00Z"
}

List Scenario Trades

Get all trades in a scenario.

GET /api/v1/scenarios/{scenario_id}/trades

Path Parameters

Parameter Type Description
scenario_id string (UUID) Scenario identifier

Example Request

curl -X GET https://api.calcbridge.io/api/v1/scenarios/990e8400-e29b-41d4-a716-446655440010/trades \
  -H "Authorization: Bearer $TOKEN"

Response

[
  {
    "id": "aa0e8400-e29b-41d4-a716-446655440021",
    "scenario_id": "990e8400-e29b-41d4-a716-446655440010",
    "trade_type": "sell",
    "cusip": "OLD123ABC",
    "borrower_name": "Weak Corp",
    "par_value": 500000.00,
    "rating_moodys": "Caa2",
    "created_at": "2026-01-25T09:00:00Z"
  },
  {
    "id": "aa0e8400-e29b-41d4-a716-446655440022",
    "scenario_id": "990e8400-e29b-41d4-a716-446655440010",
    "trade_type": "buy",
    "cusip": "NEW456DEF",
    "borrower_name": "Strong Corp",
    "par_value": 500000.00,
    "rating_moodys": "Ba2",
    "spread": 2.5,
    "created_at": "2026-01-25T09:00:00Z"
  }
]

Remove Trade

Remove a trade from a scenario.

DELETE /api/v1/scenarios/{scenario_id}/trades/{trade_id}

Path Parameters

Parameter Type Description
scenario_id string (UUID) Scenario identifier
trade_id string (UUID) Trade identifier

Example Request

curl -X DELETE https://api.calcbridge.io/api/v1/scenarios/990e8400-e29b-41d4-a716-446655440010/trades/aa0e8400-e29b-41d4-a716-446655440020 \
  -H "Authorization: Bearer $TOKEN"

Response

Returns 204 No Content on success.


Run Simulation

Execute the scenario simulation and calculate compliance impact.

POST /api/v1/scenarios/{scenario_id}/simulate

Path Parameters

Parameter Type Description
scenario_id string (UUID) Scenario identifier

Example Request

curl -X POST https://api.calcbridge.io/api/v1/scenarios/990e8400-e29b-41d4-a716-446655440010/simulate \
  -H "Authorization: Bearer $TOKEN"
import requests

response = requests.post(
    f"https://api.calcbridge.io/api/v1/scenarios/{scenario_id}/simulate",
    headers={"Authorization": f"Bearer {token}"}
)
result = response.json()
print(f"Status: {result['status']}")
print(f"New failures: {result['new_failures']}")
const response = await fetch(
  `https://api.calcbridge.io/api/v1/scenarios/${scenarioId}/simulate`,
  {
    method: 'POST',
    headers: { 'Authorization': `Bearer ${token}` }
  }
);
const result = await response.json();
console.log('Status:', result.status);
console.log('New failures:', result.new_failures);

Response

{
  "scenario_id": "990e8400-e29b-41d4-a716-446655440010",
  "status": "completed",
  "results": [
    {
      "test_name": "Single Obligor Concentration",
      "test_category": "concentration",
      "current_value": 4.2,
      "projected_value": 4.1,
      "threshold_value": 5.0,
      "cushion_current": 0.8,
      "cushion_projected": 0.9,
      "status_current": "pass",
      "status_projected": "pass",
      "impact_direction": "improve"
    },
    {
      "test_name": "CCC Rated Assets",
      "test_category": "rating",
      "current_value": 8.5,
      "projected_value": 6.2,
      "threshold_value": 7.5,
      "cushion_current": -1.0,
      "cushion_projected": 1.3,
      "status_current": "fail",
      "status_projected": "pass",
      "impact_direction": "improve"
    },
    {
      "test_name": "Weighted Average Spread",
      "test_category": "portfolio",
      "current_value": 3.8,
      "projected_value": 3.6,
      "threshold_value": 3.0,
      "cushion_current": 0.8,
      "cushion_projected": 0.6,
      "status_current": "pass",
      "status_projected": "pass",
      "impact_direction": "worsen"
    }
  ],
  "impact_summary": {
    "improve": 2,
    "worsen": 1,
    "neutral": 12
  },
  "new_failures": 0,
  "total_tests": 15,
  "message": "Simulation completed: 2 trades applied to 150 loans"
}

Get Simulation Results

Retrieve saved simulation results.

GET /api/v1/scenarios/{scenario_id}/results

Path Parameters

Parameter Type Description
scenario_id string (UUID) Scenario identifier

Query Parameters

Parameter Type Description
category string Filter by test category

Example Request

curl -X GET "https://api.calcbridge.io/api/v1/scenarios/990e8400-e29b-41d4-a716-446655440010/results?category=rating" \
  -H "Authorization: Bearer $TOKEN"

Response

[
  {
    "test_name": "CCC Rated Assets",
    "test_category": "rating",
    "current_value": 8.5,
    "projected_value": 6.2,
    "threshold_value": 7.5,
    "cushion_current": -1.0,
    "cushion_projected": 1.3,
    "status_current": "fail",
    "status_projected": "pass",
    "impact_direction": "improve"
  },
  {
    "test_name": "Average Rating Factor",
    "test_category": "rating",
    "current_value": 2450,
    "projected_value": 2380,
    "threshold_value": 2600,
    "cushion_current": 150,
    "cushion_projected": 220,
    "status_current": "pass",
    "status_projected": "pass",
    "impact_direction": "improve"
  }
]

Delete Scenario

Delete a scenario and all associated trades and results.

DELETE /api/v1/scenarios/{scenario_id}

Path Parameters

Parameter Type Description
scenario_id string (UUID) Scenario identifier

Example Request

curl -X DELETE https://api.calcbridge.io/api/v1/scenarios/990e8400-e29b-41d4-a716-446655440010 \
  -H "Authorization: Bearer $TOKEN"

Response

Returns 204 No Content on success.


Scenario Status

Status Description
draft Scenario created, awaiting simulation
calculating Simulation in progress
completed Simulation finished successfully
failed Simulation encountered an error

Impact Direction

Direction Description
improve Projected value moves closer to passing
worsen Projected value moves closer to failing
neutral No significant change in compliance position

Best Practices

  1. Use descriptive names: Make scenarios easy to identify later
  2. Include all relevant trades: Simulate the complete trade package together
  3. Review results before execution: Pay attention to new failures
  4. Compare multiple scenarios: Create variations to find optimal trades
  5. Archive completed scenarios: Keep historical records for audit trails