November 27, 2024

SOFR Curve API: Forward Rates, Fixings and Curves in Python

Author:
Ahmed Babikir
Author:
Ali Vohra
Author:
Sérgio Araújo
Author:
Gleb Pilipenko

A SOFR curve API returns the market-implied path of SOFR: forward rates for any future period, the full forward curve, and the discount factors that come with it, as JSON you can pull into a model. The New York Fed publishes the SOFR fixing itself for free, but it does not publish a forward curve. This guide covers both in Python: the free published rate, then forward rates, the whole curve, past curves and loan schedules from the BlueGamma API.

If you only need today's curve on screen, it is on our SOFR forward curve page. If you want it in code, read on.

What does a SOFR API give you?

It depends on which SOFR you need. A published fixing tells you what SOFR was; a forward curve tells you what the market prices it to be. They come from different places:

What you needWhat it isWhere it comes from
SOFR fixingsOne overnight rate per business day, published around 8:00 a.m. ET for the previous business dayNew York Fed Markets Data API, free with no key; also in the BlueGamma API alongside the curve
SOFR forward curveMarket-implied forward rates for any future period, built from SOFR swap quotesA curve API such as BlueGamma; the Fed does not publish one
Discount factorsThe present value of $1 paid on a future date, from the same curveA curve API
Term SOFRA forward-looking 1M, 3M, 6M or 12M rate fixed at the start of each periodA separate benchmark, administered and licensed by CME Group

The published rate takes three lines and no sign-up:

import requests

# Published SOFR from the New York Fed: free, no key, one rate per business day
url = "https://markets.newyorkfed.org/api/rates/secured/sofr/last/5.json"
for row in requests.get(url).json()["refRates"]:
    print(row["effectiveDate"], row["percentRate"])

That covers past accruals. For anything forward-looking (budgeting interest cost, valuing a swap, pricing a loan), you need the curve. The rest of this guide uses the BlueGamma API, which serves both. The difference between the two SOFR flavours that loans reference is in our guide to Term SOFR vs compounded SOFR.

Step 1: Set Up Your Environment

You need an API key and Python with requests and matplotlib. The key is self-serve: start the 14-day free trial, open the API Dashboard in the app and create one. There is no form to fill in and nobody to wait for.

pip install requests matplotlib

Every request authenticates with the key in the x-api-key header. A small helper keeps the examples short; each snippet below builds on it:

import requests

API_KEY = "YOUR_API_KEY"  # create one in the BlueGamma app under API Dashboard
BASE_URL = "https://api.bluegamma.io/v1"
HEADERS = {"x-api-key": API_KEY}

def get(endpoint, **params):
    response = requests.get(f"{BASE_URL}/{endpoint}", headers=HEADERS, params=params)
    response.raise_for_status()
    return response.json()

Step 2: Fetch SOFR Forward Rates

The /forward_rate endpoint returns the market-implied rate for one forward period. Here is the 3M SOFR forward rate starting one year from today:

# The 3M SOFR forward rate starting one year from today
data = get("forward_rate", index="SOFR", start_date="1Y", end_date="3M")

print(f"{data['start_date']} to {data['end_date']}: {data['forward_rate']:.4f}%")

start_date takes a tenor measured from today (1Y, 18M) or a calendar date, and end_date takes the length of the period (3M) or an end date. Tenors keep the script evergreen: it asks for "a year from now" every time it runs. The response echoes the resolved dates and the curve's valuation time, with forward_rate as an annualised percentage for the whole period.

Step 3: Build a SOFR Forward Curve

You could loop over /forward_rate date by date, but /forward_curve returns the whole strip in one request, every point priced off the same curve snapshot:

import matplotlib.pyplot as plt

# The whole curve in one call: 3M SOFR forwards, one every 3 months, for 5 years
curve = get(
    "forward_curve",
    index="SOFR",
    start_date="2D",          # spot
    end_date="5Y",            # how far out the curve runs
    tenor="3M",               # length of each forward period
    frequency="3M",           # spacing between curve points
    is_end_of_month="false",  # even 3M periods from spot
)

start_dates = [point["start_date"] for point in curve["curve"]]
forward_rates = [point["forward_rate"] for point in curve["curve"]]

plt.figure(figsize=(12, 6))
plt.plot(start_dates, forward_rates, marker="o", label="3M SOFR forward")
plt.title(f"3M SOFR Forward Curve ({curve['valuation_time'][:10]})")
plt.xlabel("Start date")
plt.ylabel("Forward rate (%)")
plt.xticks(start_dates[::4], rotation=45)
plt.grid(True, linestyle="--", alpha=0.7)
plt.legend()
plt.tight_layout()
plt.show()

tenor sets the length of each forward period and frequency the spacing between points, so 3M and 3M gives back-to-back quarterly forwards. Use 1M for a 1M SOFR curve, or push end_date to 10Y or 30Y for the long end.

Step 4: Understand the Output

The script plots the 3M SOFR forward curve, one point per quarter:

  • x-axis: the start date of each 3-month forward period
  • y-axis: the forward rate for that period, in percent
3M SOFR forward curve plotted in Python from the BlueGamma API forward_curve endpoint
Output of the Step 3 script

By default periods align to month ends, which makes the first point a short stub to the end of the current month; the script passes is_end_of_month=false to get even periods from spot instead. A forward curve is the rate the market prices today for each future period. It is not a forecast, and the next section shows how far the two can drift apart. For how the curve is built from swap quotes, see SOFR curve construction.

Step 5: Compare a Past Curve With the Fixings

Add valuation_time to any call to get the curve as it stood at that moment, which is what a month-end valuation or an audit trail needs. Pair it with /historical_fixings and you can see what the curve priced against what SOFR actually did:

# The same curve as it stood a year earlier. With valuation_time,
# give start_date and end_date as calendar dates.
curve_then = get(
    "forward_curve",
    index="SOFR",
    start_date="2025-10-14",
    end_date="2027-10-14",
    tenor="3M",
    frequency="3M",
    is_end_of_month="false",
    valuation_time="2025-10-09T16:00:00Z",
)

# Every published SOFR fixing since then
fixings = get("historical_fixings", index="SOFR", start_date="2025-10-09", end_date="2026-10-08")

plt.figure(figsize=(12, 6))
plt.plot([f["date"] for f in fixings["fixings"]], [f["rate"] for f in fixings["fixings"]], label="SOFR fixings")
plt.plot([p["start_date"] for p in curve_then["curve"]], [p["forward_rate"] for p in curve_then["curve"]], "--o", label="Forward curve a year ago")
plt.plot(start_dates[:5], forward_rates[:5], "-o", label="Forward curve today")
plt.ylabel("Rate (%)")
plt.legend()
plt.show()

With valuation_time set, pass start_date and end_date as calendar dates rather than tenors. Restyled, the result looks like this:

3M SOFR forward curve from a year ago and today, with SOFR daily fixings over the past year, all from the BlueGamma API
A year ago the curve priced 3M SOFR near 3.1% for this autumn; the fixings have stayed close to 3.9%

A year ago, the curve priced SOFR falling to around 3.1% by now. It fell, but not that far, and today's curve prices it higher again. That gap is the reason to value off today's curve, and to keep the curve you valued off: valuation_time lets you reproduce either one later.

Step 6: Price Your Own Schedule

Real loans rarely pay on neat quarter dates. /forward_rates takes your actual periods, stubs included, and returns a rate for each from one curve snapshot. /discount_factor gives the factor to present-value a cash flow on any date:

# Forward rates for your own schedule, broken periods included, in one request
schedule = {
    "index": "SOFR",
    "periods": [
        {"start_date": "2026-12-15", "end_date": "2027-03-15"},
        {"start_date": "2027-03-15", "end_date": "2027-04-02"},  # short stub
    ],
}
response = requests.post(f"{BASE_URL}/forward_rates", headers=HEADERS, json=schedule)
response.raise_for_status()
for period in response.json()["rates"]:
    print(period["start_date"], period["end_date"], round(period["forward_rate"], 4))

# Discount factor to a date, for present-valuing a cash flow
df = get("discount_factor", index="SOFR", date="5Y")
print(df["date"], df["discount_factor"])

Each rate is a simple annualised rate for its whole period on SOFR's Actual/360 basis, with daily compounding already inside it, so apply it once as rate × days / 360. That is the projection step behind valuing a swap or budgeting a floating-rate loan.

Beyond SOFR and Beyond Python

Every call above works for the other indices we cover across 30+ currencies, from SONIA and €STR to 3M EURIBOR: change index and nothing else. GET /v1/indices lists the exact names, and the full reference is in the API documentation. If the curve needs to land in a spreadsheet rather than a script, the Excel Add-in runs the same numbers as a formula: =BlueGamma.FORWARD_RATE("SOFR", start_date, end_date).

SOFR curve API

Get your API key and run this today

  • Start the 14-day free trial
  • Create your key in the app's API Dashboard
  • Live and historical SOFR curves, fixings and discount factors
Get a Free API Key

No card needed, cancels automatically

More API tutorials: the Euribor API and the CORRA API.

Frequently Asked Questions

Is there a free SOFR API?

Yes, for the published rate. The New York Fed's Markets Data API serves daily SOFR fixings as JSON with no key, for example markets.newyorkfed.org/api/rates/secured/sofr/last/5.json. It does not serve a forward curve or discount factors; those are built from SOFR swap quotes and come from a curve provider.

What is the difference between SOFR and the SOFR forward curve?

SOFR is a published overnight rate: one backward-looking number per business day. The SOFR forward curve is the market-implied rate for future periods, derived from SOFR swap prices, and it moves every time those prices do. Fixings tell you what accrued; the curve tells you what the market prices for what comes next.

Can I get historical SOFR forward curves through the API?

Yes. Add a valuation_time parameter to any curve call and the API rebuilds the curve as it stood at that moment, which is what month-end valuations and audit trails need. Give start_date and end_date as calendar dates when you do.

What format and units does the API return?

JSON over HTTPS, authenticated with an x-api-key header. Forward rates and fixings are percentages (4.25 means 4.25%); discount factors are decimals between 0 and 1.

How do I get a BlueGamma API key?

Start the 14-day free trial and create a key in the app's API Dashboard. It is self-serve and needs no card, so you can make your first call the same day.

Try BlueGamma free for 14 days
BlueGamma.io company logo.

Get historic and live interest rates and FX forward curves delivered through our Excel Add‑in, API, MCP or web-app.

Made with ❤️ in rainy London ☔