For analysts
The data API
Everything the site shows is served by one small API, and the data room’s downloads are calls to it. This page is the reference: each endpoint, what it takes and returns, and how to pull the data into Python or Excel. No key and no sign-up.
The basics
- Base URL
https://api.africaneurobonds.com. Every endpoint is a plain HTTPS GET and answers JSON unless it is a download. Any origin may call it from a browser. The earlier address,bond-api-u1jv.onrender.com, keeps answering; new work should use this one. - Prices answer with
Cache-Control: max-age=30and an ETag; sendIf-None-Matchand you get a 304 when nothing changed. The site itself polls every 30 seconds and nothing moves faster than that, so please do not poll faster. - Send a
User-Agentthat names your application, so that a problem can be traced and you can be told about a change. - Dates are ISO (
YYYY-MM-DD); times are UTC. In JSON, coupons and yields are decimals (0.0648); in the CSV and Excel exports they are in percent (6.48), as the column names say. - A bond the site holds but does not price is in
/excludedand nowhere else. A withheld yield isnull, never zero.
Endpoints
GET /bonds
Every published bond with its live price: {count, bonds: [...]}. The fields are listed below.
country- optional: a country as
/countrieslists it
Example /bonds?country=Nigeria
GET /bonds/{isin}
One bond: instrument (its stored terms), live (the same row /bonds serves, or null when the bond is held but not priced) and pricing_history (every daily close: price_date, bid_price, ask_price, bid_yield, ask_yield). 404 for an ISIN the site does not hold or does not price.
Example /bonds/XS1777972511
GET /bonds/{isin}/consideration
What a trade settles for: principal, accrued (with accrued_days, accrued_from, accrued_per_100), total, the yield at that price (yield_pct, basis to maturity or to call, workout_date), factor and current_face for a bond that has repaid part of its principal, and settlement_choices. Never cached. A refusal (bad date, zero nominal, matured bond) is a 422 with a sentence.
nominal- face amount, default 1,000,000
price- clean price per 100; default the live ask (buy) or bid (sell)
settlement- YYYY-MM-DD, a business day up to a year out; default T+2 for an XS line, T+1 for a US line
sidebuy(default) orsell
Example /bonds/XS1777972511/consideration?nominal=250000&side=buy
GET /bonds/{isin}/export
The bond’s daily closes as a file, newest first: the data room’s per-bond download.
period1W, 1M, 3M, 6M, 1Y, YTDorAll(default)formatcsvorxlsx(default)
GET /export/closes
One long table, a row per bond per day, for whatever the filters select; no filter is the whole history of every published bond. Columns: date, isin, bond, issuer, issuer_type, country, currency, coupon_pct, maturity_date, bid_price, ask_price, bid_yield_pct, ask_yield_pct, yield_to, yield_note. Rebuilt at most every ten minutes.
country- a country as
/countrieslists it issuer_typesovereign,corporateorsupranationalstart, end- YYYY-MM-DD, inclusive
on- one session: the latest on or before this date, for every bond
formatcsv(default) orxlsx
Example /export/closes?country=Kenya&start=2026-01-01&format=csv
GET /export/terms
Reference data: one row per bond with its terms and the document each figure was read from; the repayment ladders of bonds that repay in instalments (each marked documented or inferred); the call schedules of callable bonds.
tablebonds(default),amortisationorcallsformatcsv(default) orxlsx
GET /countries
{countries: [...]}, the country strings the filters above accept.
Example /countries
GET /excluded
The bonds the site holds but deliberately does not price, each with a summary and the detail behind the decision: the mirror of /bonds.
Example /excluded
GET /health
status, the commit that is serving and an api date that moves when the shape of an answer changes.
Example /health
What a bond row holds
| Field | Meaning |
|---|---|
isin, isin_144a | The Reg S ISIN, and the Rule 144A ISIN where there is one. Per-ISIN routes take either. |
ticker, issuer, issuer_name | The bond’s short name and its issuer. |
issuer_type | sovereign, supranational, or for the Corporates group corporate, bank or quasi_sovereign. |
country, country_of_risk | The country, upper case. For a corporate, the country of risk and the rule that assigned it (country_of_risk_rule). |
currency, coupon_rate, coupon_frequency, day_count | Coupon as a decimal (0.07 is 7%), coupons per year, the day-count basis. |
issue_date, maturity_date | ISO dates; maturity_date is null for a perpetual. |
amount_outstanding, outstanding_factor, current_outstanding | The original face held by the site, the share of it still outstanding after scheduled repayments, and their product. |
wal_years | Years to maturity for a bullet; the weighted average life of the remaining instalments for a bond that repays in parts. |
bid_price, ask_price, prev_close, daily_change | Clean prices per 100 of face still outstanding; the close before this bond’s own price_date; the change on it. |
bid_yield, ask_yield | Decimals (0.0648 is 6.48%), solved on the stored terms. Null when the yield is withheld or the bond trades on recovery. |
bid_workout_date, bid_workout_price (and ask_) | Set when the yield is to a call rather than to maturity: the date and price it was worked out to. |
price_date, price_time, price_source | The session the price belongs to, when it was set (UTC), and where it came from. |
stale, rejected, reject_reason | stale: the price rests on an anchor older than the latest session. rejected: the latest close was refused and the reason says why. |
distressed | Mid price below 70: priced on expected recovery, so the yield is for reference only. |
yield_status, yield_withheld_reason | published, or withheld with the reason (terms not yet read from the offering document, a reset ahead, …). |
Files beside the API
These are static files on the site, rebuilt every night from the stored terms and the last close; they need no API call.
| URL | Meaning |
|---|---|
/data/calendar.csv | Every future coupon, repayment and maturity of every bond, from the stored terms (the payment calendar). |
/data/cashflows/{ISIN}.json | One bond’s future cash flows as cash per 100 of original face: {isin, currency, maturity, frequency, flows: [{d, k, p100, rate}]}. Multiply p100 by your nominal / 100. |
/data/curves.json | The nightly yield-curve fit per issuer and currency (Nelson–Siegel parameters, tenor span, RMSE) and each bond’s tenor, mid yield, curve yield and residual at the last close (the relative-value chart). |
/learn/bondpages.json | ISIN to the bond’s page on this site. |
Recipes
Python
import requests, pandas as pd
API = "https://api.africaneurobonds.com"
bonds = pd.DataFrame(requests.get(API + "/bonds", headers={"User-Agent": "my-app"}).json()["bonds"])
print(bonds[["ticker", "currency", "bid_price", "ask_price", "ask_yield", "wal_years"]].head())
# a bond's whole close history as a frame
hist = pd.read_csv(API + "/bonds/XS1777972511/export?period=All&format=csv", parse_dates=["date"])
# the whole market on one day
day = pd.read_csv(API + "/export/closes?on=2026-10-09")
Excel
In Excel, Data → From Web (or Power Query) with a CSV URL gives a refreshable table; for example the whole market on one day:
https://api.africaneurobonds.com/export/closes?on=2026-10-09
Command line
curl -H "User-Agent: my-app" "https://api.africaneurobonds.com/bonds?country=Nigeria"
curl -o nigeria.csv "https://api.africaneurobonds.com/export/closes?country=Nigeria&format=csv"
Good to know
- Every figure is indicative: a calculation on the stored terms and the site’s indicative closes, not a traded price, not a quotation and not an offer to deal. Nothing is advice.
- No uptime is promised. The base URL and the shape of an answer may change; when they do, this page changes first and
/health’sapidate moves. - Free to use. If you publish something built on this data, please cite African Eurobonds (africaneurobonds.com). The Terms apply.