NBS Rate API: First Request

NBS Rate API: First Request

You need the National Bank of Serbia’s key policy rate inside your code, with versioned endpoints you can test right away and responses you can cache confidently. By the end of this guide you’ll query NBS_RATE over HTTPS, read its effective dates correctly, compute spreads and payments from the returned value, and integrate seven endpoints for production-grade dashboards, loan tools, and research pipelines.

What NBS_RATE Represents and Why It Matters

NBS_RATE is the National Bank of Serbia (NBS) key policy rate. In this API it is a central bank benchmark for RSD with a monthly frequency. Monetary policy decisions here influence RSD borrowing costs, loan repricing, discount factors, and macro models across Serbia- and RSD-linked instruments and portfolios.

Illustration: NBS Rate API: First Request

Key points you will use in code:

  • Symbol: NBS_RATE
  • Category: central_bank
  • Currency: RSD (listed as currency_code in symbols and as “USD” in some sample payloads for illustration only)
  • Frequency: monthly. For date-specific queries, the API uses the last day with data within the month if the exact day has no observation.

All requests are GET-only, authenticated via an api_key query parameter, and use the base URL https://interestratesapi.com/api/v1/. See interestratesapi.com and the Interest Rates API MCP for reference. When you’re ready to run calls, grab a key here: Register for Interest Rates API and Get started with Interest Rates API.

Official sample response schema (from the docs)

The following official sample shows the shape of a typical latest endpoint response. It uses SOFR to illustrate fields; the structure is the same you’ll read for NBS_RATE.

curl -s "https://interestratesapi.com/api/v1/latest?api_key=YOUR_API_KEY&symbols=SOFR"
{
"success": true,
"date": "2026-10-01",
"base": "USD",
"rates": {
"SOFR": 3.87
},
"dates": {
"SOFR": "2026-10-01"
},
"currencies": {
"SOFR": "USD"
},
"base_filter_note": null
}

Interpretation you will reuse for NBS_RATE:

  • date: The server’s canonical date for the batch. For monthly symbols, values remain unchanged through the month until updated.
  • rates: A map from symbol to numeric rate, expressed in percent per annum unless the symbol’s definition specifies otherwise.
  • dates: Effective date per symbol. Always use this when comparing across symbols.
  • currencies: The currency each symbol is associated with.

1) Discover the NBS_RATE symbol with /symbols

Use /symbols to list available identifiers and confirm metadata such as category, currency, and frequency.

cURL

Python (requests)

import requests

resp = requests.get(
"https://interestratesapi.com/api/v1/symbols",
params={"category": "central_bank", "base": "USD", "api_key": "YOUR_KEY"}
)
data = resp.json()
# Filter client-side for NBS_RATE if needed
symbols = [s for s in data.get("symbols", []) if s.get("symbol") == "NBS_RATE"]

JavaScript (fetch)

const url = "https://interestratesapi.com/api/v1/symbols?category=central_bank&base=USD&api_key=YOUR_KEY";
const res = await fetch(url);
const data = await res.json();
// Find NBS_RATE
const nbs = (data.symbols || []).find(s => s.symbol === "NBS_RATE");

PHP

<?php
$url = "https://interestratesapi.com/api/v1/symbols?category=central_bank&base=USD&api_key=YOUR_KEY";
$json = file_get_contents($url);
$data = json_decode($json, true);
$nbs = null;
if (isset($data["symbols"])) {
foreach ($data["symbols"] as $s) {
if ($s["symbol"] === "NBS_RATE") { $nbs = $s; break; }
}
}
?>

Response example

Field notes you will use later:

  • symbol: Use the exact identifier NBS_RATE in subsequent endpoints.
  • frequency: For NBS_RATE this is monthly; downstream logic should not assume daily updates.

Tip: Cache the symbols catalog in your application and refresh periodically (e.g., daily) to minimize latency and rate usage. Use it to validate inputs server-side before routing to /latest or /historical.

2) Retrieve the latest NBS_RATE with /latest

Use /latest to fetch current values. For monthly NBS_RATE, the latest value typically persists until the next policy decision or update.

cURL

Python (requests)

import requests

resp = requests.get(
"https://interestratesapi.com/api/v1/latest",
params={"symbols": "NBS_RATE,ECB_MRO", "api_key": "YOUR_KEY"}
)
data = resp.json()
nbs_rate = data["rates"]["NBS_RATE"]
nbs_effective_date = data["dates"]["NBS_RATE"]
nbs_currency = data["currencies"]["NBS_RATE"]

JavaScript (fetch)

const resp = await fetch(
"https://interestratesapi.com/api/v1/latest?symbols=NBS_RATE,ECB_MRO&api_key=YOUR_KEY"
);
const data = await resp.json();
const nbsRate = data.rates["NBS_RATE"];
const nbsDate = data.dates["NBS_RATE"];
const nbsCcy = data.currencies["NBS_RATE"];

PHP

<?php
$url = "https://interestratesapi.com/api/v1/latest?symbols=NBS_RATE,ECB_MRO&api_key=YOUR_KEY";
$data = json_decode(file_get_contents($url), true);
$nbsRate = $data["rates"]["NBS_RATE"];
$nbsDate = $data["dates"]["NBS_RATE"];
$nbsCcy = $data["currencies"]["NBS_RATE"];
?>

Response example

How to read this:

  • rates.NBS_RATE: Annualized percent value. Treat as a decimal percent (e.g., 5.33% = 0.0533 in formulas).
  • dates.NBS_RATE: Effective date for this observation. For monthly symbols this is the most recent date with data in the period.
  • currencies.NBS_RATE: Currency context for the rate. Always display alongside the rate in UI components.

Caching: For NBS_RATE, a daily cache with a small TTL (e.g., 6–24 hours) is typically safe. If you need near real-time during decision days, shorten TTLs and back off to longer durations off-cycle. Honor 429 headers (X-RateLimit-Remaining, Retry-After) if you encounter throttling.

3) Query a specific month with /historical

Use /historical when you need the rate as of a given date. For monthly symbols, the API returns the value from the last day with data within that month (documented behavior).

cURL

Python (requests)

import requests
from datetime import date

params = {"date": "2025-06-15", "symbols": "NBS_RATE", "api_key": "YOUR_KEY"}
r = requests.get("https://interestratesapi.com/api/v1/historical", params=params)
data = r.json()
value = data["rates"]["NBS_RATE"]
effective_ccy = data["currencies"]["NBS_RATE"]

JavaScript (fetch)

const url = "https://interestratesapi.com/api/v1/historical?date=2025-06-15&symbols=NBS_RATE&api_key=YOUR_KEY";
const res = await fetch(url);
const data = await res.json();
const value = data.rates["NBS_RATE"];
const ccy = data.currencies["NBS_RATE"];

PHP

<?php
$url = "https://interestratesapi.com/api/v1/historical?date=2025-06-15&symbols=NBS_RATE&api_key=YOUR_KEY";
$data = json_decode(file_get_contents($url), true);
$value = $data["rates"]["NBS_RATE"];
$ccy = $data["currencies"]["NBS_RATE"];
?>

Response example

Practical note: When backfilling time series, drive /historical with month-end or a representative mid-month date, knowing the API resolves to the last available day in that month. Always store the symbol’s effective date if you also capture it via /latest or /timeseries.

4) Pull a series with /timeseries

Use /timeseries to extract observations between two dates. For monthly symbols, values may appear repeated across days within a month. Many downstream apps resample these to month-end.

cURL

Python (requests)

import requests
import pandas as pd

params = {
"start": "2025-10-05",
"end": "2026-10-05",
"symbols": "NBS_RATE",
"api_key": "YOUR_KEY"
}
resp = requests.get("https://interestratesapi.com/api/v1/timeseries", params=params)
data = resp.json()
series = data["rates"]["NBS_RATE"] # dict of date -> value
# Optional: convert to a pandas Series
ts = pd.Series(series, name="NBS_RATE").astype(float).sort_index()

JavaScript (fetch)

const url = "https://interestratesapi.com/api/v1/timeseries?start=2025-10-05&end=2026-10-05&symbols=NBS_RATE&api_key=YOUR_KEY";
const res = await fetch(url);
const data = await res.json();
const series = data.rates["NBS_RATE"]; // object: date -> value
// To an array of points:
const points = Object.entries(series).map(([d, v]) => ({ date: d, value: v }));

PHP

<?php
$url = "https://interestratesapi.com/api/v1/timeseries?start=2025-10-05&end=2026-10-05&symbols=NBS_RATE&api_key=YOUR_KEY";
$data = json_decode(file_get_contents($url), true);
$series = $data["rates"]["NBS_RATE"]; // associative array date => value
?>

Response example

Field notes:

  • rates.NBS_RATE: Map of ISO date to numeric percent. For monthly benchmarks you may see a flat line within each month.
  • frequencies.NBS_RATE: Frequency label; your resampling and charting logic can use this.

Storage tip: Persist as a date-indexed series with numeric values in percent. If you compute daily accruals, convert percent to decimal (divide by 100) before compounding.

5) Measure changes with /fluctuation

/fluctuation summarizes the change over a period, giving start and end values, absolute and percentage change, and the high/low within the window. Handy for dashboards or alerts.

cURL

Python (requests)

import requests

payload = {
"start": "2025-10-05",
"end": "2026-10-05",
"symbols": "NBS_RATE",
"api_key": "YOUR_KEY"
}
r = requests.get("https://interestratesapi.com/api/v1/fluctuation", params=payload)
data = r.json()
stats = data["rates"]["NBS_RATE"]
change_pct = stats["change_pct"]

JavaScript (fetch)

const q = "start=2025-10-05&end=2026-10-05&symbols=NBS_RATE&api_key=YOUR_KEY";
const res = await fetch(`https://interestratesapi.com/api/v1/fluctuation?${q}`);
const data = await res.json();
const stats = data.rates["NBS_RATE"];
// stats.change_pct is percent change over the window

PHP

<?php
$url = "https://interestratesapi.com/api/v1/fluctuation?start=2025-10-05&end=2026-10-05&symbols=NBS_RATE&api_key=YOUR_KEY";
$data = json_decode(file_get_contents($url), true);
$stats = $data["rates"]["NBS_RATE"];
$high = $stats["high"];
$low = $stats["low"];
?>

Response example

Usage notes:

  • change_pct is the percentage change from start_value to end_value.
  • high and low are the extremes observed in the window; for monthly symbols, these reflect changes across months.

6) Candles for charting with /ohlc

/ohlc computes open, high, low, close for a period from daily data. Default period is monthly; you may also request weekly or quarterly.

cURL

Python (requests)

import requests

params = {
"symbols": "NBS_RATE",
"period": "monthly",
"start": "2025-10-05",
"end": "2026-10-05",
"api_key": "YOUR_KEY"
}
r = requests.get("https://interestratesapi.com/api/v1/ohlc", params=params)
data = r.json()
candles = data["rates"]["NBS_RATE"]

JavaScript (fetch)

const q = "symbols=NBS_RATE&period=monthly&start=2025-10-05&end=2026-10-05&api_key=YOUR_KEY";
const res = await fetch(`https://interestratesapi.com/api/v1/ohlc?${q}`);
const data = await res.json();
const candles = data.rates["NBS_RATE"];

PHP

<?php
$q = "symbols=NBS_RATE&period=monthly&start=2025-10-05&end=2026-10-05&api_key=YOUR_KEY";
$url = "https://interestratesapi.com/api/v1/ohlc?$q";
$data = json_decode(file_get_contents($url), true);
$candles = $data["rates"]["NBS_RATE"];
?>

Response example

How to use:

  • open/close are the first/last observed values in the aggregation period.
  • high/low reflect extremes seen in the constituent days.
  • data_points counts the number of daily data points used to compute that period’s OHLC.

7) Compare loan costs with /convert

/convert estimates simple loan interest cost at the latest rate of two symbols for a given amount and term. It’s ideal for building rate-spread savings widgets or quick comparisons.

cURL

Python (requests)

import requests

params = {
"from": "NBS_RATE",
"to": "ECB_MRO",
"amount": 100000,
"term_months": 12,
"api_key": "YOUR_KEY"
}
r = requests.get("https://interestratesapi.com/api/v1/convert", params=params)
data = r.json()
spread = data["difference"]["rate_spread"]

JavaScript (fetch)

const res = await fetch(
"https://interestratesapi.com/api/v1/convert?from=NBS_RATE&to=ECB_MRO&amount=100000&term_months=12&api_key=YOUR_KEY"
);
const data = await res.json();
const saved = data.difference.interest_saved;

PHP

<?php
$url = "https://interestratesapi.com/api/v1/convert?from=NBS_RATE&to=ECB_MRO&amount=100000&term_months=12&api_key=YOUR_KEY";
$data = json_decode(file_get_contents($url), true);
$spread = $data["difference"]["rate_spread"];
$saved = $data["difference"]["interest_saved"];
?>

Response example

Interpretation:

  • rate_spread is from.rate − to.rate in percentage points.
  • total_interest and total_payment follow a simple interest model at the latest rate. Use for comparisons; if you need amortized schedules, compute using the returned rates locally.

Reading NBS_RATE correctly: units, dates, and business days

Units: All examples express rates as percent per annum. In formulas, convert to decimals (divide by 100) before computing spreads or payments.

Effective dates: Always reference the dates map (from /latest) or the index returned in /timeseries to know the observation’s effective day. For monthly symbols, the rate remains constant across many days; use month-end or the provided effective date for alignment.

Business days: Central bank rate updates don’t necessarily follow interbank business calendars. Avoid assuming weekday-only updates. Instead, rely on the API’s effective date fields, which already represent the last day with available data for a month when you use /historical.

Caching: For production, cache symbol metadata daily and rate payloads with appropriate TTLs. During rate decision windows, lower TTLs. Respect 429 responses and the X-RateLimit-* headers to manage concurrency in your clients.

Computing spreads and payments from NBS_RATE

  • Rate spread: spread_pp = rate_A − rate_B (percentage points). Convert to decimal if you multiply by principal or term.
  • Simple monthly payment estimate: For a principal P and annual rate r_percent, monthly simple interest is P × (r_percent/100) ÷ 12. Total simple interest over T months is that monthly amount × T. Many consumer loans are amortized; in that case use your amortization formula with r_monthly = r_percent/100/12.
  • Accruals for analytics: For day-count models, compute accrual = notional × (rate_percent/100) × (day_count/period_days). Store the rate’s effective date from the API to align accrual windows precisely.

Error handling, rate limits, and retries

Common error responses share the shape success=false with an error message. Relevant statuses include 401 (missing or invalid api_key), 403 (no active plan), 404 (no symbols matched or no data for the requested range), 422 (validation error), and 429 (quota exhausted). When 429 occurs, use Retry-After and the X-RateLimit-* headers to back off, and consider caching more aggressively.

Validation tips:

  • Use ISO Y-m-d dates for date, start, end across endpoints.
  • Ensure symbols are from the allowed list (e.g., NBS_RATE). Validate client input against /symbols before forwarding.
  • All endpoints are GET. Authentication must be via the api_key query parameter.

Real-world integrations for NBS_RATE

  • Interest rate dashboards: Combine /latest and /ohlc to render current values with monthly candles for policy history.
  • Lending and mortgage platforms: Use /latest for current policy inputs and /convert to show impact relative to alternative benchmarks. For amortized loan pricing, fetch the latest rate and run your own schedule.
  • Macro research: Pull multi-year monthly sequences from /timeseries and summarize drifts with /fluctuation for reports.
  • Risk models: Cache /symbols for metadata and run nightly /timeseries updates to refresh factor sets and scenario inputs.

Explore more at interestratesapi.com and the Interest Rates API MCP.

Copy-paste quickstart for NBS_RATE

One-line cURL

Python single call

import requests
resp = requests.get(
"https://interestratesapi.com/api/v1/latest",
params={"symbols": "NBS_RATE", "api_key": "YOUR_KEY"}
)
j = resp.json()
print(j["rates"]["NBS_RATE"], j["dates"]["NBS_RATE"], j["currencies"]["NBS_RATE"])

JavaScript single call

const res = await fetch("https://interestratesapi.com/api/v1/latest?symbols=NBS_RATE&api_key=YOUR_KEY");
const j = await res.json();
console.log(j.rates.NBS_RATE, j.dates.NBS_RATE, j.currencies.NBS_RATE);

PHP single call

<?php
$j = json_decode(file_get_contents("https://interestratesapi.com/api/v1/latest?symbols=NBS_RATE&api_key=YOUR_KEY"), true);
echo $j["rates"]["NBS_RATE"]." ".$j["dates"]["NBS_RATE"]." ".$j["currencies"]["NBS_RATE"];
?>

Troubleshooting checklist

  • Authentication: Ensure the api_key is appended as a query parameter in every call.
  • Date ranges: If /historical or /timeseries returns 404, verify your dates and symbol. For monthly symbols, prefer month-end anchors.
  • Comparisons: Always use the dates map to align effective dates across symbols.
  • Caching: Avoid hammering /latest for monthly symbols—cache during quiet periods and shorten TTLs during expected policy windows.

FAQ

Q: What does the NBS_RATE value represent in calculations?
A: It’s an annualized percentage. Convert to a decimal (divide by 100) before computing accruals, spreads, or monthly payments.

Q: How often does NBS_RATE update?
A: It’s a monthly-frequency central bank benchmark. The API resolves date-specific requests to the last day with data in that month. Use the effective date field to align observations.

Q: How should I handle missing days in /timeseries for a monthly symbol?
A: You may see repeated values across days or fewer daily points. For analytics, resample to month-end or use /ohlc with period=monthly.

Q: Can I compare NBS_RATE to another policy rate directly?
A: Yes. Use /latest with multiple symbols and check dates per symbol. For a quick cost comparison on a principal and term, use /convert and read difference.rate_spread and interest_saved.

Q: What’s the best way to cache?
A: Cache /symbols daily. For NBS_RATE, a 6–24 hour TTL on /latest is typical, shortened on policy decision days. Respect 429 Retry-After and rate limit headers.

Run your first request now and integrate NBS_RATE across your pricing, dashboards, and research flows. Get an API key: Register. Browse the API model catalog and docs here: MCP.

Ready to get started?

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

Get API Key

Related posts