Docs / Rates Data API / Endpoints / Latest bulletin

Latest bulletin

The newest bulletin the corpus actually holds, which is not the same as today's date: before the day's publication it is still the previous business day's, and asking for today directly would answer empty. The filters apply before the date is resolved, so `?kind=metal` returns the newest date that has metals on it.

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

Query parameters

ParameterTypeDescription
from date Ignore dates before this one when resolving "latest".
to date Resolve "latest" as of this date rather than now — the bulletin that was in force on a given day.
codes string Currency or metal codes, comma-separated — `USD,EUR`.
kind string `currency` or `metal`.
carried_forward boolean `false` resolves to the last date the bank actually published on, skipping a weekend's repeats.
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/latest \
  -H "Authorization: Bearer $SOFTON_KEY" \
  -d codes=USD,EUR -d limit=50 -d order=-ingested_at

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:XAU",
      "source": "cbar",
      "date": "2026-09-05",
      "effective_date": "2026-09-04",
      "carried_forward": true,
      "kind": "metal",
      "base": "AZN",
      "code": "XAU",
      "name": "Q\u0131z\u0131l",
      "unit": "troy_ounce",
      "nominal": 1,
      "value": 7605.494,
      "rate_per_unit": 7605.494,
      "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.