Developer reference · v1

The JSON API

The published dictionary as static JSON files. They are written when the site is built and served from the same CDN as the pages. You don't need a key or an SDK, and there is no rate limit.

Base URL https://karachay.com/api/v1
  • MethodsGET
  • Authnone
  • CORS*
  • FormatJSON, UTF-8
  • Cache1 hour
  • Data version977e8dea

Quick start

Get one entry by its slug, or the whole list with index.json. Every document names the dataVersion it was built from.

Shell
curl -s https://karachay.com/api/v1/words/at.json | jq '.senses[].en'
JavaScript
const API = "https://karachay.com/api/v1";

const res = await fetch(`${API}/words/${encodeURIComponent(slug)}.json`);
if (res.status === 404) throw new Error("no published entry: " + slug);
const word = await res.json();

for (const sense of word.senses) {
  console.log(word.headword.cyrillic, "—", sense.en);
}
Python
import json, urllib.parse, urllib.request

API = "https://karachay.com/api/v1"

def word(slug):
    url = f"{API}/words/{urllib.parse.quote(slug)}.json"
    with urllib.request.urlopen(url) as res:
        return json.load(res)

print([s["en"] for s in word("at")["senses"]])

Endpoints

All paths are relative to the base URL.

MethodPathReturns
GET /index.json Every published entry in one file — 9,973 rows. Start here: it is the list of valid slugs.
GET /words/{slug}.json One entry: head-word, parts of speech, and published senses with definitions, labels and examples.
GET /forms/{slug}.json Every form the engine builds for an entry — cases, possessives, degrees, the full conjugation — keyed by cell.
GET /expressions/index.json Every published idiom, proverb and fixed phrase — 4,399 rows.
GET /expressions/{id}.json One expression: its wording, variants, senses with literal readings and examples, and the member words it is built from.
GET /meta.json What this build is: data version, counts, license, and the endpoints it serves.

GET /api/v1/index.json

Every published entry in one file — 9,973 rows. Start here: it is the list of valid slugs.

Response fields

FieldTypeDescription
api string Always "v1".
dataVersion string The dictionary state this file was built from.
count number Number of rows in words.
words object[] Every published entry, in dictionary order.
words[].slug string Key for words/{slug}.json and forms/{slug}.json.
words[].cyrillic string Head-word in Cyrillic.
words[].latin string Head-word in Karachay Latin.
words[].pos string[] Parts of speech.
words[].gloss string Lead gloss.

? after a type: the field is omitted when empty.

Example

GET /index.json 200 OK
{
  "api": "v1",
  "dataVersion": "977e8dea",
  "count": 9973,
  "words": [
    {
      "slug": "aba",
      "cyrillic": "аба",
      "latin": "aba",
      "pos": [
        "noun"
      ],
      "gloss": "robe"
    },
    {
      "slug": "abadan",
      "cyrillic": "абадан",
      "latin": "abadan",
      "pos": [
        "adjective"
      ],
      "gloss": "grown-up"
    }
    // … 9,971 more
  ]
}

GET /api/v1/words/{slug}.json

One entry: head-word, parts of speech, and published senses with definitions, labels and examples.

Path parameters

NameTypeDescription
slugstringFrom index.json, or the last segment of a word page's address. Percent-encode non-ASCII letters (ç, ğ, ı, ö, ş, ü, ŋ).

Response fields

FieldTypeDescription
api string Always "v1".
slug string The entry's key: the same string as in the page address and the request path.
url string Path of the human page for this entry.
headword object The head-word, in both scripts.
headword.cyrillic string Cyrillic: the source spelling.
headword.latin string Karachay Latin, derived from the Cyrillic.
pos string[] Every part of speech across the entry's records.
gloss string The lead gloss — the one-line answer to "what does it mean".
entries object[] One per dictionary record behind the page. Usually one; two records that share a spelling (noun and interjection alan) share a page.
entries[].id string The record id. Stable; senses[].entry points back to it.
entries[].headword object The record's head-word, in both scripts.
entries[].headword.cyrillic string Cyrillic: the source spelling.
entries[].headword.latin string Karachay Latin, derived from the Cyrillic.
senses object[] The published senses, in the order the page prints them.
senses[].entry string The id of the record this sense belongs to.
senses[].pos string Part of speech of this sense.
senses[].en string The definition, as printed. May quote Karachay in backticks.
senses[].short string? A shorter form for listings. Absent when it equals en.
senses[].note string? A usage note.
senses[].labels map<string,string>? Present only when set. Keys: usage, currency, connotation, register, domain; see the conventions page for the values.
senses[].examples object[]? Example sentences.
senses[].examples[].cyrillic string? The sentence in Cyrillic.
senses[].examples[].latin string The sentence in Karachay Latin.
senses[].examples[].en string English translation.
forms object Where to find the paradigm.
forms.url string Path of this entry's forms document.
dataVersion string The dictionary state this file was built from.

? after a type: the field is omitted when empty.

Example

GET /words/at.json 200 OK
{
  "api": "v1",
  "slug": "at",
  "url": "/words/at/",
  "headword": {
    "cyrillic": "ат",
    "latin": "at"
  },
  "pos": [
    "noun"
  ],
  "gloss": "horse",
  "entries": [
    {
      "id": "at",
      "headword": {
        "cyrillic": "ат",
        "latin": "at"
      }
    }
  ],
  "senses": [
    {
      "entry": "at",
      "pos": "noun",
      "en": "horse",
      "examples": [
        {
          "cyrillic": "атны семиртсенг, джаяу джюрюмезсе",
          "latin": "atnı semirtseŋ, jayaw jürümezse",
          "en": "fatten your horse and you will not go on foot"
        }
        // … 4 more
      ]
    },
    {
      "entry": "at",
      "pos": "noun",
      "en": "name",
      "examples": [
        {
          "cyrillic": "атынг неди?",
          "latin": "atıŋ nedi?",
          "en": "what is your name?"
        }
        // … 4 more
      ]
    }
    // … 4 more
  ],
  "forms": {
    "url": "/api/v1/forms/at.json"
  },
  "dataVersion": "977e8dea"
}

GET /api/v1/forms/{slug}.json

Every form the engine builds for an entry — cases, possessives, degrees, the full conjugation — keyed by cell.

Separate from the word document because a verb's paradigm runs to hundreds of cells (810 for барыргъа) and most clients do not want it.

Path parameters

NameTypeDescription
slugstringSame slug as the word document.

Response fields

FieldTypeDescription
api string Always "v1".
slug string The entry's key.
url string Path of the matching word document.
headword object The head-word, in both scripts.
headword.cyrillic string Cyrillic: the source spelling.
headword.latin string Karachay Latin, derived from the Cyrillic.
forms object[] Every generated form, one per cell. Empty when the entry prints no tables.
forms[].key string Names the cell; see Form keys below.
forms[].pos string noun, verb or adjective: which paradigm the cell belongs to.
forms[].cyrillic string? The form in Cyrillic.
forms[].latin string The form in Karachay Latin.
dataVersion string The dictionary state this file was built from.

? after a type: the field is omitted when empty.

Example

GET /forms/at.json 200 OK
{
  "api": "v1",
  "slug": "at",
  "url": "/api/v1/words/at.json",
  "headword": {
    "cyrillic": "ат",
    "latin": "at"
  },
  "forms": [
    {
      "key": "case.nominative.sg",
      "pos": "noun",
      "cyrillic": "ат",
      "latin": "at"
    },
    {
      "key": "case.nominative.pl",
      "pos": "noun",
      "cyrillic": "атла",
      "latin": "atla"
    },
    {
      "key": "case.genitive.sg",
      "pos": "noun",
      "cyrillic": "атны",
      "latin": "atnı"
    },
    {
      "key": "case.genitive.pl",
      "pos": "noun",
      "cyrillic": "атланы",
      "latin": "atlanı"
    }
    // … 20 more
  ],
  "dataVersion": "977e8dea"
}

GET /api/v1/expressions/index.json

Every published idiom, proverb and fixed phrase — 4,399 rows.

Response fields

FieldTypeDescription
api string Always "v1".
dataVersion string The dictionary state this file was built from.
count number Number of rows in idioms.
idioms object[] Every published expression. (The array is named idioms for v1 compatibility.)
idioms[].id string Key for expressions/{id}.json.
idioms[].cyrillic string The expression in Cyrillic.
idioms[].latin string The expression in Karachay Latin.
idioms[].kind string Deprecated single category; kept for compatibility. Prefer tags.
idioms[].tags string[] Classification tags, nonexclusive.
idioms[].gloss string Short gloss of the first sense.

? after a type: the field is omitted when empty.

Example

{
  "api": "v1",
  "dataVersion": "977e8dea",
  "count": 4399,
  "idioms": [
    {
      "id": "abdez-alırğa",
      "cyrillic": "абдез алыргъа",
      "latin": "abdez alırğa",
      "kind": "collocation",
      "tags": [
        "collocation",
        "light-verb-construction"
      ],
      "gloss": "perform ablution"
    },
    {
      "id": "abrekge-çığarğa",
      "cyrillic": "абрекге чыгъаргъа",
      "latin": "abrekge çığarğa",
      "kind": "collocation",
      "tags": [
        "collocation"
      ],
      "gloss": "become an outlaw"
    }
    // … 4,397 more
  ]
}

GET /api/v1/expressions/{id}.json

One expression: its wording, variants, senses with literal readings and examples, and the member words it is built from.

Path parameters

NameTypeDescription
idstringFrom expressions/index.json. Percent-encode it.

Response fields

FieldTypeDescription
api string Always "v1".
id string The expression's key.
url string Path of the human page (percent-encode it before use).
kind string Deprecated single category; prefer tags.
tags string[] The union of the senses' tags.
expression object The wording, in both scripts.
expression.cyrillic string Cyrillic: the source spelling.
expression.latin string Karachay Latin, derived from the Cyrillic.
variants object[] Other attested wordings.
variants[].expression object The variant wording, in both scripts.
variants[].expression.cyrillic string Cyrillic: the source spelling.
variants[].expression.latin string Karachay Latin, derived from the Cyrillic.
variants[].dialect string? Where the variant is said, when recorded.
senses object[] The published senses.
senses[].tags string[] This sense's classification tags.
senses[].short string Listing-length gloss.
senses[].en string The full definition.
senses[].literal string? Word-for-word reading, where it differs from the meaning.
senses[].labels map<string,string>? The word-sense label keys, plus dialect.
senses[].examples object[]? Example sentences.
senses[].examples[].cyrillic string The sentence in Cyrillic.
senses[].examples[].latin string The sentence in Karachay Latin.
senses[].examples[].en string English translation.
words object[] Member words that have a published page.
words[].slug string The member's word slug.
words[].role string "anchor" (the word the phrase is built around) or "component".
words[].url string Its word document: follow it.
dataVersion string The dictionary state this file was built from.

? after a type: the field is omitted when empty.

Example

{
  "api": "v1",
  "id": "abdez-alırğa",
  "url": "/expressions/abdez-alırğa/",
  "kind": "collocation",
  "tags": [
    "collocation",
    "light-verb-construction"
  ],
  "expression": {
    "cyrillic": "абдез алыргъа",
    "latin": "abdez alırğa"
  },
  "variants": [],
  "senses": [
    {
      "tags": [
        "collocation",
        "light-verb-construction"
      ],
      "short": "perform ablution",
      "en": "To wash the body for ritual purity before prayer: the hands up to the fingers, the feet up to the knees, washing the face and hands and rinsing the mouth.",
      "literal": "to take ablution",
      "examples": [
        {
          "cyrillic": "Кюнде, джауунда да черекни боюнунда атам абидез ала, намаз къыла, таулада къаргъа, кырдыкга, тынгылауукъ ташлагъа джалан мангылайын салыб, дуниягъа ахшы тилекле этгенди.",
          "latin": "Künde, jawunda da çerekni boyununda atam abidez ala, namaz qıla, tawlada qarğa, kırdıkga, tıŋılawuq taşlağa jalan maŋılayın salıb, duniyağa ahşı tilekle etgendi.",
          "en": "In sun and in rain alike, on the bank of the river, my father would take ablution and pray, laying his bare forehead in the mountains on snow, on grass, on silent stones, and offer up good prayers for the world."
        }
        // … 1 more
      ]
    }
  ],
  "words": [
    {
      "slug": "abdez",
      "role": "component",
      "url": "/api/v1/words/abdez.json"
    },
    {
      "slug": "alırğa",
      "role": "component",
      "url": "/api/v1/words/alırğa.json"
    }
  ],
  "dataVersion": "977e8dea"
}

GET /api/v1/meta.json

What this build is: data version, counts, license, and the endpoints it serves.

Response fields

FieldTypeDescription
api string Always "v1".
dataVersion string The dictionary state this build was made from. Compare it to know whether anything could have changed.
generated string Build date, YYYY-MM-DD. Two builds of the same data differ only here.
counts object Sizes of this build.
counts.entries number Word pages (and word documents).
counts.records number Dictionary records behind those pages.
counts.senses number Published word senses.
counts.expressions number Published expressions.
counts.expressionSenses number Published expression senses.
licence string SPDX identifier of the data license.
licenceUrl string The license text.
attribution string The credit line to reproduce.
docs string This page.
endpoints map<string,string> The URL templates this build actually serves.

? after a type: the field is omitted when empty.

Example

GET /meta.json 200 OK
{
  "api": "v1",
  "dataVersion": "977e8dea",
  "generated": "2026-10-02",
  "counts": {
    "entries": 9973,
    "records": 9982,
    "senses": 20185,
    "expressions": 4399,
    "expressionSenses": 4900
  },
  "licence": "CC-BY-4.0",
  "licenceUrl": "https://creativecommons.org/licenses/by/4.0/",
  "attribution": "Karachay dictionary (karachay.com) by Davud Kaplan, CC BY 4.0",
  "docs": "/api/",
  "endpoints": {
    "index": "/api/v1/index.json",
    "word": "/api/v1/words/{slug}.json",
    "forms": "/api/v1/forms/{slug}.json",
    "idiomIndex": "/api/v1/expressions/index.json",
    "idiom": "/api/v1/expressions/{id}.json",
    "meta": "/api/v1/meta.json"
  }
}

Form keys

Each form's key is the same string the dictionary uses to store a correction to that cell, so you can quote it back in a bug report. It stays the same across data versions.

PatternExampleMeaning
case.<case>.<sg|pl>case.dative.sgNoun case: nominative, genitive, accusative, dative, locative, ablative.
owner.<person>.<sg|pl>owner.1sg.plPossessed noun: owner 1sg, 2sg, 3sg, 1pl, 2pl, 3pl; then the noun's own number.
degree.<degree>degree.comparativeAdjective degree: base, comparative, intensifier, superlative.
<table>.<polarity>.<person>present.n.4Verb cell. table is a conjugation name (present, past-definite, …); polarity below; person 0–5.

Verb polarity

aaffirmative
nnegative
qquestion
nqnegative question
nanegative on the auxiliary (compound tenses only)
nbnegative on both parts (compound tenses only)

Verb person index

0men — I
1biz — we
2sen — you (sg)
3siz — you (pl, polite)
4ol — he, she, it
5ala — they

The person index follows the engine's order (men, biz, sen, siz, ol, ala), not the order the word page shows its columns in.

Karachay in strings

Every Karachay string comes as a pair, as cyrillic and latin. The Cyrillic is the source. The Latin is derived from it by rule, in one direction only, so you never have to romanize anything yourself. Don't convert Latin back to Cyrillic: the rule loses information. For example, the dative of кюн is кюннге, with two н, and working backward from the Latin would give one.

Backticks mark Karachay inside English. A definition can quote a Karachay word in Cyrillic between backticks: to be made to stumble (passive of `абындырыргъа`). That is the only markup. It can appear in en, short, note and an example's translation. For plain text, remove the backticks and keep what is between them.

Slugs are Latin, lowercase and NFC. They keep the letters ç, ğ, ı, ö, ş and ü, and write the nasal ŋ as ng. That means a slug doesn't always match the displayed spelling. Take slugs from index.json instead of building them, and percent-encode them in URLs.

What is excluded

The API contains exactly what the site shows: published entries, senses and expressions. These are left out:

  • drafts, and material that hasn't been reviewed;
  • expression meanings marked as Balkar, and expressions with no published meaning;
  • unadapted Russian loans, which are kept as source evidence but not presented as Karachay words;
  • paradigm tables that the word page doesn't show;
  • quotations from the source dictionaries and per-sense source lists (the site cites its sources but doesn't reproduce them);
  • editorial fields, such as confidence, review status and corpus frequency.

Versioning

The version is part of the URL. Inside /api/v1/, changes are additive only. New fields and endpoints may appear, but an existing field won't be removed, renamed or given a new meaning. A breaking change would go to /api/v2/, and this tree would stay where it is. Ignore fields you don't recognize; don't treat them as errors.

The content itself changes as definitions are corrected, senses added and entries published. Each document has a dataVersion field. If a cached copy has the same dataVersion as meta.json, nothing in it has changed.

HTTP behavior

200The document, as application/json; charset=utf-8.
404No published entry has that slug or id. The body is the site's HTML not-found page, not JSON, so check the status before you parse.
CachingCache-Control: public, max-age=3600. A correction reaches you within an hour.
CORSAccess-Control-Allow-Origin: *, so you can call it from a browser on any site.
Limits None. These are static files, but please be considerate. One request to index.json costs less than 9,973 requests for word files. Only fetch a forms file for a word you are actually displaying, and cache what you fetch.

Not the API

The site serves two other machine-readable files. They aren't part of the API, and their format isn't guaranteed.

  • /data.json powers the search box, the analyzer and the word card. Its shape changes whenever those features do, and it is loaded with a version stamp. It replaced /search-index.json, /lexicon.json and /tagger.json in September 2026, and those addresses no longer exist.
  • /sitemap.xml is for search engines.

Build on /api/v1/ instead.

License and citation

The data is licensed under Creative Commons Attribution 4.0 International (CC-BY-4.0). You may copy it, build on it and use it commercially, as long as you credit it, link to the license and say what you changed. Use this credit line, which is also the attribution field in meta.json:

Attribution
Karachay dictionary (karachay.com) by Davud Kaplan, CC BY 4.0

In published work, cite the data version as well, because the dictionary keeps changing:

Citation
Karachay dictionary (karachay.com), data version 977e8dea, retrieved 2 October 2026.

The engine that generates the forms is a separate work under the MIT license. Nothing here licenses the source dictionaries; they remain the work of their authors and publishers. The abbreviations used in definitions are explained on abbreviations and conventions, and the two scripts on spelling and scripts.