Live

Albanian lek exchange-rate API

Buy and sell rates against the lek (ALL) from the Bank of Albania, commercial banks and exchange offices — one JSON document, refreshed every 15 minutes. Current rates need no key and no sign-up.

Quick start

One request returns every currency, with each institution’s own quote next to the average.

cURL
curl https://api.kursi.al/api/rates
JavaScript
const { timestamp, rates } = await fetch('https://api.kursi.al/api/rates').then(r => r.json());

console.log(`1 EUR = ${rates.EUR.buy} / ${rates.EUR.sell} ALL (${timestamp})`);

// One institution instead of the average — undefined when it did not quote EUR in this run:
const bkt = rates.EUR.sources.BKT;
Python
import requests

data = requests.get("https://api.kursi.al/api/rates", timeout=10).json()
eur = data["rates"]["EUR"]
print(eur["buy"], eur["sell"], data["timestamp"])

Access

Open

Free · no key
  • GET /api/rates
  • GET /api/rate/{code}
  • GET /health

No sign-up. CORS is open, so these can be called from a browser on any site as well as from a server.

With a key

Paid
  • GET /api/history/{code}
  • GET /api/graph/{code}

Send the key in the X-API-Key header. For a key and pricing, write to info@oda.al.

curl "https://api.kursi.al/api/history/EUR?from_date=2026-09-01&to_date=2026-09-07&source=BKT" \
  -H "X-API-Key: your-key"

Without a valid key these endpoints answer:

HTTP/1.1 403 Forbidden

{ "detail": "This endpoint requires an API key. Contact info@oda.al for access and pricing." }
Keep your key on a server. A key placed in front-end JavaScript can be read by anyone who opens the page. Call the key-protected endpoints from your backend and pass the result on to the browser.

Endpoints

Base URL: https://api.kursi.al. Every endpoint is a GET that returns JSON; {code} is an ISO 4217 currency code, in any letter case.

Current rates

Free · no key
GET /api/rates

Every currency in one document — the one this site’s own rates table is drawn from.

{
  "timestamp": "2026-09-21T14:30:00+02:00",
  "rates": {
    "EUR": {
      "buy": 91.25,
      "sell": 91.71,
      "change": "-0.11%",
      "trend": "down",
      "sources": {
        "BOA":      { "buy": 91.49, "sell": 91.49 },
        "BKT":      { "buy": 91.15, "sell": 91.85 },
        "Iliria98": { "buy": 91.10, "sell": 91.80 }
      }
    },
    "NOK": {
      "buy": 7.74,
      "sell": 8.19,
      "change": "+0.13%",
      "trend": "up",
      "sources": {
        "BOA":        { "buy": 8.48, "sell": 8.48 },
        "Iliria98":   { "buy": 7.00, "sell": 7.90 },
        "Raiffeisen": { "buy": 1.45, "sell": 15.45, "in_avg": false }
      }
    }
  }
}
timestamp
When this set of rates was collected — ISO 8601 with Albania’s UTC offset.
buy, sell
The average across the sources that quoted the currency in this run, in lek per one unit.
change, trend
Movement of the mid-rate against roughly 24 hours earlier, as text ("+0.12%"), and its direction: up, down or neutral.
sources
Each institution’s own quote. A source that did not quote the currency is absent. "in_avg": false marks a quote that was left out of the average — see Conventions.

One currency

Free · no key
GET /api/rate/{code}

The latest rate of a single currency. rate is the mid-point between the average buy and sell.

{
  "currency": "EUR",
  "timestamp": "2026-09-21T14:30:00+02:00",
  "sources": {
    "BOA":      { "buy": 91.49, "sell": 91.49 },
    "BKT":      { "buy": 91.15, "sell": 91.85 },
    "Iliria98": { "buy": 91.10, "sell": 91.80 }
  },
  "rate": 91.48,
  "buy": 91.25,
  "sell": 91.71,
  "type": "avg"
}

With ?type=buy or ?type=sell the answer narrows to that side: rate is the average for it, and sources maps each institution to a single number.

{
  "currency": "EUR",
  "timestamp": "2026-09-21T14:30:00+02:00",
  "sources": { "BOA": 91.49, "BKT": 91.15, "Iliria98": 91.1 },
  "rate": 91.25,
  "type": "buy"
}

History

Key required
GET /api/history/{code}

Every recorded rate in a date range — one row per update run — for the average or for a single source. Made for back-office reconciliation, research and exports.

from_date
Start of the range: 2026-09-01 or 2026-09-01 08:00:00, Albanian local time. Always pass one — without it the answer starts at the first row we have.
to_date
End of the range. A date without a time includes that whole day.
source
AVG (the default), or one of BOA, ADON, BKT, Raiffeisen, Iliria98, AlbKredit.
[
  { "timestamp": "2026-09-01 09:00:00", "buy": 91.15, "sell": 91.85, "source": "BKT" },
  { "timestamp": "2026-09-01 09:15:00", "buy": 91.15, "sell": 91.85, "source": "BKT" },
  { "timestamp": "2026-09-01 09:30:00", "buy": null,  "sell": null,  "source": "BKT" }
]

Timestamps here are Albanian local time without an offset. buy and sell are null in runs where the chosen source had no quote.

Chart series

Key required
GET /api/graph/{code}

The series behind this site’s charts, already bucketed for the time span and ready to plot.

timeframe
1D, 1W, 1M (the default), 3M, 6M, 1Y or YTD.
source
One source (AVG by default). Answers { labels, buy_data, sell_data }; points where the source had no quote are dropped.
sources
Several at once, comma-separated: sources=BOA,BKT,Iliria98. Answers every series on one shared time axis, with null where a source had no quote — one request for a whole comparison chart.
{
  "labels": ["22 Aug", "23 Aug", "24 Aug"],
  "series": {
    "BOA": { "buy": [91.60, 91.58, 91.54], "sell": [91.60, 91.58, 91.54] },
    "BKT": { "buy": [91.20, null,  91.15], "sell": [91.90, null,  91.85] }
  }
}

labels are display strings in Albanian local time: 14:30 for 1D, Mon 21 for 1W, 21 Sep up to six months, 21 Sep 26 for a year.

Service health

Free · no key
GET /health

Whether rates are still being collected, source by source. status is ok, degraded (some source is failing, the rest are fresh) or down — and down comes with HTTP 503, so an uptime monitor can watch it. Worth checking before you alert on a rate that has not moved.

{
  "status": "ok",
  "last_run": "2026-09-21T14:30:04+02:00",
  "database": "ok",
  "failing_sources": [],
  "sources": {
    "BKT": {
      "status": "ok",
      "last_success": "2026-09-21T14:30:02+02:00",
      "last_attempt": "2026-09-21T14:30:02+02:00",
      "consecutive_failures": 0,
      "currencies": 7
    }
  }
}

Conventions

Currencies

Against the Albanian lek (ALL):

EUR Euro USD US Dollar GBP British Pound CHF Swiss Franc CAD Canadian Dollar AUD Australian Dollar SEK Swedish Krona NOK Norwegian Krone TRY Turkish Lira SAR Saudi Riyal AED UAE Dirham JPY Japanese Yen RUB Russian Rouble MKD Macedonian Denar DKK Danish Krone RSD Serbian Dinar CZK Czech Koruna RON Romanian Leu PLN Polish Zloty BAM Bosnian Mark

Sources

IdInstitutionKind
BOABank of AlbaniaOfficial reference rate
ADONADONMarket rate — a place you can exchange at
BKTBKTMarket rate — a place you can exchange at
RaiffeisenRaiffeisenMarket rate — a place you can exchange at
Iliria98Iliria98Market rate — a place you can exchange at
AlbKreditAlbKreditMarket rate — a place you can exchange at

AVG is accepted wherever a source is, and means the average. More about each institution on the sources page.

Errors

StatusBodyWhen
400{ "detail": "Unknown source 'XYZ'. Valid: AVG, BOA, …" }An unknown source, or a date that is not YYYY-MM-DD / YYYY-MM-DD HH:MM:SS.
403{ "detail": "This endpoint requires an API key. …" }A key-protected endpoint was called without a valid X-API-Key.
404{ "error": "Currency not found" }/api/rate/{code} for a currency we do not track.
429Too many requests from your IP address. Back off and retry; cache responses for a minute and you will not see it.
503{ "error": "Database unavailable" }A temporary backend problem. /health also answers 503 when rates have stopped updating.

Validation errors use detail, the others error. During a rare backend failure a 200 answer can carry { "error": … } in place of data, so treat a missing rates key as a failure rather than reading through it.

Widget

No code to write: an iframe that shows live rates on your site, in English, with the sources and currencies you choose. It loads one small stylesheet and script and refreshes itself.

Build your widget

Currencies (pick the ones you need)
Embed code

Preview

FAQ

Is the current-rates API really free?

Yes. /api/rates and /api/rate/{code} need no key and no sign-up, and can be called from a server or straight from a browser on any site. Requests are rate-limited per IP address to keep the service stable for everyone; the data changes every 15 minutes, so caching it for a minute costs you nothing.

How do I get an API key?

Keys are issued by hand. Write to info@oda.al with a line about what you are building and which endpoints you need; we reply with pricing and a key.

Why are history and chart data paid?

Current rates are one small document. Years of per-source history, recorded at every update, are what cost money to keep and to serve — so that part is a paid service, and the current rates stay free.

Where do the rates come from?

From what each institution publishes itself: the Bank of Albania’s official rate, two commercial banks and three exchange businesses. The sources page lists them and explains how the average is calculated and which quotes are left out of it.

Can I get the rate of one bank instead of the average?

Yes. Every currency carries a sources object with each institution’s own buy and sell rate, and /api/history and /api/graph take a source parameter. A source that did not quote the currency is simply absent.

Need history or chart data?

Tell us what you are building and which endpoints you need; we reply with pricing and a key.

Write to info@oda.al