# How to Price a Swap Using the API

This guide walks you through pricing interest rate swaps using the BlueGamma API. Whether you need a simple mid-market rate or detailed cashflow analysis for an amortizing loan hedge, we offer multiple approaches.

This example uses **SOFR swaps** with **semi-annual payments**.

***

### Before You Start

To follow this guide, make sure you have:

* An active BlueGamma API key
* Python 3.x with the `requests` library installed

If you don't have an API key yet, see [Authentication](/documentation/integrations/api/authentication.md) or contact <support@bluegamma.io>.

***

### Overview: Mid Swap Rate vs Mark-to-Market

When pricing a swap, there are two key values you'll typically need:

**Mid Swap Rate (Fair Rate)**

The **mid swap rate** (also called the **par rate** or **fair rate**) is the fixed rate that makes the present value of the fixed leg equal to the present value of the floating leg — i.e., NPV = 0.

$$
\text{Mid Swap Rate} = \frac{\sum\_{i=1}^{n} (F\_i \times DF\_i \times \tau\_i \times N\_i)}{\sum\_{i=1}^{n} (DF\_i \times \tau\_i \times N\_i)}
$$

Where:

* **F**<sub>**i**</sub> = Forward rate for period *i*
* **DF**<sub>**i**</sub> = Discount factor to payment date *i*
* **τ**<sub>**i**</sub> = Day count fraction for period *i*
* **N**<sub>**i**</sub> = Notional for period *i*

**Mark-to-Market (MTM)**

The **mark-to-market** value represents the current market value of an existing swap. It's calculated as the difference between the present value of the floating leg and the fixed leg at the contracted rate.

* **MTM > 0**: The swap is an asset (in your favor)
* **MTM < 0**: The swap is a liability (against you)

***

### Method 1: Use the /swap\_pricer Endpoint (Recommended)

The `/swap_pricer` endpoint provides comprehensive swap valuation in a single API call:

* Fair swap rate calculation
* Mark-to-market valuation
* PV01 (dollar value of a basis point)
* Detailed cashflow schedules for both fixed and floating legs

This is the recommended approach for loan hedging and amortizing swaps.

#### Request Format

```
POST https://api.bluegamma.io/v1/swap_pricer
Content-Type: application/json
x-api-key: your_api_key_here
```

#### Request Parameters

| Field                          | Required | Description                                                                                                  |
| ------------------------------ | -------- | ------------------------------------------------------------------------------------------------------------ |
| `index`                        | Yes      | Reference rate index (e.g., "SOFR", "SONIA", "3M EURIBOR")                                                   |
| `start_date`                   | Yes      | Swap start date (YYYY-MM-DD or tenor like "0D")                                                              |
| `maturity_date`                | Yes      | Swap maturity date (YYYY-MM-DD or tenor like "5Y")                                                           |
| `fixed_leg_frequency`          | Yes      | Payment frequency (e.g., "6M", "3M", "1Y")                                                                   |
| `fixed_notionals`              | Yes      | Notional amount(s) — see [Notionals](#notionals) below                                                       |
| `fixed_rate`                   | No       | Fixed rate as percentage (e.g., 4.25 for 4.25%). If omitted, MTM = 0                                         |
| `fixed_leg_first_payment_date` | No       | First payment date (YYYY-MM-DD). Defaults to start\_date + fixed\_leg\_frequency adjusted for business days. |
| `fixed_leg_day_count`          | No       | Day count convention for fixed leg (defaults to currency-specific)                                           |
| `valuation_time`               | No       | Valuation timestamp (ISO 8601). Defaults to current time.                                                    |

For a full list of supported indices, see [Available Indices](/documentation/integrations/available-indices.md).

#### Notionals

The `fixed_notionals` field accepts either a single number or an array, depending on your swap type:

| Swap type         | `fixed_notionals` value                | What happens                                 |
| ----------------- | -------------------------------------- | -------------------------------------------- |
| **Flat (bullet)** | `10000000` or `[10000000]`             | Same notional applied to every period        |
| **Amortising**    | `[100000000, 90000000, 80000000, ...]` | Each value maps to a payment period in order |

**Flat notional** — for a standard swap where the notional stays the same throughout, pass a single number or a single-element array. Both are equivalent:

```json
{ "fixed_notionals": 10000000 }
```

```json
{ "fixed_notionals": [10000000] }
```

**Amortising notional** — for a swap where the notional decreases over time (e.g. matching a loan repayment schedule), pass an array with one value per payment period. The number of values should match the number of periods in the swap:

```json
{
  "fixed_notionals": [100000000, 90000000, 80000000, 70000000, 60000000]
}
```

Each value is applied to the corresponding period in chronological order. If you provide fewer values than periods, the last value is used for all remaining periods.

#### Response Fields

| Field                | Description                                               |
| -------------------- | --------------------------------------------------------- |
| `fair_rate`          | The mid-market par swap rate (percentage)                 |
| `mtm`                | Mark-to-market value (0 if no fixed\_rate provided)       |
| `pv01`               | Dollar value of 1 basis point move                        |
| `fixed_rate`         | The fixed rate used (input or fair\_rate if not provided) |
| `fixed_cashflows`    | Array of fixed leg cashflow details                       |
| `floating_cashflows` | Array of floating leg cashflow details                    |

***

### Example 1: Get the Mid Swap Rate

To get the current mid-market swap rate, simply omit the `fixed_rate` parameter. The API will return the fair rate, and MTM will be zero.

```python
import requests

API_KEY = "your_api_key_here"
BASE_URL = "https://api.bluegamma.io/v1"
headers = {
    "x-api-key": API_KEY,
    "Content-Type": "application/json"
}

# Get the mid swap rate for a 10Y SOFR swap
response = requests.post(
    f"{BASE_URL}/swap_pricer",
    headers=headers,
    json={
        "index": "SOFR",
        "start_date": "2026-01-26",
        "maturity_date": "2036-01-26",
        "fixed_leg_frequency": "6M",
        "fixed_notionals": [10000000]
    }
)

data = response.json()
print(f"Mid Swap Rate: {data['fair_rate']:.4f}%")
print(f"MTM: ${data['mtm']:,.2f}")
print(f"PV01: ${data['pv01']:,.2f}")
```

```bash
curl -X POST "https://api.bluegamma.io/v1/swap_pricer" \
  -H "x-api-key: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "index": "SOFR",
    "start_date": "2026-01-26",
    "maturity_date": "2036-01-26",
    "fixed_leg_frequency": "6M",
    "fixed_notionals": [10000000]
  }'
```

**Example Response:**

```json
{
  "index": "SOFR",
  "currency": "USD",
  "start_date": "2026-01-26",
  "maturity_date": "2036-01-26",
  "fixed_leg_first_payment_date": "2026-07-27",
  "floating_leg_first_payment_date": "2026-07-27",
  "valuation_time": "2026-02-02T16:22:49.128781",
  "timestamp": "2026-02-02T16:22:29",
  "fixed_leg_frequency": "6M",
  "floating_leg_frequency": "6M",
  "fixed_leg_day_count": "Actual360",
  "floating_leg_day_count": "Actual360",
  "fixed_rate": 3.844,
  "fair_rate": 3.844,
  "mtm": 0.0,
  "pv01": -8419.0,
  "fixed_cashflows": [...],
  "floating_cashflows": [...]
}
```

**Key Points:**

* The `fair_rate` is **3.844%** — this is your mid swap rate
* The `mtm` is **0.0** because the swap is priced at fair value
* The `pv01` of **-$8,419** means a 1bp increase in rates decreases the swap value by \~$8.4k

{% hint style="success" %}
**Want help integrating swap pricing into your workflow?** Book a 15-minute call and we'll walk you through your first API integration.

[Book a demo →](https://app.lemcal.com/@alivohra/website-demo?back=1)
{% endhint %}

***

### Example 2: Get Mark-to-Market for an Existing Swap

If you have an existing swap with a contracted fixed rate, provide the `fixed_rate` parameter to calculate the MTM.

```python
# Calculate MTM for an existing swap at 4.25% fixed rate
response = requests.post(
    f"{BASE_URL}/swap_pricer",
    headers=headers,
    json={
        "index": "SOFR",
        "start_date": "2026-01-26",
        "maturity_date": "2036-01-26",
        "fixed_leg_frequency": "6M",
        "fixed_rate": 4.25,  # Existing contracted rate
        "fixed_notionals": [10000000]
    }
)

data = response.json()
print(f"Fair Rate: {data['fair_rate']:.4f}%")
print(f"Fixed Rate: {data['fixed_rate']:.4f}%")
print(f"MTM: ${data['mtm']:,.2f}")
```

```bash
curl -X POST "https://api.bluegamma.io/v1/swap_pricer" \
  -H "x-api-key: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "index": "SOFR",
    "start_date": "2026-01-26",
    "maturity_date": "2036-01-26",
    "fixed_leg_frequency": "6M",
    "fixed_rate": 4.25,
    "fixed_notionals": [10000000]
  }'
```

**Example Response:**

```json
{
  "index": "SOFR",
  "currency": "USD",
  "start_date": "2026-01-26",
  "maturity_date": "2036-01-26",
  "fixed_rate": 4.25,
  "fair_rate": 3.848,
  "mtm": -33839.15,
  "pv01": -8417.50
}
```

**Interpretation:**

* Your fixed rate (4.25%) is **higher** than the current fair rate (3.848%)
* If you're paying fixed, you're paying more than market — the swap is a **liability**
* MTM is **negative** — you would need to pay this to exit the swap

{% hint style="info" %}
**Pro Tip:** The MTM can be approximated as: MTM ≈ (Fair Rate - Fixed Rate) × PV01 × 100

Example: (3.848% - 4.25%) × (-8,417) × 100 ≈ $33,836 (close to actual MTM)
{% endhint %}

{% hint style="success" %}
**Need to value your swap portfolio?** We can help you set up automated MTM calculations for all your positions.

[Book a demo →](https://app.lemcal.com/@alivohra/website-demo?back=1)
{% endhint %}

For ongoing MTM tracking of existing swaps, also see [Swap Mark-to-Market](/documentation/pricers/calculating-the-mtm-of-a-swap.md).

***

### Example 3: Price an Amortizing Swap

For loan hedging, you often need to match your swap notional to your loan's amortization schedule. Pass an array of notionals to `fixed_notionals`.

```python
# Define the loan amortization schedule (decreasing notionals)
notionals = [
    100000000,  # Period 1: $100M
    90000000,   # Period 2: $90M
    80000000,   # Period 3: $80M
    70000000,   # Period 4: $70M
    60000000,   # Period 5: $60M
    50000000,   # Period 6: $50M
    40000000,   # Period 7: $40M
    30000000,   # Period 8: $30M
    20000000,   # Period 9: $20M
    10000000    # Period 10: $10M
]

response = requests.post(
    f"{BASE_URL}/swap_pricer",
    headers=headers,
    json={
        "index": "SOFR",
        "start_date": "2026-02-02",
        "fixed_leg_first_payment_date": "2026-06-30",  # Match loan payment date
        "maturity_date": "2031-06-30",
        "fixed_leg_frequency": "6M",
        "fixed_rate": 3.85,
        "fixed_notionals": notionals
    }
)

data = response.json()
print(f"Fair Rate: {data['fair_rate']:.4f}%")
print(f"MTM: ${data['mtm']:,.2f}")
print(f"PV01: ${data['pv01']:,.2f}")
```

```bash
curl -X POST "https://api.bluegamma.io/v1/swap_pricer" \
  -H "x-api-key: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "index": "SOFR",
    "start_date": "2026-02-02",
    "fixed_leg_first_payment_date": "2026-06-30",
    "maturity_date": "2031-06-30",
    "fixed_leg_frequency": "6M",
    "fixed_rate": 3.85,
    "fixed_notionals": [100000000, 90000000, 80000000, 70000000, 60000000, 50000000, 40000000, 30000000, 20000000, 10000000]
  }'
```

**Example Response:**

```json
{
  "index": "SOFR",
  "currency": "USD",
  "start_date": "2026-02-02",
  "maturity_date": "2031-06-30",
  "fixed_leg_first_payment_date": "2026-06-30",
  "fixed_rate": 3.85,
  "fair_rate": 3.4632,
  "mtm": -101868.92,
  "pv01": -26412.46
}
```

**Key Points:**

* The **amortizing swap rate** (3.46%) is lower than a bullet swap rate because more weight is placed on near-term periods where forward rates are lower
* MTM is calculated correctly based on the amortizing schedule
* PV01 is smaller because the average outstanding notional is lower than a bullet swap

***

### Example 4: Custom First Payment Date

When hedging a loan, your first interest payment date often doesn't fall exactly one period from the start date. Use `fixed_leg_first_payment_date` to align your swap to your loan schedule.

```python
response = requests.post(
    f"{BASE_URL}/swap_pricer",
    headers=headers,
    json={
        "index": "SOFR",
        "start_date": "2026-01-15",
        "fixed_leg_first_payment_date": "2026-03-31",  # Short first period
        "maturity_date": "2031-03-31",
        "fixed_leg_frequency": "6M",
        "fixed_notionals": [100000000]
    }
)
```

```bash
curl -X POST "https://api.bluegamma.io/v1/swap_pricer" \
  -H "x-api-key: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "index": "SOFR",
    "start_date": "2026-01-15",
    "fixed_leg_first_payment_date": "2026-03-31",
    "maturity_date": "2031-03-31",
    "fixed_leg_frequency": "6M",
    "fixed_notionals": [100000000]
  }'
```

This creates a swap where the first period runs from 2026-01-15 to 2026-03-31 (a short stub), then regular 6M periods thereafter.

***

### Understanding the Cashflow Response

Each cashflow in the response contains detailed period information:

```json
{
  "period_start": "2026-02-02",
  "period_end": "2026-08-03",
  "notional": 100000000.0,
  "day_count_fraction": 0.5056,
  "rate": 3.6307,
  "cashflow": 1835536.94,
  "discount_factor": 0.9820,
  "present_value": 1802452.26
}
```

| Field                | Description                                                             |
| -------------------- | ----------------------------------------------------------------------- |
| `period_start`       | Accrual start date                                                      |
| `period_end`         | Accrual end date (payment date)                                         |
| `notional`           | Notional amount for this period                                         |
| `day_count_fraction` | Year fraction based on day count convention                             |
| `rate`               | Interest rate (fixed rate for fixed leg, forward rate for floating leg) |
| `cashflow`           | Undiscounted cashflow: Notional × Rate × DCF                            |
| `discount_factor`    | Discount factor to payment date                                         |
| `present_value`      | Discounted cashflow value                                               |

For more on discount factors, see [Getting Discount Factors](/documentation/integrations/api/how-to-guides/getting-discount-factors.md).

***

### Method 2: Use the /swap\_rate Endpoint (Quick)

For a quick par rate without cashflows, use the GET `/swap_rate` endpoint:

```python
response = requests.get(
    f"{BASE_URL}/swap_rate",
    headers={"x-api-key": API_KEY},
    params={
        "index": "SOFR",
        "start_date": "2026-01-26",
        "maturity_date": "2036-01-26",
        "fixed_leg_frequency": "6M"
    }
)

print(response.json())
```

```bash
curl -X GET "https://api.bluegamma.io/v1/swap_rate?index=SOFR&start_date=2026-01-26&maturity_date=2036-01-26&fixed_leg_frequency=6M" \
  -H "x-api-key: your_api_key_here"
```

**Example Response:**

```json
{
  "index": "SOFR",
  "start_date": "2026-01-26",
  "maturity_date": "2036-01-26",
  "fixed_leg_first_payment_date": "2026-07-27",
  "floating_leg_first_payment_date": "2026-07-27",
  "floating_leg_frequency": "6M",
  "floating_leg_day_count": "Actual360",
  "fixed_leg_frequency": "6M",
  "fixed_leg_day_count": "Actual360",
  "valuation_time": "2026-02-02T16:22:49.128781",
  "swap_rate": 3.844
}
```

For more details, see [Fetching a Swap Rate](/documentation/integrations/api/how-to-guides/fetching-a-swap-rate.md).

***

### Method 3: Build the Cashflow Schedule (Full Control)

For complete control — such as custom date schedules or integrating into your own pricing models — you can build the cashflow schedule yourself using the [Getting Forward Rates](/documentation/integrations/api/how-to-guides/getting-forward-rates.md) and [Getting Discount Factors](/documentation/integrations/api/how-to-guides/getting-discount-factors.md) endpoints.

```python
def fetch_forward_rate(index: str, start_date: str, end_date: str) -> float:
    """Fetch forward rate for a specific period."""
    response = requests.get(
        f"{BASE_URL}/forward_rate",
        headers=headers,
        params={"index": index, "start_date": start_date, "end_date": end_date}
    )
    return response.json()["forward_rate"]

def fetch_discount_factor(index: str, date: str) -> float:
    """Fetch discount factor for a specific date."""
    response = requests.get(
        f"{BASE_URL}/discount_factor",
        headers=headers,
        params={"index": index, "date": date}
    )
    return response.json()["discount_factor"]
```

***

### Comparing with the BlueGamma Web App

You can validate your API results against the BlueGamma web application.

#### Step 1: Open the Swap Pricer

Go to [app.bluegamma.io/swap-pricer](https://app.bluegamma.io/swap-pricer) and click **Add Swap**.

#### Step 2: Enter the Same Swap Parameters

Configure the swap with the same parameters used in your API call:

* **Currency:** USD (for SOFR)
* **Start Date:** 26/01/2026
* **First Interest Payment Date:** 26/07/2026
* **End Date:** 26/01/2036 (10 years)
* **Payment Frequency:** 6M
* **Notional:** 10,000,000

<figure><img src="/files/OoAn8jj8RYIqj3A18Yac" alt="BlueGamma Swap Pricer form showing USD currency selection with 10-year tenor and 6M payment frequency"><figcaption><p>Enter swap details matching your API parameters</p></figcaption></figure>

#### Step 3: Compare the Results

The app displays the **Mid Swap Rate: 3.844%** and **BPV: 8,419**, which matches our API result.

<figure><img src="/files/48wSGTR3eGgAWN0xmVvS" alt="BlueGamma Swap Pricer showing Mid Swap Rate of 3.844% and BPV of 8,419 for a 10-year USD SOFR swap"><figcaption><p>The web app shows 3.844% and BPV 8,419 — matching the API result</p></figcaption></figure>

The results match because both the API and web app use the same underlying curve data and calculation methodology.

{% hint style="info" %}
**Tip:** If you see small differences, check that your day count convention and payment frequency match exactly. The API defaults to currency-standard conventions.
{% endhint %}

***

### Day Count Conventions

The API supports the following day count conventions:

| Convention               | Description                                    |
| ------------------------ | ---------------------------------------------- |
| `Actual360`              | Actual days / 360 (standard for SOFR, EURIBOR) |
| `Actual365Fixed`         | Actual days / 365 (standard for GBP SONIA)     |
| `Thirty360BondBasis`     | 30/360 US convention                           |
| `Thirty360EuroBondBasis` | 30/360 European convention                     |
| `Business252`            | Business days / 252 (used for BRL CDI)         |

When using the `/swap_pricer` endpoint, you can specify the convention:

```python
response = requests.post(
    f"{BASE_URL}/swap_pricer",
    headers=headers,
    json={
        "index": "SONIA",
        "start_date": "2026-02-02",
        "maturity_date": "2031-02-02",
        "fixed_leg_frequency": "1Y",
        "fixed_leg_day_count": "Actual365Fixed",
        "floating_leg_day_count": "Actual365Fixed",
        "fixed_notionals": [50000000]
    }
)
```

```bash
curl -X POST "https://api.bluegamma.io/v1/swap_pricer" \
  -H "x-api-key: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "index": "SONIA",
    "start_date": "2026-02-02",
    "maturity_date": "2031-02-02",
    "fixed_leg_frequency": "1Y",
    "fixed_leg_day_count": "Actual365Fixed",
    "floating_leg_day_count": "Actual365Fixed",
    "fixed_notionals": [50000000]
  }'
```

***

### Error Handling

Always handle potential API errors. For rate limit details, see [Rate Limits & Best Practices](/documentation/integrations/api/rate-limits.md).

```python
response = requests.post(f"{BASE_URL}/swap_pricer", headers=headers, json=payload)

if response.status_code == 200:
    data = response.json()
    print(f"Fair Rate: {data['fair_rate']:.4f}%")
elif response.status_code == 403:
    print("Error: Invalid or missing API key")
elif response.status_code == 400:
    print(f"Error: Bad request - {response.json()}")
elif response.status_code == 422:
    print(f"Error: Validation failed - {response.json()}")
elif response.status_code == 429:
    print("Error: Rate limit exceeded - please wait and retry")
else:
    print(f"Error: {response.status_code} - {response.text}")
```

***

### Summary: Mid Rate vs MTM

| Scenario         | `fixed_rate` Parameter  | What You Get                                  |
| ---------------- | ----------------------- | --------------------------------------------- |
| **Get Mid Rate** | Omit                    | `fair_rate` = mid swap rate, `mtm` = 0        |
| **Get MTM**      | Provide contracted rate | `fair_rate` = current mid, `mtm` = swap value |

***

### API Endpoint Reference

| Endpoint           | Method | Use Case                                       |
| ------------------ | ------ | ---------------------------------------------- |
| `/swap_pricer`     | POST   | Full swap pricing with cashflows (recommended) |
| `/swap_rate`       | GET    | Quick par rate calculation (no cashflows)      |
| `/forward_rate`    | GET    | Forward rate between any two dates             |
| `/discount_factor` | GET    | Discount factor to any specific date           |

For the complete API specification, see [API Reference](/documentation/integrations/api/api-reference.md).

***

### Related Guides

* [Fetching a Swap Rate](/documentation/integrations/api/how-to-guides/fetching-a-swap-rate.md) — Quick par rate lookup
* [Fetching a Swap Curve](/documentation/integrations/api/how-to-guides/fetching-a-swap-curve.md) — Get rates for all tenors
* [Getting Forward Rates](/documentation/integrations/api/how-to-guides/getting-forward-rates.md) — Forward rates for custom periods
* [Getting Discount Factors](/documentation/integrations/api/how-to-guides/getting-discount-factors.md) — Discount factors for PV calculations
* [Fetching Compounded RFR Rates](/documentation/integrations/api/how-to-guides/fetching-compounded-rfr-rates.md) — Realised rates for RFR indices
* [Validating BlueGamma API Data Against Bloomberg or Other Platforms](/documentation/integrations/api/how-to-guides/validating-bluegamma-api-data-against-bloomberg-or-other-platforms.md) — Compare with Bloomberg

***

**Need help?** 📩 <support@bluegamma.io> | 📅 [Book a call](https://app.lemcal.com/@alivohra/website-demo?back=1)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://bluegamma.io/documentation/integrations/api/how-to-guides/how-to-price-a-swap-using-the-api.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
