πŸ“– ad-bs API

← back to app

Read-only Β· unauthenticated Β· JSON. Machine-readable schema: OpenAPI 3.1.

envelopeSuccess β†’ { "ok": true, "data": … } Β· Failure β†’ { "ok": false, "error": "slug", "message": "…" } with a proper 4xx status. Responses are never malformed; a date outside the dataset returns 404 out_of_range with the valid range.

date inputsLenient everywhere: 2026-07-09, 20260709, 2026_07_09, 2026/07/09, 2026-07-09T13:45:00Z β€” separators optional, time stripped.

flagsEvery endpoint (except /dump) accepts ?quiet=true β€” only the asked-for values, no enrichment β€” and ?plain=true β€” text/plain instead of JSON (errors too). quiet+plain on /convert returns just the converted date. Span endpoints also take ?unit=days|weeks|months|years for whole-unit breakdowns with leftovers, e.g. 23 Years, 9 Months, 2 Weeks & 6 Days ago.

# quiet: only the asked-for values, no enrichment
$ curl -s 'https://ad-bs.ajam.dev/api/v1/convert?ad=2026-07-09&quiet=true'
{"ok":true,"data":{"ad":"2026-07-09","bs":"2083-03-25"}}

# plain: plaintext instead of JSON (errors become "error: ..." text too)
$ curl -s 'https://ad-bs.ajam.dev/api/v1/convert?ad=2026-07-09&plain=true'
ad: 2026-07-09
bs: 2083-03-25
day: Thursday
ad_human: Thursday, 9th July - 2026 AD
bs_human: Thursday, 25th Ashad - 2083 BS
divergence_ad_to_bs: +56y 8m 16d
divergence_bs_to_ad: -56y 8m 16d

# KISS: quiet + plain = just the answer
$ curl -s 'https://ad-bs.ajam.dev/api/v1/convert?ad=2026-07-09&quiet=true&plain=true'
2083-03-25

Endpoints

routeparamsdescription
GET /api/v1/convertad | bsConvert one date. Returns the full entry: both dates, weekday, human forms, divergence (both directions).
GET /api/v1/todaytz?Today’s entry. tz = IANA name or +HH:MM; default Asia/Kathmandu.
GET /api/v1/rangeβ€”Dataset range (first/last AD+BS), total entries, last update, seed hash.
GET /api/v1/monthad | bs (YYYY-MM)Every day of one calendar month β€” powers calendar grids.
GET /api/v1/days-sincead | bs, tz?Signed day count from a date to today.
GET /api/v1/days-betweenfrom_ad|from_bs, to_ad|to_bsSigned day count between any two dates; calendars can be mixed.
GET /api/v1/months/:bsYearpath: BS yearBS month lengths for a year + total days.
GET /api/v1/seasonsβ€”Static season/climate hint for each of the 12 BS months (also embedded in every entry as season).
GET /api/v1/dumpβ€”Full database dump as a JSON attachment: meta, month table, and every mapping fully enriched (day, human dates, divergence).

Example

$ curl -s 'https://ad-bs.ajam.dev/api/v1/convert?ad=2026-07-09'
{
  "ok": true,
  "data": {
    "id": 38907,
    "ad": "2026-07-09",
    "bs": "2083-03-25",
    "day": "Thursday",
    "day_of_week": 4,
    "ad_human": "Thursday, 9th July - 2026 AD",
    "bs_human": "Thursday, 25th Ashad - 2083 BS",
    "ad_month_name": "July",
    "bs_month_name": "Ashad",
    "season": {
      "emoji": "🌦️",
      "label": "Hot Β· monsoon onset"
    },
    "divergence": {
      "ad_to_bs": "+56y 8m 16d",
      "bs_to_ad": "-56y 8m 16d"
    }
  }
}

Divergence

Every entry carries a component-wise offset such that AD + ad_to_bs = BS (days borrow against real BS month lengths, months against years). The reverse direction is its exact negation. It lets you fast-forward/rewind between the calendars by whole years/months/days without re-querying.

Caching & limits

Responses are CORS-open (Access-Control-Allow-Origin: *) and carry ETag + Cache-Control (5 min for stable data, 60 s for today-dependent endpoints). Send If-None-Match to get cheap 304s β€” the ETag changes the moment the dataset is corrected. Heavy callers may hit a best-effort per-IP rate limit (429 with Retry-After); pace to a few requests per second and you will never see it.

Reliability

The dataset is a manually curated mapping of 81,919 consecutive days. Every rebuild is verified with round-trip regeneration plus a deterministic anomaly checker before it goes live; full dumps and pre-mutation snapshots are kept in object storage, restorable after validation. Inputs are validated; the API returns typed errors rather than guesses.