{"openapi":"3.0.3","info":{"title":"Dhamma.gift search API","version":"1.0.0","description":"Поиск по палийскому канону (Sutta/Vinaya) — API для dg-light.js. Все ответы — JSON."},"servers":[{"url":"/","description":"Текущий сервер"}],"tags":[{"name":"search","description":"Поиск по ключевому слову"},{"name":"text","description":"Полный текст сутты для ридера"},{"name":"toc","description":"Оглавление и структура текстов"},{"name":"tts","description":"Озвучка (Voice API) — api.dhamma.gift"},{"name":"mcp","description":"MCP-сервер для ИИ-агентов"},{"name":"uposatha","description":"Календарь упосатх"}],"components":{"parameters":{"scope":{"name":"scope","in":"query","description":"Область поиска. Составные значения: `default` (или вообще не передавать параметр) — 4 никаи + 6 книг Кхуддаки, без Винаи/Абхидхаммы. `all` — весь корпус. Категории (каждая — целый верхнеуровневый раздел): `dhamma` — только 4 никаи (Дигха, Маджджхима, Саньютта, Ангуттара). `khudakka` — вся Кхуддака Никая (все её книги, не только 6 из `default`). `vinaya` — вся Виная-питака. `abhi` — Абхидхамма. Можно также перечислить конкретные id книг/собраний через запятую, вперемешку с категориями (например `dn,mn` или `dhamma,vinaya`) — id: `dn`, `mn`, `sn`, `an` (4 никаи); `ud`, `snp`, `dhp`, `thag`, `thig`, `iti`, `ja`, `tha-ap`, `thi-ap`, `mil`, `vv`, `pv`, `cp`, `bv`, `ps`, `ne`, `cnd`, `mnd`, `kp`, `pe` (Кхуддака Никая); `pli-tv-bi`, `pli-tv-bu`, `pli-tv-kd`, `pli-tv-pvr` (Виная).","schema":{"type":"string","default":"default","example":"dhamma"}},"exact":{"name":"exact","in":"query","description":"Точное совпадение слова целиком (grep -w), а не подстроки.","schema":{"type":"boolean","default":false}},"langs":{"name":"langs","in":"query","description":"Языки переводов через запятую. `all` — все доступные языки.","schema":{"type":"string","default":"ru,en","example":"ru,en"}},"lb":{"name":"lb","in":"query","description":"Число строк контекста ДО найденного сегмента (Пали root-текст).","schema":{"type":"integer","default":0,"minimum":0}},"la":{"name":"la","in":"query","description":"Число строк контекста ПОСЛЕ найденного сегмента (Пали root-текст).","schema":{"type":"integer","default":0,"minimum":0}}},"schemas":{"SearchMetadata":{"type":"object","properties":{"query":{"type":"string"},"scope":{"type":"string"},"langs":{"type":"array","items":{"type":"string"}},"lb":{"type":"integer"},"la":{"type":"integer"},"exactMatch":{"type":"boolean"},"totalFiles":{"type":"integer","description":"Число найденных сутт"},"totalMatches":{"type":"integer","description":"Суммарное число совпадений"},"hasVariantMatch":{"type":"boolean","description":"Есть ли варианты чтения для этого слова где-либо в корпусе (не только в текущем scope)"},"partial":{"type":"boolean","description":"true — это ответ ?fast=1, root-текст/переводы для части сегментов ещё не подгружены (см. /search/enrich)"},"tooShort":{"type":"boolean","description":"true — keyword короче минимальной длины (3 символа), поиск не выполнялся"}}},"Segment":{"type":"object","properties":{"segment":{"type":"string","example":"dn1:1.1"},"root_text":{"type":"string","description":"Пали, root-чтение"},"variant":{"type":"string","description":"Пали, вариантное чтение (если есть)"},"translations":{"type":"object","description":"Ключ вида \"ru_khantibalo\", \"en_sujato\" -> текст перевода","additionalProperties":{"type":"string"}},"html":{"type":"string"},"lb_context":{"type":"array","items":{"type":"object"}},"la_context":{"type":"array","items":{"type":"object"}}}},"SuttaResult":{"type":"object","properties":{"sutta_id":{"type":"string","example":"dn1"},"category":{"type":"string","enum":["dhamma","khudakka","vinaya","abhi","other"]},"dir_path":{"type":"string"},"titles":{"type":"object","additionalProperties":{"type":"string"}},"mr":{"type":"integer","description":"Ранг версии/релевантности (mtph из textinfo)"},"count":{"type":"integer","description":"Число совпадений в этой сутте"},"unique_words":{"type":"array","items":{"type":"string"}},"segments":{"type":"array","items":{"$ref":"#/components/schemas/Segment"}}}},"WordReportEntry":{"type":"object","properties":{"word":{"type":"string"},"textCount":{"type":"integer"},"matchCount":{"type":"integer"},"links":{"type":"array","items":{"type":"object","properties":{"sutta_id":{"type":"string"},"segment":{"type":"string"}}}}}},"VariantSegment":{"type":"object","description":"Сегмент, где keyword встречается в вариантном (не root) чтении — текст берётся из variant-файла как есть, включая редакторскую нотацию SuttaCentral (\"→\", \"(mr)\", \"(?)\").","properties":{"sutta_id":{"type":"string"},"segment":{"type":"string"},"text":{"type":"string","example":"Macchakacchapasañchannā → macchakacchapasampannā (?) "}}},"SearchResponse":{"type":"object","properties":{"metadata":{"$ref":"#/components/schemas/SearchMetadata"},"data":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/SuttaResult"}},"wordReport":{"type":"array","items":{"$ref":"#/components/schemas/WordReportEntry"}},"variantSegments":{"type":"array","items":{"$ref":"#/components/schemas/VariantSegment"}}}},"Error":{"type":"object","properties":{"error":{"type":"string"}}}}},"paths":{"/search":{"get":{"tags":["search"],"summary":"Поиск по ключевому слову","description":"Без `?fast=1` — полный ответ (root-текст/переводы для всех найденных сегментов, wordReport, variantSegments). С `?fast=1` — быстрый частичный ответ (только skeleton + wordReport + variantSegments, без чтения файлов сутт) — используется для мгновенного первого рендера, полные данные потом дозагружаются через /search/enrich.","parameters":[{"name":"q","in":"query","required":true,"description":"Искомое слово/фраза. Минимум 3 символа — короче игнорируется (см. `tooShort` в ответе).","schema":{"type":"string"},"example":"kacchapa"},{"$ref":"#/components/parameters/scope"},{"$ref":"#/components/parameters/exact"},{"$ref":"#/components/parameters/langs"},{"$ref":"#/components/parameters/lb"},{"$ref":"#/components/parameters/la"},{"name":"fast","in":"query","description":"`1` — быстрый частичный ответ без чтения файлов сутт (см. описание выше).","schema":{"type":"string","enum":["1"]}}],"responses":{"200":{"description":"Результат поиска","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}},"400":{"description":"Не передан q","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/search/{keyword}":{"get":{"tags":["search"],"summary":"То же самое, что /search?q={keyword} — keyword как часть пути","description":"Короткие ссылки: /search/kacchapa?scope=dhamma работает наравне с /search?q=kacchapa&scope=dhamma. Остальные параметры — те же query-параметры, что у /search.","parameters":[{"name":"keyword","in":"path","required":true,"schema":{"type":"string"},"example":"kacchapa"},{"$ref":"#/components/parameters/scope"},{"$ref":"#/components/parameters/exact"},{"$ref":"#/components/parameters/langs"},{"$ref":"#/components/parameters/lb"},{"$ref":"#/components/parameters/la"},{"name":"fast","in":"query","schema":{"type":"string","enum":["1"]}}],"responses":{"200":{"description":"Результат поиска","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}}}}},"/search/enrich":{"get":{"tags":["search"],"summary":"Догрузить полные данные (root-текст/переводы) для конкретных id сутт","description":"Вызывается вслед за /search?fast=1 с id сутт, которые нужно \"дообогатить\" — например видимую страницу таблицы, или сразу все найденные id разом. keyword/scope должны совпадать с исходным вызовом /search?fast=1 (иначе будет считаться заново, без переиспользования кеша).","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string"},"example":"kacchapa"},{"name":"ids","in":"query","required":true,"description":"Id сутт через запятую.","schema":{"type":"string"},"example":"dn1,dn2,sn35.240"},{"$ref":"#/components/parameters/scope"},{"$ref":"#/components/parameters/exact"},{"$ref":"#/components/parameters/langs"},{"$ref":"#/components/parameters/lb"},{"$ref":"#/components/parameters/la"}],"responses":{"200":{"description":"Данные по запрошенным id (та же форма, что и data[id] у /search) плюс актуальные wordReport/metadata/variantSegments","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}},"400":{"description":"Не передан q или ids","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/text/{suttaId}":{"get":{"tags":["text"],"summary":"Полный текст сутты (все сегменты, не только совпадения) — для ридера","parameters":[{"name":"suttaId","in":"path","required":true,"schema":{"type":"string"},"example":"dn22"},{"$ref":"#/components/parameters/langs"},{"name":"translators","in":"query","description":"Явный список переводчиков через запятую (например `ru_o,ru_sv`) — два перевода ОДНОГО языка одновременно, в обход обычного выбора \"один переводчик на язык\".","schema":{"type":"string"}}],"responses":{"200":{"description":"Полный текст сутты","content":{"application/json":{"schema":{"type":"object","properties":{"sutta_id":{"type":"string"},"category":{"type":"string"},"dir_path":{"type":"string"},"title":{"type":"string"},"mr":{"type":"integer"},"segments":{"type":"array","items":{"$ref":"#/components/schemas/Segment"}}}}}}},"404":{"description":"Неизвестный id сутты","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/nav/{suttaId}":{"get":{"tags":["text"],"summary":"Предыдущая/следующая сутта для навигации в ридере","parameters":[{"name":"suttaId","in":"path","required":true,"schema":{"type":"string"},"example":"dn22"}],"responses":{"200":{"description":"Соседние сутты по порядку в skeletonDB","content":{"application/json":{"schema":{"type":"object","properties":{"prev":{"type":"object","nullable":true,"properties":{"slug":{"type":"string"},"title":{"type":"string"}}},"next":{"type":"object","nullable":true,"properties":{"slug":{"type":"string"},"title":{"type":"string"}}}}}}}},"404":{"description":"Неизвестный id сутты","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/toc":{"get":{"tags":["toc"],"summary":"Дерево категорий/книг оглавления (Sutta/Vinaya и их разделы)","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"categories":{"type":"array","items":{"type":"object"}}}}}}}}}},"/api/toc/book/{code}":{"get":{"tags":["toc"],"summary":"Полное дерево одной книги, опционально с переводчиками по языкам","parameters":[{"name":"code","in":"path","required":true,"schema":{"type":"string"},"example":"dn"},{"name":"langs","in":"query","required":false,"schema":{"type":"string"},"description":"Языки через запятую — для каких показать доступных переводчиков","example":"ru,en"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string"},"tree":{"type":"array","items":{"type":"object"}},"translations":{"type":"object"},"interlinearKeys":{"type":"array","items":{"type":"string"}}}}}}},"404":{"description":"Неизвестный код книги","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/transliterate":{"get":{"tags":["text"],"summary":"Транслитерация введённого текста в IAST (латиница с диакритикой)","parameters":[{"name":"text","in":"query","required":true,"schema":{"type":"string"},"example":"kamma"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string"},"converted":{"type":"boolean"}}}}}}}}},"/api/patimokkha-fragment/{side}":{"get":{"tags":["text"],"summary":"HTML-фрагмент Патимоккхи (bu — бхиккху, bi — бхиккхуни) для сравнения редакций","parameters":[{"name":"side","in":"path","required":true,"schema":{"type":"string","enum":["bu","bi"]},"example":"bu"}],"responses":{"200":{"description":"OK","content":{"text/html":{"schema":{"type":"string"}}}},"404":{"description":"Некорректный side"}}}},"/api/tts/pali":{"servers":[{"url":"https://api.dhamma.gift","description":"api.dhamma.gift"}],"post":{"tags":["tts"],"summary":"Озвучить фразу (MP3 в base64)","description":"Открытый сервис озвучки без ключа, CORS открыт, 60 запросов в минуту с IP. Ответ в формате Google Text-to-Speech.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["text"],"properties":{"text":{"type":"string","maxLength":2000,"description":"Текст: пали в IAST, перевод на английском или русском","example":"Evaṁ me sutaṁ."},"voice":{"type":"string","default":"pratham","description":"Голос, список — GET /api/tts/dg-voices","example":"pratham"},"rate":{"type":"number","minimum":0.25,"maximum":3,"default":1,"description":"Скорость; на сайте пали читается на 0.875","example":0.875}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"audioContent":{"type":"string","description":"base64 MP3, mono, 22 kHz"}}}}}},"400":{"description":"Неизвестный голос, пустой текст или неверный запрос","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"429":{"description":"Превышен лимит запросов"}}}},"/api/tts/memo":{"servers":[{"url":"https://api.dhamma.gift","description":"api.dhamma.gift"}],"post":{"tags":["tts"],"summary":"Текст целиком одним MP3 с паузами (Memo)","description":"Строки читаются подряд с паузами любой длины. Речь — до 30 минут (паузы не считаются), вся запись с паузами — до 180 минут; до 200 строк и 20 000 символов. Считается как 10 запросов в лимите.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["segments"],"properties":{"segments":{"type":"array","items":{"type":"string"},"maxItems":200,"description":"Строки, всего до 20 000 символов","example":["Evaṁ me sutaṁ.","Ekaṁ samayaṁ bhagavā…"]},"voice":{"type":"string","default":"pratham"},"rate":{"type":"number","default":1},"delay":{"type":"number","maximum":3600,"description":"Пауза между строками, секунды","example":2},"end_delay":{"type":"number","maximum":3600,"description":"Пауза в конце, секунды","example":0},"sound":{"type":"string","enum":["","gong.mp3","tick.mp3"],"description":"Звук в конце"}}}}}},"responses":{"200":{"description":"MP3","content":{"audio/mpeg":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Неизвестный голос или пустой текст","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"413":{"description":"Превышен лимит: паузы, число строк/символов или длина записи","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"429":{"description":"Превышен лимит запросов"}}}},"/api/tts/dg-voices":{"servers":[{"url":"https://api.dhamma.gift","description":"api.dhamma.gift"}],"get":{"tags":["tts"],"summary":"Список голосов","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"voices":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"lang":{"type":"string"},"label":{"type":"string"}}}}}}}}}},"description":"Порядок — как в меню; первый голос языка — голос по умолчанию; lang: pi, en, ru."}},"/api/tts/health":{"servers":[{"url":"https://api.dhamma.gift","description":"api.dhamma.gift"}],"get":{"tags":["tts"],"summary":"Сервис жив, версия правил произношения","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"loaded":{"type":"array","items":{"type":"string"}},"rules":{"type":"string"}}}}}}}}},"/mcp":{"servers":[{"url":"https://api.dhamma.gift","description":"api.dhamma.gift"}],"post":{"tags":["mcp"],"summary":"MCP-сервер для ИИ-агентов (JSON-RPC, Streamable HTTP)","description":"Инструменты: search, get_text, compare_translations, list_structure. По умолчанию только пали; переводы — langs или translators. Подключение в Claude: Settings → Connectors → https://api.dhamma.gift/mcp. Нужен заголовок Accept: application/json, text/event-stream.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"examples":{"tools/list":{"value":{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}},"get_text":{"value":{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"get_text","arguments":{"suttaId":"sn56.11","langs":["ru"]}}}},"search":{"value":{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"search","arguments":{"query":"kata.*dukkh","include_segments":true}}}}}}}},"responses":{"200":{"description":"JSON-RPC ответ (text/event-stream: строки «data: {...}»)"}}}},"/uposatha.ics":{"get":{"tags":["uposatha"],"summary":"Подписка на календарь упосатх (iCalendar для Google/Apple)","description":"Без хранения: всё, что нужно ленте, — в адресе. Дни на 400 дней вперёд, напоминания; лента пересчитывается раз в час.","parameters":[{"name":"tz","in":"query","required":false,"description":"Часовой пояс IANA","schema":{"type":"string"},"example":"Europe/Moscow"},{"name":"lang","in":"query","required":false,"description":"Язык событий","schema":{"type":"string","enum":["en","ru"]},"example":"ru"},{"name":"lat","in":"query","required":false,"description":"Широта (для рассвета и восхода луны)","schema":{"type":"number"},"example":55.75},{"name":"lon","in":"query","required":false,"description":"Долгота","schema":{"type":"number"},"example":37.62},{"name":"scheme","in":"query","required":false,"description":"sutta — по суттам (по умолчанию), modern — современный календарь","schema":{"type":"string","enum":["sutta","modern"]}},{"name":"lead","in":"query","required":false,"description":"За сколько часов напоминать (0–72, по умолчанию 24)","schema":{"type":"integer"},"example":24},{"name":"d8","in":"query","required":false,"description":"Дни 8-й луны: 0 — не включать","schema":{"type":"string","enum":["0","1"]}},{"name":"d14","in":"query","required":false,"description":"Дни 14-й луны: 0 — не включать","schema":{"type":"string","enum":["0","1"]}},{"name":"d15","in":"query","required":false,"description":"Дни 15-й луны: 1 — включать","schema":{"type":"string","enum":["0","1"]}},{"name":"day","in":"query","required":false,"description":"Второе напоминание в сам день, ЧЧММ","schema":{"type":"string"},"example":"0600"},{"name":"adv","in":"query","required":false,"description":"С day=: 0 — без напоминания заранее","schema":{"type":"string","enum":["0","1"]}}],"responses":{"200":{"description":"iCalendar","content":{"text/calendar":{"schema":{"type":"string"}}}},"400":{"description":"Неверный часовой пояс"}}}},"/api/ai-search":{"get":{"tags":["search"],"summary":"ИИ-поиск: вопрос своими словами → сутты","description":"Когда точный поиск ничего не нашёл: слова пали из словаря DPD, иначе смысловой поиск. Ответ — сутты и подсказки слов. Медленнее обычного поиска (секунды).","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string"},"example":"черепаха"},{"name":"lang","in":"query","required":false,"description":"Язык подсказок слов (язык интерфейса)","schema":{"type":"string","enum":["ru","en"]},"example":"ru"},{"name":"scope","in":"query","required":false,"description":"Область, как у /search","schema":{"type":"string"},"example":"default"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"query":{"type":"string"},"suttas":{"type":"array","items":{"type":"object"}},"wordSuggestions":{"type":"array","items":{"type":"object"}}}}}}}}}}}}