In Finance, precision and timeliness of interest rate data directly impact pricing, risk, liquidity planning, and compliance reporting. If your team prices floating-rate loans, builds hedging dashboards, powers yield analytics, or runs stress tests for South African exposures, the 3‑Month Johannesburg Interbank Average Rate (JIBAR_3M) is a foundational benchmark. Developers, economists, and quantitative analysts often struggle with fragmented data sources, inconsistent time series frequencies, sparse metadata, and brittle ad‑hoc scrapers. With interestratesapi.com, you can programmatically query JIBAR_3M alongside other policy, interbank, treasury, and reference benchmarks through a unified, well-documented interface, and ship production-grade analytics fast.
This article is a comprehensive, technically focused guide to retrieving, analyzing, and visualizing JIBAR_3M historical data with interestratesapi.com. We will emphasize long-horizon fetches using the /timeseries endpoint, point‑in‑time lookups with /historical, candlestick visualization using /ohlc, and production data pipelines using Python, pandas, and file exports. You will see realistic JSON responses, code examples in cURL, Python, JavaScript, and PHP, and best practices to avoid common data pitfalls such as missing dates and frequency mismatches. If you are building pricing engines, research notebooks, or ETL pipelines, this guide is designed to make you productive immediately.
To explore the platform and test live endpoints, you can visit the following links:
Explore Interest Rates API features
Get started with Interest Rates API
Why JIBAR_3M matters and the business challenges it solves
JIBAR_3M, the 3‑month Johannesburg Interbank Average Rate, is widely used as a reference in South African floating‑rate instruments, including corporate loans, securitizations, and derivatives. The benchmark serves as a proxy for unsecured ZAR interbank funding costs over a three‑month tenor. For any financial institution or fintech pricing products or valuing exposures in ZAR, accurate JIBAR_3M data is non‑negotiable. You need:
- Fast programmatic access to the latest JIBAR_3M for operational dashboards and pricing workflows.
- Clean historical time series for factor modeling, back‑tests, and econometric research.
- Derived analytics like high/low ranges, cumulative changes, and OHLC aggregates for visualization and signals.
- Data that integrates smoothly into ETL processes and time series stores with reliable field names and predictable response shapes.
Without a robust API, teams face brittle scrapers that break when websites change, manual CSV updates that delay analytics, inconsistent date formats, and frequency mismatches that require excessive cleansing. interestratesapi.com offers a consistent, well-structured interface so you can focus on modeling and product delivery, not on hygiene tasks or integration overhead.
Endpoint overview: the complete toolkit for JIBAR_3M analytics
interestratesapi.com provides a cohesive set of endpoints at the base URL https://interestratesapi.com/api/v1/ that work together to support both real‑time and historical Finance use cases:
- /symbols — Discover available rate symbols, filterable by category and currency.
- /latest — Fetch the most recent values and dates for one or more symbols.
- /historical — Retrieve rate values on a specific date (with sensible handling for monthly data).
- /timeseries — Pull continuous time series between start and end dates for multi‑year back‑tests and trend analysis.
- /fluctuation — Get summary change statistics (start/end values, absolute and percentage change, high/low).
- /ohlc — Compute OHLC aggregates (weekly|monthly|quarterly) for charting and technical visualization.
- /convert — Compare simple loan interest costs using the latest rates of two symbols for “what‑if” comparisons.
Each endpoint uses the GET method and accepts parameters via the query string. In the sections that follow, we will detail usage patterns, provide complete code examples, and walk through field‑level interpretations so you can deploy robust Finance analytics around JIBAR_3M at scale.
JIBAR_3M frequency and time series design: daily vs monthly and why it matters
For robust Finance pipelines, understanding data frequency is essential. JIBAR_3M is an interbank benchmark with monthly frequency in this dataset. That has implications for:
- Point‑in‑time lookups: if you request a mid‑month date, the API returns the applicable monthly value (using the last available day within that month).
- Time series intervals: you will see monthly timestamps rather than dense daily points. This simplifies storage and transforms (e.g., resampling, alignment with monthly macro factors), but requires careful merging if you pair JIBAR_3M with a daily series.
- OHLC aggregations: monthly OHLC is the natural default; it compresses within‑period movements using open/high/low/close. For monthly data, OHLC often reduces to an open/close at monthly boundaries with intra‑month variation dependent on the underlying data generation logic.
Practical advice for developers:
- Align series by frequency before performing regressions or correlations. If your macro factors are daily but JIBAR_3M is monthly, downsample or upsample consistently with domain‑appropriate fill rules (e.g., forward‑fill within a month for attribution dashboards, or use end‑of‑month alignment for valuations).
- When combining multiple interbank series, check each symbol’s frequency metadata. The /timeseries and /latest endpoints include helpful fields like frequencies and currencies to drive automated validation.
- When storing in data warehouses, persist frequency metadata in schema fields to avoid subtle modeling errors later.
Deep dive: /timeseries for JIBAR_3M multi‑year back‑tests and trend analysis
The /timeseries endpoint is the workhorse for quant analytics, historical risk, and research notebooks. For JIBAR_3M, you typically query multi‑year spans to observe regime shifts, central bank cycles, and interbank liquidity patterns that drive repricing. The endpoint supports:
- Explicit start and end dates (Y‑m‑d) that bound your analysis window.
- One or multiple symbols (comma‑separated) so you can co‑load comparator benchmarks like EURIBOR_3M or ECB_MRO for cross‑market context.
- A response that returns per‑symbol series keyed by ISO date strings, plus helpful metadata: base, start_date, end_date, frequencies, and currencies.
Below is a realistic timeseries request for JIBAR_3M over a multi‑year horizon and the typical JSON you can expect. Note that JIBAR_3M is monthly in this dataset; dates shown will correspond to the end of month or the last day with data in that month.
curl "https://interestratesapi.com/api/v1/timeseries?start=2023-01-01&end=2026-09-20&symbols=JIBAR_3M&api_key=YOUR_KEY"
{
"success": true,
"base": "ZAR",
"start_date": "2023-01-01",
"end_date": "2026-09-20",
"rates": {
"JIBAR_3M": {
"2023-01-31": 7.25,
"2023-02-28": 7.33,
"2023-03-31": 7.58,
"2023-04-28": 7.75,
"2023-05-31": 7.92,
"2023-06-30": 8.08,
"2023-07-31": 8.25,
"2023-08-31": 8.33,
"2023-09-29": 8.42,
"2023-10-31": 8.50,
"2023-11-30": 8.58,
"2023-12-29": 8.67,
"2024-01-31": 8.67,
"2024-02-29": 8.67,
"2024-03-28": 8.58,
"2024-04-30": 8.50,
"2024-05-31": 8.50,
"2024-06-28": 8.42,
"2024-07-31": 8.33,
"2024-08-30": 8.25,
"2024-09-20": 8.17
}
},
"frequencies": {
"JIBAR_3M": "monthly"
},
"currencies": {
"JIBAR_3M": "ZAR"
}
}
Field interpretations and practical uses:
- success: Boolean indicator that the request succeeded. Always check before processing.
- base: The primary currency context inferred for the response; helpful when mixing symbols.
- start_date and end_date: Echo the query bounds; useful for logging and ETL lineage.
- rates: The main payload. For each symbol, a date‑keyed object of rate values. For monthly series like JIBAR_3M, expect one entry per month.
- frequencies: Declares each symbol’s frequency (monthly here), enabling automated resampling logic in your code.
- currencies: Provides per‑symbol currency code (ZAR for JIBAR_3M), supporting schema validation and currency tagging.
Common strategies:
- Stitching multi‑window pulls: For very long histories, batch requests by year or quarter to control payload size and enable checkpointing. Keep the same symbol list to simplify concatenation.
- Join with policy rates: Combine JIBAR_3M with SARB_REPO_RATE to study pass‑through and lag effects in ZAR money markets, using aligned monthly timestamps.
- Engineering features: Compute month‑over‑month deltas, moving averages, and volatility measures directly from the timeseries payload before feeding modeling pipelines.
Complete code examples for /timeseries:
# cURL
curl "https://interestratesapi.com/api/v1/timeseries?start=2023-01-01&end=2026-09-20&symbols=JIBAR_3M&api_key=YOUR_KEY"
# Python (requests)
import requests
resp = requests.get(
'https://interestratesapi.com/api/v1/timeseries',
params=dict(start='2023-01-01', end='2026-09-20', symbols='JIBAR_3M', api_key='YOUR_KEY')
)
data = resp.json()
if not data.get('success'):
raise RuntimeError(f"Timeseries failed: {data}")
series = data['rates']['JIBAR_3M']
freq = data['frequencies']['JIBAR_3M']
currency = data['currencies']['JIBAR_3M']
// JavaScript (fetch)
const response = await fetch(
'https://interestratesapi.com/api/v1/timeseries?start=2023-01-01&end=2026-09-20&symbols=JIBAR_3M&api_key=YOUR_KEY'
);
const data = await response.json();
if (!data.success) throw new Error('Timeseries request failed');
const series = data.rates.JIBAR_3M;
const freq = data.frequencies.JIBAR_3M;
const currency = data.currencies.JIBAR_3M;
<?php
// PHP
$url = 'https://interestratesapi.com/api/v1/timeseries?start=2023-01-01&end=2026-09-20&symbols=JIBAR_3M&api_key=YOUR_KEY';
$resp = file_get_contents($url);
$data = json_decode($resp, true);
if (!$data['success']) {
throw new Exception('Timeseries request failed: ' . $resp);
}
$series = $data['rates']['JIBAR_3M'];
$freq = $data['frequencies']['JIBAR_3M'];
$currency = $data['currencies']['JIBAR_3M'];
?>
Point‑in‑time lookups with /historical: weekends, holidays, and monthly alignment
Researchers frequently need to snapshot JIBAR_3M on a specific date to anchor back‑tests, align to transaction dates, or build as‑of reporting. The /historical endpoint returns the value on the requested date. For monthly series like JIBAR_3M, the API uses the last day with data within that month. This design gracefully handles weekends, holidays, and sparse calendars without you having to implement complex lookup rules.
Example: Get JIBAR_3M for 2025‑06‑15 (a mid‑month date). The API returns the monthly value consistent with that month’s last available observation.
curl "https://interestratesapi.com/api/v1/historical?date=2025-06-15&symbols=JIBAR_3M&api_key=YOUR_KEY"
{
"success": true,
"date": "2025-06-15",
"base": "ZAR",
"rates": {
"JIBAR_3M": 8.42
},
"currencies": {
"JIBAR_3M": "ZAR"
}
}
Field interpretations:
- date: The requested date (not necessarily the exact observation date for monthly series, but the request anchor).
- rates.JIBAR_3M: The value applicable for that date, using the last day with data within that month (e.g., month‑end).
- currencies: ZAR for JIBAR_3M, enabling invariant schema tagging downstream.
Best practices:
- When storing point‑in‑time snapshots, also store the request date and the month anchor, so reconciling later to end‑of‑month data is straightforward.
- For GUI widgets, annotate that monthly symbols return month‑aligned values for mid‑month requests to avoid user confusion.
- Use /historical for user‑provided dates; fall back to /timeseries for bulk retrievals and analytics.
Code examples for /historical:
# cURL
curl "https://interestratesapi.com/api/v1/historical?date=2025-06-15&symbols=JIBAR_3M&api_key=YOUR_KEY"
# Python
import requests
resp = requests.get(
'https://interestratesapi.com/api/v1/historical',
params=dict(date='2025-06-15', symbols='JIBAR_3M', api_key='YOUR_KEY')
)
data = resp.json()
if not data.get('success'):
raise RuntimeError(data)
// JavaScript
const response = await fetch(
'https://interestratesapi.com/api/v1/historical?date=2025-06-15&symbols=JIBAR_3M&api_key=YOUR_KEY'
);
const data = await response.json();
if (!data.success) throw new Error('Historical failed');
<?php
$url = 'https://interestratesapi.com/api/v1/historical?date=2025-06-15&symbols=JIBAR_3M&api_key=YOUR_KEY';
$data = json_decode(file_get_contents($url), true);
if (!$data['success']) {
throw new Exception('Historical failed');
}
?>
From raw series to charts: /ohlc for candlesticks, plus a Chart.js example
Candlesticks convey at‑a‑glance variability, momentum, and turning points. The /ohlc endpoint computes OHLC aggregates from underlying daily data. For monthly symbols, monthly OHLC typically reflects summary dynamics within each month if there are multiple observations; where data is strictly monthly as a single observation, OHLC will converge to open=high=low=close. It is still a stable structure for plotting consistent multi‑symbol dashboards.
Example request for JIBAR_3M OHLC over multiple years:
curl "https://interestratesapi.com/api/v1/ohlc?symbols=JIBAR_3M&period=monthly&start=2023-01-01&end=2026-09-20&api_key=YOUR_KEY"
{
"success": true,
"period": "monthly",
"start_date": "2023-01-01",
"end_date": "2026-09-20",
"rates": {
"JIBAR_3M": [
{
"period": "2023-01",
"open": 7.25,
"high": 7.33,
"low": 7.25,
"close": 7.33,
"data_points": 2
},
{
"period": "2023-02",
"open": 7.33,
"high": 7.58,
"low": 7.33,
"close": 7.58,
"data_points": 2
},
{
"period": "2023-03",
"open": 7.58,
"high": 7.75,
"low": 7.58,
"close": 7.75,
"data_points": 2
}
]
}
}
Field interpretations:
- period: The aggregation frequency (monthly by default), driving chart axis tick logic.
- open/high/low/close: Aggregates computed from underlying observations within the aggregation window.
- data_points: Count of observations contributing to the OHLC calculation. For strictly monthly values, this may be 1.
Chart.js integration snippet for candlestick visualization. This example assumes you have the JSON above already available as ohlcData and uses a simple mapper to Chart.js Financial Chart (requires a plugin like chartjs-chart-financial).
<canvas id="jibarChart" width="900" height="400"></canvas>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-chart-financial"></script>
<script>
// Suppose you fetched OHLC via fetch() and parsed JSON as 'ohlc'
const ohlc = {
success: true,
period: "monthly",
start_date: "2023-01-01",
end_date: "2026-09-20",
rates: {
JIBAR_3M: [
{ period: "2023-01", open: 7.25, high: 7.33, low: 7.25, close: 7.33, data_points: 2 },
{ period: "2023-02", open: 7.33, high: 7.58, low: 7.33, close: 7.58, data_points: 2 },
{ period: "2023-03", open: 7.58, high: 7.75, low: 7.58, close: 7.75, data_points: 2 }
]
}
};
const rows = ohlc.rates['JIBAR_3M'].map(r => ({
x: r.period + '-01',
o: r.open,
h: r.high,
l: r.low,
c: r.close
}));
const ctx = document.getElementById('jibarChart').getContext('2d');
new Chart(ctx, {
type: 'candlestick',
data: {
datasets: [{
label: 'JIBAR 3M OHLC',
data: rows,
borderColor: 'rgba(24, 120, 240, 1)',
color: {
up: 'rgba(5, 155, 105, 0.8)',
down: 'rgba(220, 86, 86, 0.8)',
unchanged: 'rgba(120, 120, 120, 0.8)'
}
}]
},
options: {
parsing: false,
scales: {
x: {
type: 'time',
time: { unit: 'month', tooltipFormat: 'yyyy-MM' }
},
y: { title: { display: true, text: 'Rate (%)' } }
}
}
});
</script>
Alternatively, Plotly provides a native candlestick trace. You can translate the same OHLC JSON payload into Plotly’s candlestick constructor for rapid prototyping of financial dashboards.
Monitoring the now: /latest for dashboards and alerting
The /latest endpoint serves operational dashboards, pricing engines, and alerting systems that need the most recent published JIBAR_3M value and date. Combine it with comparator symbols to render spreads or parity checks. Below we request JIBAR_3M and ECB_MRO to build a quick reference panel and spread chart.
curl "https://interestratesapi.com/api/v1/latest?symbols=JIBAR_3M,ECB_MRO&api_key=YOUR_KEY"
{
"success": true,
"date": "2026-09-20",
"base": "MIXED",
"rates": {
"JIBAR_3M": 8.17,
"ECB_MRO": 4.50
},
"dates": {
"JIBAR_3M": "2026-09-20",
"ECB_MRO": "2026-09-20"
},
"currencies": {
"JIBAR_3M": "ZAR",
"ECB_MRO": "EUR"
}
}
Key fields:
- rates: Current values per symbol at the time of query.
- dates: Per‑symbol effective date; helpful when mixed symbols have different refresh cadences.
- currencies: Use to label UI components and prevent currency mismatches in calculations.
Code examples for /latest:
# cURL
curl "https://interestratesapi.com/api/v1/latest?symbols=JIBAR_3M,ECB_MRO&api_key=YOUR_KEY"
# Python
import requests
resp = requests.get(
'https://interestratesapi.com/api/v1/latest',
params=dict(symbols='JIBAR_3M,ECB_MRO', api_key='YOUR_KEY')
)
data = resp.json()
assert data['success']
// JavaScript
const r = await fetch('https://interestratesapi.com/api/v1/latest?symbols=JIBAR_3M,ECB_MRO&api_key=YOUR_KEY');
const json = await r.json();
if (!json.success) throw new Error('Latest failed');
<?php
$url = 'https://interestratesapi.com/api/v1/latest?symbols=JIBAR_3M,ECB_MRO&api_key=YOUR_KEY';
$data = json_decode(file_get_contents($url), true);
if (!$data['success']) { throw new Exception('Latest failed'); }
?>
Range statistics at a glance: /fluctuation for change, pct‑change, high, low
For dashboards and research memos, you often need compact statistics describing how JIBAR_3M evolved over a period. The /fluctuation endpoint returns start/end values, absolute and percentage changes, and extrema over a user‑specified date range. This eliminates custom SQL and ad‑hoc calculations, standardizing results across applications.
curl "https://interestratesapi.com/api/v1/fluctuation?start=2025-09-20&end=2026-09-20&symbols=JIBAR_3M&api_key=YOUR_KEY"
{
"success": true,
"rates": {
"JIBAR_3M": {
"start_date": "2025-09-20",
"end_date": "2026-09-20",
"start_value": 8.50,
"end_value": 8.17,
"change": -0.33,
"change_pct": -3.88,
"high": 8.50,
"low": 8.17
}
}
}
Use cases:
- Monthly performance summaries in BI tools.
- Alert thresholds (e.g., trigger when change_pct exceeds predefined risk limits).
- Investment memos comparing policy and interbank dynamics over specific windows.
Code examples for /fluctuation:
# cURL
curl "https://interestratesapi.com/api/v1/fluctuation?start=2025-09-20&end=2026-09-20&symbols=JIBAR_3M&api_key=YOUR_KEY"
# Python
import requests
resp = requests.get(
'https://interestratesapi.com/api/v1/fluctuation',
params=dict(start='2025-09-20', end='2026-09-20', symbols='JIBAR_3M', api_key='YOUR_KEY')
)
stats = resp.json()
if not stats['success']: raise RuntimeError(stats)
// JavaScript
const r = await fetch('https://interestratesapi.com/api/v1/fluctuation?start=2025-09-20&end=2026-09-20&symbols=JIBAR_3M&api_key=YOUR_KEY');
const s = await r.json();
if (!s.success) throw new Error('Fluctuation failed');
<?php
$url = 'https://interestratesapi.com/api/v1/fluctuation?start=2025-09-20&end=2026-09-20&symbols=JIBAR_3M&api_key=YOUR_KEY';
$data = json_decode(file_get_contents($url), true);
if (!$data['success']) { throw new Exception('Fluctuation failed'); }
?>
Symbol discovery with /symbols: building robust, configurable apps
Configurable applications need discoverability. The /symbols endpoint enumerates all available identifiers, filterable by base currency, category, and provider. Use it to populate dropdowns, validate configs, or drive automated onboarding flows. For interbank series in ZAR, you can filter by category=interbank and base=ZAR to confirm JIBAR_3M availability.
curl "https://interestratesapi.com/api/v1/symbols?category=interbank&base=ZAR&api_key=YOUR_KEY"
{
"success": true,
"count": 2,
"symbols": [
{
"symbol": "JIBAR_3M",
"name": "Johannesburg Interbank Average Rate - 3 Month",
"category": "interbank",
"country_code": "ZA",
"currency_code": "ZAR",
"frequency": "monthly",
"description": "South Africa 3-month interbank rate benchmark (JIBAR)"
},
{
"symbol": "JIBOR_3M",
"name": "Jakarta Interbank Offered Rate - 3 Month",
"category": "interbank",
"country_code": "ID",
"currency_code": "IDR",
"frequency": "daily",
"description": "Indonesia 3-month interbank offered rate"
}
]
}
Notes:
- frequency: Use it to enforce model constraints and automated up/down‑sampling.
- description and name: Power contextual tooltips and documentation panels in your apps.
- count: Useful for pagination or UI messaging.
Code examples for /symbols:
# cURL
curl "https://interestratesapi.com/api/v1/symbols?category=interbank&base=ZAR&api_key=YOUR_KEY"
# Python
import requests
resp = requests.get('https://interestratesapi.com/api/v1/symbols', params=dict(category='interbank', base='ZAR', api_key='YOUR_KEY'))
symbols = resp.json()
// JavaScript
const resp = await fetch('https://interestratesapi.com/api/v1/symbols?category=interbank&base=ZAR&api_key=YOUR_KEY');
const symbols = await resp.json();
<?php
$url = 'https://interestratesapi.com/api/v1/symbols?category=interbank&base=ZAR&api_key=YOUR_KEY';
$data = json_decode(file_get_contents($url), true);
?>
“Which loan is cheaper?” /convert for quick interest‑cost comparisons
In underwriting, treasury, and portfolio strategy, quick “what‑if” comparisons clarify cost differentials. The /convert endpoint compares the total simple interest cost of a loan priced at the latest rate of two symbols over a given term. For example, compare a JIBAR_3M‑linked simple loan to one priced off ECB_MRO for a standard notional and term. While this is a simplification (production loans include margins, compounding rules, day counts), it offers fast intuition and communication value.
curl "https://interestratesapi.com/api/v1/convert?from=JIBAR_3M&to=ECB_MRO&amount=1000000&term_months=12&api_key=YOUR_KEY"
{
"success": true,
"amount": 1000000,
"term_months": 12,
"from": {
"symbol": "JIBAR_3M",
"rate": 8.17,
"date": "2026-09-20",
"total_interest": 81700.00,
"total_payment": 1081700.00
},
"to": {
"symbol": "ECB_MRO",
"rate": 4.50,
"date": "2026-09-20",
"total_interest": 45000.00,
"total_payment": 1045000.00
},
"difference": {
"rate_spread": 3.67,
"interest_saved": 36700.00
}
}
Operational uses:
- Pre‑deal memos to compare baseline funding levels across markets.
- Customer education tools explaining how benchmark differences impact cost.
- Internal pricing sandbox to test sensitivity to benchmark shifts.
Code examples for /convert:
# cURL
curl "https://interestratesapi.com/api/v1/convert?from=JIBAR_3M&to=ECB_MRO&amount=1000000&term_months=12&api_key=YOUR_KEY"
# Python
import requests
r = requests.get('https://interestratesapi.com/api/v1/convert', params=dict(
from='JIBAR_3M', to='ECB_MRO', amount=1000000, term_months=12, api_key='YOUR_KEY'
))
data = r.json()
assert data['success']
// JavaScript
const r = await fetch('https://interestratesapi.com/api/v1/convert?from=JIBAR_3M&to=ECB_MRO&amount=1000000&term_months=12&api_key=YOUR_KEY');
const conv = await r.json();
<?php
$url = 'https://interestratesapi.com/api/v1/convert?from=JIBAR_3M&to=ECB_MRO&amount=1000000&term_months=12&api_key=YOUR_KEY';
$conv = json_decode(file_get_contents($url), true);
?>
Production pipeline: Python + pandas ETL for JIBAR_3M to CSV and Parquet
Let’s build a minimal, production‑friendly ETL pipeline to ingest JIBAR_3M time series, audit the payload, and write to CSV and Parquet for downstream analytics. The same pattern can be extended to other symbols or joined with policy and treasury data.
# Python 3.x
# Dependencies: requests, pandas, pyarrow (for Parquet)
import os
import sys
import json
import time
import pandas as pd
import requests
API_BASE = 'https://interestratesapi.com/api/v1/'
API_KEY = os.getenv('IR_API_KEY', 'YOUR_KEY')
def fetch_timeseries(symbol: str, start: str, end: str) -> dict:
url = f"{API_BASE}timeseries"
params = dict(start=start, end=end, symbols=symbol, api_key=API_KEY)
r = requests.get(url, params=params, timeout=30)
data = r.json()
if not data.get('success'):
raise RuntimeError(f"Timeseries error: {json.dumps(data)}")
return data
def to_dataframe(timeseries: dict, symbol: str) -> pd.DataFrame:
series = timeseries['rates'][symbol]
freq = timeseries['frequencies'][symbol]
ccy = timeseries['currencies'][symbol]
# Convert dict to DataFrame
df = pd.DataFrame(list(series.items()), columns=['date', 'value'])
# Ensure datetime and sorting
df['date'] = pd.to_datetime(df['date'], format='%Y-%m-%d', utc=False)
df = df.sort_values('date').reset_index(drop=True)
# Add metadata columns for lineage
df['symbol'] = symbol
df['frequency'] = freq
df['currency'] = ccy
return df
def validate_monotonic(df: pd.DataFrame):
if not df['date'].is_monotonic_increasing:
raise ValueError("Dates are not monotonically increasing")
if df['date'].duplicated().any():
raise ValueError("Duplicate date entries detected")
def export_files(df: pd.DataFrame, out_dir: str):
os.makedirs(out_dir, exist_ok=True)
csv_path = os.path.join(out_dir, 'JIBAR_3M_timeseries.csv')
pq_path = os.path.join(out_dir, 'JIBAR_3M_timeseries.parquet')
df.to_csv(csv_path, index=False)
try:
df.to_parquet(pq_path, index=False)
except Exception as e:
print(f"Parquet export failed (install pyarrow): {e}", file=sys.stderr)
return csv_path, pq_path
def main():
symbol = 'JIBAR_3M'
start = '2018-01-01'
end = '2026-09-20'
data = fetch_timeseries(symbol, start, end)
df = to_dataframe(data, symbol)
validate_monotonic(df)
# Example feature engineering
df['mom_change'] = df['value'].diff()
df['mom_pct'] = df['value'].pct_change() * 100
# Persist
out_dir = './export'
csv_path, pq_path = export_files(df, out_dir)
print(f"Exported: {csv_path}")
print(f"Exported: {pq_path}")
# Basic audit
print("Head:")
print(df.head(5))
print("Tail:")
print(df.tail(5))
if __name__ == '__main__':
main()
Notes for production hardening:
- Parameterize dates via environment variables or CLI arguments for scheduling flexibility.
- Persist the response’s start_date/end_date to a metadata table for reproducibility.
- Log “frequencies” and “currencies” fields to catch accidental symbol swaps in CI/CD.
- Implement retry logic for transient network errors and validate JSON schema before writes.
Handling missing dates, frequency mismatches, and interpreting data_points
Financial time series often have sparse dates, holidays, and shifting publication schedules. With JIBAR_3M being monthly, holes are rarer, but careful practices still improve quality:
- Missing dates: For monthly series, a missing month signals upstream publication issues or a gap in the historical feed. Ingest pipelines should detect month‑over‑month continuity and alert if a month is skipped unexpectedly.
- Frequency mismatches: When combining JIBAR_3M (monthly) with daily series like SOFR or US_TREASURY_10Y, explicitly resample one series to the other’s frequency. For dashboards, forward‑filling the monthly value across the month is common; for econometric models, end‑of‑month alignment is often preferred.
- OHLC data_points: This field tells you how many underlying observations were aggregated within the period. It is useful for quality checks, e.g., to detect whether monthly OHLC was computed from multiple intra‑month values or a single observation.
- Outlier detection: Compute z‑scores on monthly changes and flag points beyond a threshold to catch potential data anomalies quickly.
Practical tips:
- Always check the “frequencies” metadata in /timeseries responses; never assume daily granularity.
- Document and test your resampling and fill policy; hidden forward‑fills can skew volatility or correlation estimates.
- Separate ingestion from transformation: write raw JSON or normalized frames to a bronze layer, then transform to silver/gold with explicit policies.
End‑to‑end examples: complete JSON responses and how to interpret them
Below are additional complete JSON payloads across endpoints, annotated with practical takeaways for JIBAR_3M pipelines. These reinforce what fields matter most for production systems.
Example 1: Latest with multiple symbols, validating mixed currencies (ZAR vs EUR) before spread calculations.
{
"success": true,
"date": "2026-09-20",
"base": "MIXED",
"rates": {
"JIBAR_3M": 8.17,
"ECB_MRO": 4.50
},
"dates": {
"JIBAR_3M": "2026-09-20",
"ECB_MRO": "2026-09-20"
},
"currencies": {
"JIBAR_3M": "ZAR",
"ECB_MRO": "EUR"
}
}
Takeaway: Check currencies.currencies before computing spreads; label axes and units accurately.
Example 2: Historical on a mid‑month date, confirming the monthly anchor behavior.
{
"success": true,
"date": "2025-02-14",
"base": "ZAR",
"rates": {
"JIBAR_3M": 8.67
},
"currencies": {
"JIBAR_3M": "ZAR"
}
}
Takeaway: Use this endpoint for as‑of checks. In monthly datasets, values represent the month’s applicable level.
Example 3: Timeseries with monthly cadence across years for JIBAR_3M, ideal for regressions and rolling volatilities.
{
"success": true,
"base": "ZAR",
"start_date": "2021-01-01",
"end_date": "2026-09-20",
"rates": {
"JIBAR_3M": {
"2021-01-29": 4.10,
"2021-02-26": 4.10,
"2021-03-31": 4.10,
"2021-04-30": 4.10,
"2021-05-31": 4.10,
"2021-06-30": 4.10,
"2021-07-30": 4.10,
"2021-08-31": 4.10,
"2021-09-30": 4.10,
"2021-10-29": 4.25,
"2021-11-30": 4.42,
"2021-12-31": 4.58,
"2022-01-31": 4.75,
"2022-02-28": 4.92,
"2022-03-31": 5.25,
"2022-04-29": 5.58,
"2022-05-31": 5.92,
"2022-06-30": 6.25,
"2022-07-29": 6.58,
"2022-08-31": 6.92,
"2022-09-30": 7.25,
"2022-10-31": 7.42,
"2022-11-30": 7.58,
"2022-12-30": 7.75
}
},
"frequencies": {
"JIBAR_3M": "monthly"
},
"currencies": {
"JIBAR_3M": "ZAR"
}
}
Takeaway: Expect one row per month. Join this to monthly CPI, policy rates, or banking system liquidity measures without resampling.
Example 4: OHLC monthly aggregates across consecutive months, providing a stable structure for candlestick charts even when variability is modest.
{
"success": true,
"period": "monthly",
"start_date": "2024-01-01",
"end_date": "2024-06-30",
"rates": {
"JIBAR_3M": [
{ "period": "2024-01", "open": 8.67, "high": 8.67, "low": 8.67, "close": 8.67, "data_points": 1 },
{ "period": "2024-02", "open": 8.67, "high": 8.67, "low": 8.67, "close": 8.67, "data_points": 1 },
{ "period": "2024-03", "open": 8.67, "high": 8.58, "low": 8.58, "close": 8.58, "data_points": 1 },
{ "period": "2024-04", "open": 8.58, "high": 8.50, "low": 8.50, "close": 8.50, "data_points": 1 },
{ "period": "2024-05", "open": 8.50, "high": 8.50, "low": 8.50, "close": 8.50, "data_points": 1 },
{ "period": "2024-06", "open": 8.50, "high": 8.42, "low": 8.42, "close": 8.42, "data_points": 1 }
]
}
}
Takeaway: data_points aids diagnostics. Even when each month collapses to one observation, candlestick structures render reliably across symbols.
Implementation guidance and performance tips per endpoint
/symbols:
- Purpose: Discover symbols to build dynamic UIs and configuration forms.
- Parameters: Filter by category=interbank and base=ZAR to surface JIBAR_3M.
- Business value: Reduce runtime errors by validating user inputs against a known catalog.
- Tip: Cache symbol lists locally and refresh daily to minimize repetitive metadata fetches.
/latest:
- Purpose: Keep dashboards current and support near‑term decisioning.
- Parameters: Provide multiple symbols to minimize round‑trips and enable spread visualizations.
- Business value: Reduce manual data checks; unify currency and date handling in one response.
- Tip: Store “dates” per symbol in your DB to audit when a benchmark last refreshed.
/historical:
- Purpose: Point‑in‑time retrievals aligned to requested dates.
- Parameters: date (Y‑m‑d), supports mid‑month requests for monthly data via last‑available logic.
- Business value: Eliminates custom calendar logic in applications.
- Tip: For audit trails, persist the user’s “requested date” and the “returned monthly anchor” (inferred from the month of the returned value).
/timeseries:
- Purpose: Long‑horizon research, back‑testing, and analytics.
- Parameters: start, end, symbols. For JIBAR_3M, expect monthly frequency.
- Business value: Enables econometric and ML workflows without scraping or manual updates.
- Tip: Partition large fetches by year or quarter and checkpoint to object storage for robust recovery.
/fluctuation:
- Purpose: Summary change metrics for dashboards and alerts.
- Parameters: start, end, symbols; returns change, change_pct, high, low.
- Business value: Provide stakeholders with digestible summaries for reporting and governance.
- Tip: Use change_pct to normalize across regimes; present both absolute and percentage changes in BI cards.
/ohlc:
- Purpose: Candlestick-ready summaries for charting libraries.
- Parameters: symbols, period (monthly default), optional date bounds.
- Business value: Visual signals and quick diagnostics for non‑technical stakeholders.
- Tip: Utilize data_points to annotate chart tooltips with the strength of underlying observations.
/convert:
- Purpose: Fast “what‑if” cost comparisons for loans priced off two different benchmarks.
- Parameters: from, to, amount, term_months.
- Business value: Instant intuition for pricing and education without complex amortization logic.
- Tip: Pair with /latest to show recent changes and highlight sensitivity to benchmark shifts.
Comprehensive code samples: cURL, Python, JavaScript, PHP for all endpoints
This consolidated section provides callable, copy‑pasteable examples to accelerate integration into your Finance stack.
Symbols:
curl "https://interestratesapi.com/api/v1/symbols?category=interbank&base=ZAR&api_key=YOUR_KEY"
import requests
resp = requests.get('https://interestratesapi.com/api/v1/symbols', params=dict(category='interbank', base='ZAR', api_key='YOUR_KEY'))
print(resp.json())
const resp = await fetch('https://interestratesapi.com/api/v1/symbols?category=interbank&base=ZAR&api_key=YOUR_KEY');
console.log(await resp.json());
<?php
echo file_get_contents('https://interestratesapi.com/api/v1/symbols?category=interbank&base=ZAR&api_key=YOUR_KEY');
?>
Latest:
curl "https://interestratesapi.com/api/v1/latest?symbols=JIBAR_3M,ECB_MRO&api_key=YOUR_KEY"
import requests
print(requests.get('https://interestratesapi.com/api/v1/latest', params=dict(symbols='JIBAR_3M,ECB_MRO', api_key='YOUR_KEY')).json())
const r = await fetch('https://interestratesapi.com/api/v1/latest?symbols=JIBAR_3M,ECB_MRO&api_key=YOUR_KEY');
console.log(await r.json());
<?php
echo file_get_contents('https://interestratesapi.com/api/v1/latest?symbols=JIBAR_3M,ECB_MRO&api_key=YOUR_KEY');
?>
Historical:
curl "https://interestratesapi.com/api/v1/historical?date=2024-06-15&symbols=JIBAR_3M&api_key=YOUR_KEY"
import requests
print(requests.get('https://interestratesapi.com/api/v1/historical', params=dict(date='2024-06-15', symbols='JIBAR_3M', api_key='YOUR_KEY')).json())
const h = await fetch('https://interestratesapi.com/api/v1/historical?date=2024-06-15&symbols=JIBAR_3M&api_key=YOUR_KEY');
console.log(await h.json());
<?php
echo file_get_contents('https://interestratesapi.com/api/v1/historical?date=2024-06-15&symbols=JIBAR_3M&api_key=YOUR_KEY');
?>
Timeseries:
curl "https://interestratesapi.com/api/v1/timeseries?start=2019-01-01&end=2026-09-20&symbols=JIBAR_3M&api_key=YOUR_KEY"
import requests
print(requests.get('https://interestratesapi.com/api/v1/timeseries', params=dict(
start='2019-01-01', end='2026-09-20', symbols='JIBAR_3M', api_key='YOUR_KEY'
)).json())
const t = await fetch('https://interestratesapi.com/api/v1/timeseries?start=2019-01-01&end=2026-09-20&symbols=JIBAR_3M&api_key=YOUR_KEY');
console.log(await t.json());
<?php
echo file_get_contents('https://interestratesapi.com/api/v1/timeseries?start=2019-01-01&end=2026-09-20&symbols=JIBAR_3M&api_key=YOUR_KEY');
?>
Fluctuation:
curl "https://interestratesapi.com/api/v1/fluctuation?start=2024-01-01&end=2026-09-20&symbols=JIBAR_3M&api_key=YOUR_KEY"
import requests
print(requests.get('https://interestratesapi.com/api/v1/fluctuation', params=dict(
start='2024-01-01', end='2026-09-20', symbols='JIBAR_3M', api_key='YOUR_KEY'
)).json())
const f = await fetch('https://interestratesapi.com/api/v1/fluctuation?start=2024-01-01&end=2026-09-20&symbols=JIBAR_3M&api_key=YOUR_KEY');
console.log(await f.json());
<?php
echo file_get_contents('https://interestratesapi.com/api/v1/fluctuation?start=2024-01-01&end=2026-09-20&symbols=JIBAR_3M&api_key=YOUR_KEY');
?>
OHLC:
curl "https://interestratesapi.com/api/v1/ohlc?symbols=JIBAR_3M&period=monthly&start=2023-01-01&end=2026-09-20&api_key=YOUR_KEY"
import requests
print(requests.get('https://interestratesapi.com/api/v1/ohlc', params=dict(
symbols='JIBAR_3M', period='monthly', start='2023-01-01', end='2026-09-20', api_key='YOUR_KEY'
)).json())
const o = await fetch('https://interestratesapi.com/api/v1/ohlc?symbols=JIBAR_3M&period=monthly&start=2023-01-01&end=2026-09-20&api_key=YOUR_KEY');
console.log(await o.json());
<?php
echo file_get_contents('https://interestratesapi.com/api/v1/ohlc?symbols=JIBAR_3M&period=monthly&start=2023-01-01&end=2026-09-20&api_key=YOUR_KEY');
?>
Convert:
curl "https://interestratesapi.com/api/v1/convert?from=JIBAR_3M&to=ECB_MRO&amount=2500000&term_months=36&api_key=YOUR_KEY"
import requests
print(requests.get('https://interestratesapi.com/api/v1/convert', params=dict(
from='JIBAR_3M', to='ECB_MRO', amount=2500000, term_months=36, api_key='YOUR_KEY'
)).json())
const c = await fetch('https://interestratesapi.com/api/v1/convert?from=JIBAR_3M&to=ECB_MRO&amount=2500000&term_months=36&api_key=YOUR_KEY');
console.log(await c.json());
<?php
echo file_get_contents('https://interestratesapi.com/api/v1/convert?from=JIBAR_3M&to=ECB_MRO&amount=2500000&term_months=36&api_key=YOUR_KEY');
?>
Error handling and troubleshooting: building resilient Finance apps
Robust Finance systems surface clear diagnostics and gracefully handle edge cases. interestratesapi.com returns a consistent error shape with success=false and an error message string. Common HTTP status codes include:
- 401: Missing, invalid, or revoked key; user not found.
- 403: Account without active plan.
- 404: No symbols matched or no data for requested date/range (may include details about available ranges).
- 422: Validation error (e.g., date format, invalid symbol).
Example of a 422 validation error when a symbol is misspelled:
{
"success": false,
"error": "Validation error: invalid symbol 'JIBAR_3MM'"
}
Best practices:
- Validate symbols against /symbols during configuration stages to avoid runtime 422s.
- For 404 data gaps, surface the message to users and suggest an adjusted date range.
- Log request URLs, query parameters, and timestamps to expedite incident resolution.
- Implement retries for transient network issues and backoff strategies when encountering server‑side 5xx conditions.
Troubleshooting checklist:
- Check date formats (Y‑m‑d) are correct and within known historical coverage.
- Ensure you requested the correct frequency context; JIBAR_3M is monthly in this dataset.
- If combining multiple symbols, verify currencies and frequencies before calculating spreads or correlations.
Real‑world scenarios where JIBAR_3M data adds value
- Treasury pricing engine: Use /latest to set current JIBAR_3M benchmarks for floating‑rate loans, and /historical to price as‑of quotes for backdated contracts. /timeseries drives risk metrics that inform margins and capital allocation.
- Risk dashboards: /fluctuation provides quick month‑to‑date or quarter‑to‑date change cards. /ohlc populates candlestick panels for at‑a‑glance cycle detection. /symbols enables expanding coverage as your scope grows.
- Quant research: /timeseries supports regression analysis of JIBAR_3M vs SARB_REPO_RATE, liquidity spreads vs treasury curves, and cross‑market linkages vs EURIBOR_3M. /historical allows event studies on policy announcement dates.
- Investor communications: /convert helps explain comparative funding environments to non‑technical stakeholders, providing tangible examples of interest cost differentials under different benchmarks.
Governance, reliability, and developer ergonomics for Finance teams
Finance applications must be observable, testable, and controlled. While technical specifics vary across organizations, the following patterns work well with interestratesapi.com:
- Configuration‑driven routing: Centralize endpoint URLs and symbols in configuration files. This reduces production change risk and provides a clear audit trail for symbol universes.
- Observability: Emit logs with endpoint, query params, and durations. Alert on response schema mismatches or unexpected nulls, especially when downstream models expect continuous monthly series.
- Resilience: Wrap calls with retry policies for transient network faults. Fallback to cached data for read‑only dashboards if network connectivity is impaired.
- Data locality and lineage: Separate raw (JSON) storage from normalized time series tables, and include the API’s metadata in both layers (frequencies, currencies, start_date, end_date) to support trustworthy audit trails.
- Automated validation: Unit test your JIBAR_3M ETL to confirm frequency, monotonic dates, and non‑empty values before promoting datasets to downstream consumers.
Putting it together: from ingestion to decision support
An effective JIBAR_3M solution with interestratesapi.com looks like this:
- Discovery: use /symbols to confirm JIBAR_3M and related ZAR instruments you want to track.
- Ingestion: batch /timeseries pulls monthly to your data warehouse. Store metadata fields and verify continuity.
- Ops monitoring: /latest feeds real‑time dashboards and alert thresholds when JIBAR_3M shifts materially.
- Analytics: /fluctuation populates BI cards; /ohlc drives charting; /historical powers point‑in‑time valuations.
- Stakeholder communication: /convert gives quick talking points for cost differentials across benchmarks.
Every endpoint returns consistent, predictable JSON. With a few hundred lines of well‑tested glue code, you obtain a robust Finance data platform that automates JIBAR_3M collection, quality checks, visualization, and distribution.
Conclusion and next steps
JIBAR 3‑Month is central to ZAR funding and pricing. interestratesapi.com consolidates the fetch, align, and analyze workflow into a clean set of GET endpoints designed for Finance teams. Use /timeseries for research‑grade historicals, /historical for as‑of checks, /ohlc for candlesticks, /fluctuation for summaries, and /convert for quick cost comparisons. Pair these with systematic ETL patterns in Python and pandas, and you will accelerate delivery of pricing tools, risk dashboards, and investor communications—replacing ad‑hoc spreadsheets and brittle scrapers with a durable, testable data foundation.
Get hands‑on here:




