SONIA vs SOFR Rate API: Two Overnight Prints

SONIA vs SOFR Rate API: Two Overnight Prints

You need both SONIA (GBP) and SOFR (USD) inside your pricing, treasury or lending stack, side by side, with the correct effective dates. By the end of this guide you’ll request both benchmarks from a single Interest Rates API, parse the JSON safely, handle business-day publication patterns, and compute spreads or loan payments using the returned values—without mixing timezones or currencies.

What SONIA and SOFR are, and when to fetch them together

SONIA and SOFR are overnight reference rates used across sterling and US dollar markets. If you quote cross-currency loans, fund overnight sweeps, compare cash ladders in GBP vs USD, or reconcile margin interest, you’ll likely need both prints from the same API, on demand, tagged to their own effective dates.

Interest Rates API exposes these benchmarks by code on a single REST endpoint. For this article we focus on two symbols only:

  • SONIA — Sterling Overnight Index Average (GBP)
  • SOFR — Secured Overnight Financing Rate (USD)

Both are delivered over GET /api/v1/latest with an api_key query parameter. You can pull each symbol separately (Starter plan) or in a single call (Professional plan). For documentation and model coverage, see MCP.

Endpoint and plan basics you actually need

Use GET /api/v1/latest with:

  • api_key — your API key as a query parameter
  • symbols — one or more rate codes, depending on plan

Plans relevant to this workflow:

  • Starter ($19/mo, 7‑day trial): one symbol per latest request and 250 calls. Make two calls (one for SONIA, one for SOFR) and merge the results in your app.
  • Professional ($49): pass both SONIA and SOFR in one request and parse both prints from one response.

Important operational notes:

  • Do not pass base=USD if you need SONIA (GBP). These are benchmark rates, not FX conversions.
  • Dates can differ per series. Always label and store dates.SONIA and dates.SOFR separately; never assume they’re equal.
  • If you need to express a loan’s spread relative to a different benchmark (e.g., convert from=SOFR&to=EURIBOR_3M), that is a different path than latest. Keep spread logic out of your SONIA/SOFR latest calls.

Make the request

Starter users: call the endpoint twice (once for SONIA, once for SOFR). Professional users: include both codes in the same request. Below is the official curl that demonstrates the request structure and authentication with api_key. If you’re on Starter, repeat the call with the other symbol; if you’re on Professional, pass both codes in symbols.

curl "https://interestratesapi.com/api/v1/latest?api_key=YOUR_API_KEY&symbols=SONIA"
curl "https://interestratesapi.com/api/v1/latest?api_key=YOUR_API_KEY&symbols=SOFR"

Python example (Starter: two separate calls)

This script fetches SONIA and SOFR sequentially using GET /api/v1/latest, then aligns them in memory. Replace YOUR_API_KEY with your key.

import requests

API = "https://interestratesapi.com/api/v1/latest"
API_KEY = "YOUR_API_KEY"

def get_latest(symbol):
    params = {
        "api_key": API_KEY,
        "symbols": symbol
    }
    r = requests.get(API, params=params, timeout=10)
    data = r.json()
    if not data.get("success", True):
        # Production code: log data.get("error"), retry or surface to monitoring
        raise RuntimeError(f"API returned success=false for {symbol}: {data}")
    # Return the raw dict so callers can decide how to cast value/units
    return data

sonia = get_latest("SONIA")
sofr = get_latest("SOFR")

# Label explicitly: dates can differ. Keep per-series fields.
pair = {
    "SONIA": {
        "date": sonia.get("dates", {}).get("SONIA") or sonia.get("date"),
        "value": sonia.get("rates", {}).get("SONIA") or sonia.get("rate")
    },
    "SOFR": {
        "date": sofr.get("dates", {}).get("SOFR") or sofr.get("date"),
        "value": sofr.get("rates", {}).get("SOFR") or sofr.get("rate")
    }
}

print(pair)

Understand the response

Here is the official JSON response example for the latest endpoint. Your integration should parse it as shown and treat dates per series independently.

{
  "rates": {
    "SOFR": 4.31,
    "SONIA": 4.70
  },
  "dates": {
    "SOFR": "2026-04-19",
    "SONIA": "2026-04-20"
  },
  "currencies": {
    "SOFR": "USD",
    "SONIA": "GBP"
  }
}

How to read the fields your code will actually use (field names depend on the response structure you receive):

  • success — Boolean. If false, do not use the payload for pricing; handle errors and retry or fail fast.
  • rates and/or rate — The numeric value(s) for the requested symbol(s). Use the symbol keys (e.g., SONIA, SOFR) when present.
  • dates and/or date — Effective dates. Always store per symbol, e.g., dates.SONIA and dates.SOFR, because publication calendars differ.

Units and interpretation:

  • The API returns each benchmark’s published level for the specified date. Do not convert currencies or apply FX bases here; SONIA is GBP, SOFR is USD.
  • Use the numeric value exactly as returned. If your UX requires percent formatting, format for display only. Keep the raw numeric for calculation.

Timezone and business day handling:

  • Effective dates reflect each administrator’s publication calendar. Weekends and local holidays typically yield no new print; the latest value holds until the next business publication.
  • Do not assume GMT or New York time for both. Persist the date string returned by the API and treat each series independently.

Publication cadence, business days, and caching strategy

Overnight benchmarks publish on their respective business days; gaps appear on weekends and local holidays. Build your polling and caching around that reality:

  • Polling: Schedule fetches on applicable business days shortly after the expected publication window for each rate. Avoid unnecessary weekend polling.
  • Caching: Cache by (symbol, date). If you fetch after market close and your integration is tolerant of the last available print, you can cache until the next expected business day.
  • Idempotency: Re-fetching the same (symbol, date) should yield the same value. Use this to simplify retries and monitoring.

Computing spreads and loan payments from the returned values

Spreads and payments often combine a benchmark with a margin and product-specific accrual conventions. Keep it deterministic and separate concerns:

  • Same-benchmark spread: Given two rates on the same day (e.g., SOFR vs SONIA for comparison), compute a simple difference: spread = rate_A − rate_B. Store the pair of effective dates to document any mismatch.
  • Cross-benchmark or tenor conversion: If you need to convert from one rate family to another benchmark (e.g., from=SOFR&to=EURIBOR_3M), use the dedicated convert path rather than trying to infer spreads from latest. This avoids mixing series definitions and minimizes mapping errors.
  • Monthly payment (amortizing loan): For a principal P, a periodic rate r_p (derived from the benchmark plus margin and any day-count adjustment), and N periods: - Payment = P × r_p / (1 − (1 + r_p)^−N) - r_p is your per-period rate. If working with monthly payments, derive r_p from the annualized benchmark according to your product’s conventions (e.g., divide by 12 if that’s your policy, or apply your day-count/compounding method). Use the raw numeric from the API as your starting point.

Practical guardrails:

  • Never mix currencies. SONIA (GBP) vs SOFR (USD) comparisons are spreads-in-level-only; they are not FX-adjusted.
  • Document the effective date next to any calculated spread or payment. If dates differ, retain both labels (e.g., “SOFR as of YYYY‑MM‑DD; SONIA as of YYYY‑MM‑DD”).

Go live: from trial to production

  1. Register for the trial at Register.
  2. Copy your api_key from the dashboard.
  3. On Starter, call GET /api/v1/latest twice (once for SONIA, once for SOFR). On Professional, pass both symbols in one call.
  4. Persist and label dates.SONIA and dates.SOFR. Do not add base=USD anywhere in these calls.

If you need symbol coverage, naming, or model notes, see MCP.

Error handling and operational tips

  • Check success in every response. If success=false, do not continue with pricing. Log, alert, or retry based on your SLOs.
  • Null or missing values: If a symbol key is present but the value is missing, treat it as unavailable for that date. Keep the last known good value only if your policy allows and tag it as stale.
  • Schema tolerance: Your code should handle either a per-symbol map (rates and dates keyed by SONIA and SOFR) or a single-value payload when only one symbol is requested.
  • Monitoring: Track the last-seen effective date per symbol and alert if it lags beyond your tolerance window (e.g., extended holidays).

Testing checklist before shipping

  • Starter vs Professional: Verify that your code path supports one or multiple symbols appropriately and merges data deterministically.
  • Date labeling: Confirm that the UI and logs display both dates when you compare SONIA and SOFR.
  • No currency base parameter: Ensure you never send base=USD or similar in latest calls.
  • Idempotent retries: Re-run the same call and assert unchanged values for the same date.
  • Calculation isolation: Keep spread and payment formulas in separate modules so that API ingestion and math changes are independently testable.

FAQ

Can I request SONIA and SOFR together on Starter?
No. Starter returns one symbol per latest request. Make two calls (one for SONIA, one for SOFR) and join them in your code. Professional can pass both in one call.

Do I need to set base=USD for SOFR?
No. Do not send base=USD. These are benchmark rates, not FX conversions, and the symbol you request determines the series.

Why are the dates different for SONIA and SOFR in the same response?
Each series follows its own publication calendar. Dates can differ per series; always label and store dates.SONIA and dates.SOFR separately.

How do I compute a spread to another benchmark like EURIBOR 3M?
Use the convert path dedicated to conversions (e.g., from=SOFR&to=EURIBOR_3M). Keep that separate from latest calls so you don’t conflate series definitions.

What should I cache?
Cache by (symbol, date). Refresh on the next applicable business day or when your job detects a new effective date for that series.

Ready to integrate SONIA and SOFR in one workflow? Start your 7‑day trial, get your key, and ship a production‑ready fetch in minutes: Register. For symbol coverage and documentation, see MCP.

Ready to get started?

Get your API key and start validating bank data in minutes.

Get API Key