Docs / Rates Data API / Endpoints / List exchange rates

List exchange rates

Returns one row per (date, code), newest ingest first. `date` is the calendar date you asked about in Asia/Baku; `effective_date` is the date the bank says those rates take effect from, read out of the bulletin rather than inferred from the date requested. Filter `carried_forward=false` for a strict business-day series, or take every row for a dense daily one and know which values are repeats.

GET https://api.softon.dev/v1/rates Copy

Query parameters

ParameterTypeDescription
from date Earliest `date`, inclusive.
to date Latest `date`, inclusive.
codes string Currency or metal codes, comma-separated — `USD,EUR`. Case is normalised, and a repeated `?codes=` is unioned with the list rather than overwriting it. Omit for all 42.
kind string `currency` or `metal`. The metals are the four the bank publishes per troy ounce.
carried_forward boolean `false` returns only the dates the bank actually published on — a strict business-day series. `true` returns only the repeats. Omit for the dense daily series, which is both.
limit integer Items per page, 1–100. Defaults to 25.
cursor string Opaque cursor from a previous response's meta.next. Do not construct one.
order string Sort field: `ingested_at`, each optionally prefixed with `-` to reverse. Default is `-ingested_at`. Rows with no value for the sort column always sort LAST in either direction, so paging never leads with undated rows.
source string Restrict to ONE scraper source, by its stem — `abb`, not `ABB` or `abb-bank.az`. Not a list: `?source=a,b` and a repeated `?source=` do not select two sources. On `/v1/jobs` an unknown stem is a `400` naming it, and `source_type` is the way to select several sources at once. `GET /v1/sources` lists every stem.

Request

curl -G https://api.softon.dev/v1/rates \
  -H "Authorization: Bearer $SOFTON_KEY" \
  -d from=2026-09-01 -d to=2026-09-05 -d codes=USD,EUR

Response

The envelope is identical on every softon.dev API: data, meta, error. Only the shape inside data changes per dataset — see the response envelope.

{
  "data": [
    {
      "id": "cbar:2026-09-05:USD",
      "source": "cbar",
      "date": "2026-09-05",
      "effective_date": "2026-09-04",
      "carried_forward": true,
      "kind": "currency",
      "base": "AZN",
      "code": "USD",
      "name": "1 AB\u015e dollar\u0131",
      "unit": "unit",
      "nominal": 1,
      "value": 1.7,
      "rate_per_unit": 1.7,
      "source_url": "https://www.cbar.az/currencies/05.09.2026.xml",
      "bulletin_url": "https://www.cbar.az/currencies/04.09.2026.xml",
      "ingested_at": "2026-09-14T22:53:47.016591Z"
    }
  ],
  "meta": { "count": 1, "next": "eyJvIjoyfQ", "request_id": "req_9Fv3" },
  "error": null
}

Fields of each item in data[]

FieldTypeDescription
id string Stable identifier, "<source>:<date>:<code>" — `cbar:2026-09-05:USD`. Opaque: treat the whole string as the id rather than parsing the halves out of it.
source string Which scraper delivered this bulletin. `cbar` is the Central Bank of Azerbaijan.
date date The calendar date this row answers for, **Asia/Baku**. Azerbaijan is UTC+4 year-round with no DST, so a consumer computing "today" in UTC gets yesterday's date for the four hours after 20:00 Baku — which is a real bug this feed's predecessor shipped, not a hypothetical one.
effective_date date The date the bank says these rates take effect from — the bulletin's own `ValCurs Date=`, never inferred from the date requested. On a business day it equals `date`; on a weekend, a public holiday or a future date it is the last business day before it.
carried_forward boolean `date != effective_date`: these numbers were published earlier and are still standing. **Filter `carried_forward=false` for a strict business-day series**; take every row for a dense daily one and know which values are repeats. The upstream answers `200` with a full bulletin for every date string including weekends and dates in the future, so this flag is the only thing that distinguishes a fresh publication from a repeat.
kind string `currency` or `metal`. The four bank metals (XAU, XPD, XPT, XAG) are the metals.
base string The currency the rate is expressed in. Always `AZN` for this source.
code string ISO 4217 code, or the metal's X-code. 42 per bulletin: 38 currencies and 4 bank metals. `SDR` is the IMF basket rather than a currency, and is carried as the bank publishes it.
name string · nullable The bank's own label, in Azerbaijani, including the multiplier it prints there — "1 ABŞ dolları", "100 Yapon iyeni".
unit string What one of `nominal` is: `unit` for a currency, `troy_ounce` for a metal.
nominal integer How many units `value` is quoted for. Seven currencies quote per 100 — KRW, KZT, HUF, UZS, PKR, RUB and JPY — and everything else per 1. Reading `value` without dividing by this is how a rouble comes out a hundred times too large.
value number The published figure, unrounded: AZN per `nominal` units.
rate_per_unit number `value / nominal`, unrounded. **This is the number you almost certainly want**: AZN for one unit of `code`, or for one troy ounce of a metal.
source_url string · nullable The document requested for `date`.
bulletin_url string · nullable The document these numbers were published in, i.e. the one for `effective_date`. Differs from `source_url` on a carried-forward row.
ingested_at timestamp When this version was stored.

Try it

v1 · stable
Send the request to see a response.