{"openapi":"3.1.0","info":{"title":"masnavi.ai","description":"Rumi's Masnavi-ye Maʿnavi as a public REST + MCP service. 25,635 beyts across six daftars, sourced from ganjoor.net. Ten tools: search, search_meaning (semantic, any language), lookup, verify, get_section, get_range, find_sections, table_of_contents, random_beyt, explain. No authentication required. Designed for AI agents, Custom GPTs, Gemini Gems, and any HTTP client.","contact":{"name":"masnavi.ai","url":"https://masnavi.ai/"},"license":{"name":"Public Domain (source text)","url":"https://creativecommons.org/publicdomain/mark/1.0/"},"version":"0.9.48"},"servers":[{"url":"https://masnavi.ai","description":"Production"}],"paths":{"/api/search":{"get":{"tags":["rest"],"summary":"Search the Masnavi","description":"Full-text search across all 25,635 beyts of Rumi's Masnavi-ye Maʿnavi. Returns ranked results with canonical citations. Use this to find passages on a theme, word, or phrase.","operationId":"searchMasnavi","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":200,"description":"Persian text to search for. Diacritic-insensitive.","examples":["عشق","خاموش"],"title":"Q"},"description":"Persian text to search for. Diacritic-insensitive."},{"name":"daftar","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":6,"minimum":1},{"type":"null"}],"description":"Restrict to a single daftar (1-6).","title":"Daftar"},"description":"Restrict to a single daftar (1-6)."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"description":"Max results to return.","default":10,"title":"Limit"},"description":"Max results to return."},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Pagination offset.","default":0,"title":"Offset"},"description":"Pagination offset."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/search_meaning":{"get":{"tags":["rest"],"summary":"Search the Masnavi by meaning (any language)","description":"Semantic search: finds the beyts closest in MEANING to the query, not the ones containing its words. The query can be in ANY language — English, Persian, Spanish, Turkish, Arabic, … — e.g. 'feeling separated from your origin' → M1:1. Each hit carries a cosine-similarity score. Complements /api/search (lexical, Persian). status='unavailable' means the vector index is not built yet.","operationId":"searchMasnaviByMeaning","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":500,"description":"What the verse should MEAN, in any language.","examples":["feeling separated from your origin","غم دوری از وطن"],"title":"Q"},"description":"What the verse should MEAN, in any language."},{"name":"daftar","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":6,"minimum":1},{"type":"null"}],"description":"Restrict to a single daftar (1-6).","title":"Daftar"},"description":"Restrict to a single daftar (1-6)."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"description":"Max results to return.","default":10,"title":"Limit"},"description":"Max results to return."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeaningSearchResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/lookup":{"get":{"tags":["rest"],"summary":"Look up a specific beyt by citation","description":"Fetch a beyt by its canonical citation (e.g. 'M3:1278' = Daftar 3 beyt 1278), or by daftar+beyt_in_daftar, or by global index. Optionally include surrounding beyts for context.","operationId":"lookupBeyt","parameters":[{"name":"citation","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Citation, e.g. 'M3:1278' or 'g:7421'.","examples":["M1:1","M3:1278"],"title":"Citation"},"description":"Citation, e.g. 'M3:1278' or 'g:7421'."},{"name":"daftar","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":6,"minimum":1},{"type":"null"}],"description":"Daftar number 1-6 (use with beyt_in_daftar).","title":"Daftar"},"description":"Daftar number 1-6 (use with beyt_in_daftar)."},{"name":"beyt_in_daftar","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"description":"1-based beyt index within the daftar.","title":"Beyt In Daftar"},"description":"1-based beyt index within the daftar."},{"name":"beyt_global","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":25635,"minimum":1},{"type":"null"}],"description":"Global beyt index 1..25635.","title":"Beyt Global"},"description":"Global beyt index 1..25635."},{"name":"before","in":"query","required":false,"schema":{"type":"integer","maximum":20,"minimum":0,"description":"Beyts of context before.","default":0,"title":"Before"},"description":"Beyts of context before."},{"name":"after","in":"query","required":false,"schema":{"type":"integer","maximum":20,"minimum":0,"description":"Beyts of context after.","default":0,"title":"After"},"description":"Beyts of context after."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LookupResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/verify":{"get":{"tags":["rest"],"summary":"Verify a Rumi quote against the corpus (anti-hallucination)","description":"Given a candidate quote attributed to Rumi's Masnavi, check whether it actually appears. Returns status='exact' (with citation), 'fuzzy' (with similar candidates), or 'not_found'. Call this BEFORE repeating any quote you're not certain about.","operationId":"verifyQuote","parameters":[{"name":"text","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":500,"description":"Candidate Rumi quote in Persian.","examples":["بشنو این نی چون شکایت می‌کند"],"title":"Text"},"description":"Candidate Rumi quote in Persian."},{"name":"fuzzy_threshold","in":"query","required":false,"schema":{"type":"number","maximum":1.0,"minimum":0.5,"description":"Minimum similarity for fuzzy match (0.5-1.0).","default":0.82,"title":"Fuzzy Threshold"},"description":"Minimum similarity for fuzzy match (0.5-1.0)."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/section":{"get":{"tags":["rest"],"summary":"Retrieve a full section (story) of the Masnavi","description":"Fetch a named section (story / بخش) with all its beyts.","operationId":"getSection","parameters":[{"name":"slug","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Stable URL slug like 'd2-sh40'.","examples":["d1-sh1"],"title":"Slug"},"description":"Stable URL slug like 'd2-sh40'."},{"name":"section_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"description":"Numeric section id.","title":"Section Id"},"description":"Numeric section id."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SectionDetail"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/toc":{"get":{"tags":["rest"],"summary":"Browse the Masnavi's table of contents","description":"Returns the named sections (972 across 6 daftars) with beyt counts and global beyt ranges. Optionally restrict to one daftar.","operationId":"tableOfContents","parameters":[{"name":"daftar","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":6,"minimum":1},{"type":"null"}],"description":"Restrict to one daftar.","title":"Daftar"},"description":"Restrict to one daftar."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TocResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/range":{"get":{"tags":["rest"],"summary":"Fetch a contiguous range of beyts","description":"Returns ALL beyts between two endpoints (inclusive), grouped by section. Use this for fetching a full multi-section story in one call. Endpoints can be citations like 'M2:2608'/'M2:2775' or global indices. Max range: 500 beyts.","operationId":"getRange","parameters":[{"name":"start","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Start citation, e.g. 'M2:2608'.","title":"Start"},"description":"Start citation, e.g. 'M2:2608'."},{"name":"end","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"End citation, e.g. 'M2:2775'.","title":"End"},"description":"End citation, e.g. 'M2:2775'."},{"name":"start_global","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"title":"Start Global"}},{"name":"end_global","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"title":"End Global"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RangeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/find_sections":{"get":{"tags":["rest"],"summary":"Search section titles","description":"Find named sections by Persian title. Returns matching sections with slugs and beyt-global ranges. Combine with /api/range to fetch the full text of a multi-section story.","operationId":"findSections","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":200,"description":"Persian phrase to match against section titles","examples":["ابلیس معاویه"],"title":"Q"},"description":"Persian phrase to match against section titles"},{"name":"daftar","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":6,"minimum":1},{"type":"null"}],"title":"Daftar"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":30,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FindSectionsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/range.txt":{"get":{"tags":["rest"],"summary":"Plain-text download of a beyt range","description":"Returns the same content as /api/range but formatted as a human-readable plain-text document. Pass ?download=1 to receive as a downloadable .txt attachment instead of inline.","operationId":"getRangeText","parameters":[{"name":"start","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Start"}},{"name":"end","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"End"}},{"name":"start_global","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"title":"Start Global"}},{"name":"end_global","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"title":"End Global"}},{"name":"download","in":"query","required":false,"schema":{"type":"integer","description":"1 = attach as file","default":0,"title":"Download"},"description":"1 = attach as file"}],"responses":{"200":{"description":"Successful Response","content":{"text/plain":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/section.txt":{"get":{"tags":["rest"],"summary":"Plain-text download of a single section","description":"Plain-text variant of /api/section. Pass ?download=1 to attach.","operationId":"getSectionText","parameters":[{"name":"slug","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Slug"}},{"name":"section_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"title":"Section Id"}},{"name":"download","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Download"}}],"responses":{"200":{"description":"Successful Response","content":{"text/plain":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/random":{"get":{"tags":["rest"],"summary":"Random beyt from the Masnavi","description":"Returns a randomly-selected beyt, optionally restricted to a daftar.","operationId":"randomBeyt","parameters":[{"name":"daftar","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":6,"minimum":1},{"type":"null"}],"description":"Restrict to one daftar.","title":"Daftar"},"description":"Restrict to one daftar."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Beyt"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/divan/search":{"get":{"tags":["rest"],"summary":"Search the Divan-e Shams ghazals (full-text)","description":"Full-text search across the 34,603 beyts of the ghazals of Rumi's Divan-e Shams (Divan-e Kabir). Returns beyts with divan citations (G{ghazal}:{beyt}); each links to its whole ghazal at /divan/{ghazal}. Complements /api/search (the Masnavi).","operationId":"searchDivan","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":200,"description":"Persian text to search for.","examples":["مرده بدم زنده شدم"],"title":"Q"},"description":"Persian text to search for."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"default":10,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DivanSearchResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/divan/search_meaning":{"get":{"tags":["rest"],"summary":"Search the Divan-e Shams by meaning (any language)","description":"Semantic search over the ghazals: given a theme, feeling, or idea in ANY language, returns the GHAZALS closest in meaning — each with its best-matching couplet as a preview and a cosine score. Couplet-level and whole-ghazal vectors are both searched. status='unavailable' means the index is not built yet.","operationId":"searchDivanByMeaning","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":500,"description":"What the ghazal should be ABOUT, in any language.","examples":["dying to yourself and being reborn"],"title":"Q"},"description":"What the ghazal should be ABOUT, in any language."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":30,"minimum":1,"default":8,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DivanMeaningResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/divan/ghazal":{"get":{"tags":["rest"],"summary":"Fetch one complete ghazal of the Divan-e Shams","description":"Returns every beyt of one ghazal by its canonical number (1..3230), plus prev/next numbers. Famous example: number=1393 → «مرده بدم زنده شدم…».","operationId":"getGhazal","parameters":[{"name":"number","in":"query","required":true,"schema":{"type":"integer","minimum":1,"description":"Ghazal number, e.g. 1393.","title":"Number"},"description":"Ghazal number, e.g. 1393."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GhazalDetail"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/divan/random":{"get":{"tags":["rest"],"summary":"Random ghazal from the Divan-e Shams","operationId":"randomGhazal","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GhazalSummary"}}}}}}},"/api/":{"get":{"tags":["rest"],"summary":"API directory","description":"A small directory of available REST endpoints.","operationId":"apiIndex","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Apiindex"}}}}}}},"/api/beyt/{citation}/explanations":{"get":{"tags":["rest"],"summary":"Commentary for a specific beyt","operationId":"getBeytExplanations","parameters":[{"name":"citation","in":"path","required":true,"schema":{"type":"string","title":"Citation"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Getbeytexplanations"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"Beyt":{"properties":{"citation":{"type":"string","title":"Citation","description":"Canonical citation, e.g. 'M3:1278'"},"daftar":{"type":"integer","title":"Daftar"},"beyt_in_daftar":{"type":"integer","title":"Beyt In Daftar"},"beyt_global":{"type":"integer","title":"Beyt Global"},"mesra1":{"type":"string","title":"Mesra1","description":"First hemistich (with diacritics)"},"mesra2":{"type":"string","title":"Mesra2","description":"Second hemistich"},"section_id":{"type":"integer","title":"Section Id"},"section_title":{"type":"string","title":"Section Title"},"section_slug":{"type":"string","title":"Section Slug"}},"type":"object","required":["citation","daftar","beyt_in_daftar","beyt_global","mesra1","mesra2","section_id","section_title","section_slug"],"title":"Beyt"},"DivanMeaningHit":{"properties":{"ghazal":{"type":"integer","title":"Ghazal"},"citation":{"type":"string","title":"Citation"},"slug":{"type":"string","title":"Slug"},"title_fa":{"type":"string","title":"Title Fa"},"beyt_count":{"type":"integer","title":"Beyt Count"},"score":{"type":"number","title":"Score","description":"Best cosine similarity for this ghazal, 0..1"},"match_kind":{"type":"string","title":"Match Kind","description":"'beyt' (a couplet matched), 'ghazal' (the whole ghazal's theme matched), or 'both'"},"best_beyt":{"anyOf":[{"$ref":"#/components/schemas/GhazalBeyt"},{"type":"null"}]},"best_beyt_score":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Best Beyt Score"}},"type":"object","required":["ghazal","citation","slug","title_fa","beyt_count","score","match_kind"],"title":"DivanMeaningHit"},"DivanMeaningResponse":{"properties":{"query":{"type":"string","title":"Query"},"status":{"type":"string","title":"Status","default":"ok"},"total_indexed_beyts":{"type":"integer","title":"Total Indexed Beyts","default":0},"total_indexed_ghazals":{"type":"integer","title":"Total Indexed Ghazals","default":0},"results":{"items":{"$ref":"#/components/schemas/DivanMeaningHit"},"type":"array","title":"Results","default":[]},"note":{"type":"string","title":"Note","default":""}},"type":"object","required":["query"],"title":"DivanMeaningResponse"},"DivanSearchHit":{"properties":{"citation":{"type":"string","title":"Citation","description":"Canonical divan citation, e.g. 'G1393:1'"},"ghazal":{"type":"integer","title":"Ghazal"},"beyt_in_ghazal":{"type":"integer","title":"Beyt In Ghazal"},"mesra1":{"type":"string","title":"Mesra1"},"mesra2":{"type":"string","title":"Mesra2"},"ghazal_title":{"type":"string","title":"Ghazal Title"},"rank":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Rank"}},"type":"object","required":["citation","ghazal","beyt_in_ghazal","mesra1","mesra2","ghazal_title"],"title":"DivanSearchHit"},"DivanSearchResponse":{"properties":{"query":{"type":"string","title":"Query"},"total":{"type":"integer","title":"Total"},"results":{"items":{"$ref":"#/components/schemas/DivanSearchHit"},"type":"array","title":"Results"},"match":{"type":"string","title":"Match","default":"exact"}},"type":"object","required":["query","total","results"],"title":"DivanSearchResponse"},"FindSectionsResponse":{"properties":{"query":{"type":"string","title":"Query"},"total":{"type":"integer","title":"Total"},"sections":{"items":{"$ref":"#/components/schemas/SectionMatch"},"type":"array","title":"Sections","default":[]},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"}},"type":"object","required":["query","total"],"title":"FindSectionsResponse"},"GhazalBeyt":{"properties":{"citation":{"type":"string","title":"Citation","description":"Canonical divan citation, e.g. 'G1393:1'"},"ghazal":{"type":"integer","title":"Ghazal"},"beyt_in_ghazal":{"type":"integer","title":"Beyt In Ghazal"},"mesra1":{"type":"string","title":"Mesra1"},"mesra2":{"type":"string","title":"Mesra2"}},"type":"object","required":["citation","ghazal","beyt_in_ghazal","mesra1","mesra2"],"title":"GhazalBeyt"},"GhazalDetail":{"properties":{"ghazal":{"type":"integer","title":"Ghazal","description":"Canonical ghazal number, 1..3230"},"citation":{"type":"string","title":"Citation","description":"'G{n}' — cites the whole ghazal"},"slug":{"type":"string","title":"Slug"},"title_fa":{"type":"string","title":"Title Fa"},"beyt_count":{"type":"integer","title":"Beyt Count"},"excerpt":{"type":"string","title":"Excerpt","description":"First hemistich of the ghazal","default":""},"beyts":{"items":{"$ref":"#/components/schemas/GhazalBeyt"},"type":"array","title":"Beyts","default":[]},"prev_ghazal":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Prev Ghazal"},"next_ghazal":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Next Ghazal"}},"type":"object","required":["ghazal","citation","slug","title_fa","beyt_count"],"title":"GhazalDetail"},"GhazalSummary":{"properties":{"ghazal":{"type":"integer","title":"Ghazal","description":"Canonical ghazal number, 1..3230"},"citation":{"type":"string","title":"Citation","description":"'G{n}' — cites the whole ghazal"},"slug":{"type":"string","title":"Slug"},"title_fa":{"type":"string","title":"Title Fa"},"beyt_count":{"type":"integer","title":"Beyt Count"},"excerpt":{"type":"string","title":"Excerpt","description":"First hemistich of the ghazal","default":""}},"type":"object","required":["ghazal","citation","slug","title_fa","beyt_count"],"title":"GhazalSummary"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"LookupResponse":{"properties":{"primary":{"$ref":"#/components/schemas/Beyt"},"context_before":{"items":{"$ref":"#/components/schemas/Beyt"},"type":"array","title":"Context Before","default":[]},"context_after":{"items":{"$ref":"#/components/schemas/Beyt"},"type":"array","title":"Context After","default":[]}},"type":"object","required":["primary"],"title":"LookupResponse"},"MeaningHit":{"properties":{"citation":{"type":"string","title":"Citation","description":"Canonical citation, e.g. 'M3:1278'"},"daftar":{"type":"integer","title":"Daftar"},"beyt_in_daftar":{"type":"integer","title":"Beyt In Daftar"},"beyt_global":{"type":"integer","title":"Beyt Global"},"mesra1":{"type":"string","title":"Mesra1","description":"First hemistich (with diacritics)"},"mesra2":{"type":"string","title":"Mesra2","description":"Second hemistich"},"section_id":{"type":"integer","title":"Section Id"},"section_title":{"type":"string","title":"Section Title"},"section_slug":{"type":"string","title":"Section Slug"},"score":{"type":"number","title":"Score","description":"Cosine similarity between query and beyt, 0..1"}},"type":"object","required":["citation","daftar","beyt_in_daftar","beyt_global","mesra1","mesra2","section_id","section_title","section_slug","score"],"title":"MeaningHit"},"MeaningSearchResponse":{"properties":{"query":{"type":"string","title":"Query"},"status":{"type":"string","title":"Status","description":"'ok' | 'unavailable' (index not built / no key) | 'error'","default":"ok"},"total_indexed":{"type":"integer","title":"Total Indexed","default":0},"results":{"items":{"$ref":"#/components/schemas/MeaningHit"},"type":"array","title":"Results","default":[]},"note":{"type":"string","title":"Note","default":""}},"type":"object","required":["query"],"title":"MeaningSearchResponse"},"RangeResponse":{"properties":{"start_citation":{"type":"string","title":"Start Citation"},"end_citation":{"type":"string","title":"End Citation"},"total_beyts":{"type":"integer","title":"Total Beyts"},"total_sections":{"type":"integer","title":"Total Sections"},"sections":{"items":{"$ref":"#/components/schemas/RangeSection"},"type":"array","title":"Sections","default":[]}},"type":"object","required":["start_citation","end_citation","total_beyts","total_sections"],"title":"RangeResponse"},"RangeSection":{"properties":{"section_id":{"type":"integer","title":"Section Id"},"slug":{"type":"string","title":"Slug"},"title_fa":{"type":"string","title":"Title Fa"},"daftar":{"type":"integer","title":"Daftar"},"order_in_parent":{"type":"integer","title":"Order In Parent"},"beyts":{"items":{"$ref":"#/components/schemas/Beyt"},"type":"array","title":"Beyts","default":[]}},"type":"object","required":["section_id","slug","title_fa","daftar","order_in_parent"],"title":"RangeSection"},"SearchHit":{"properties":{"citation":{"type":"string","title":"Citation","description":"Canonical citation, e.g. 'M3:1278'"},"daftar":{"type":"integer","title":"Daftar"},"beyt_in_daftar":{"type":"integer","title":"Beyt In Daftar"},"beyt_global":{"type":"integer","title":"Beyt Global"},"mesra1":{"type":"string","title":"Mesra1","description":"First hemistich (with diacritics)"},"mesra2":{"type":"string","title":"Mesra2","description":"Second hemistich"},"section_id":{"type":"integer","title":"Section Id"},"section_title":{"type":"string","title":"Section Title"},"section_slug":{"type":"string","title":"Section Slug"},"rank":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Rank"}},"type":"object","required":["citation","daftar","beyt_in_daftar","beyt_global","mesra1","mesra2","section_id","section_title","section_slug"],"title":"SearchHit"},"SearchResponse":{"properties":{"query":{"type":"string","title":"Query"},"total":{"type":"integer","title":"Total"},"results":{"items":{"$ref":"#/components/schemas/SearchHit"},"type":"array","title":"Results"},"match":{"type":"string","title":"Match","default":"exact"}},"type":"object","required":["query","total","results"],"title":"SearchResponse"},"SectionDetail":{"properties":{"id":{"type":"integer","title":"Id"},"slug":{"type":"string","title":"Slug"},"title_fa":{"type":"string","title":"Title Fa"},"daftar":{"type":"integer","title":"Daftar"},"first_beyt_global":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"First Beyt Global"},"last_beyt_global":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Last Beyt Global"},"beyt_count":{"type":"integer","title":"Beyt Count","default":0},"beyts":{"items":{"$ref":"#/components/schemas/Beyt"},"type":"array","title":"Beyts","default":[]}},"type":"object","required":["id","slug","title_fa","daftar"],"title":"SectionDetail"},"SectionMatch":{"properties":{"id":{"type":"integer","title":"Id"},"slug":{"type":"string","title":"Slug"},"title_fa":{"type":"string","title":"Title Fa"},"daftar":{"type":"integer","title":"Daftar"},"order_in_parent":{"type":"integer","title":"Order In Parent"},"first_beyt_global":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"First Beyt Global"},"last_beyt_global":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Last Beyt Global"},"first_citation":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Citation"},"last_citation":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Citation"},"beyt_count":{"type":"integer","title":"Beyt Count","default":0},"match":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Match"},"score":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Score"}},"type":"object","required":["id","slug","title_fa","daftar","order_in_parent"],"title":"SectionMatch"},"TocNode":{"properties":{"id":{"type":"integer","title":"Id"},"slug":{"type":"string","title":"Slug"},"title_fa":{"type":"string","title":"Title Fa"},"daftar":{"type":"integer","title":"Daftar"},"first_beyt_global":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"First Beyt Global"},"last_beyt_global":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Last Beyt Global"},"beyt_count":{"type":"integer","title":"Beyt Count","default":0},"children":{"items":{"$ref":"#/components/schemas/TocNode"},"type":"array","title":"Children","default":[]}},"type":"object","required":["id","slug","title_fa","daftar"],"title":"TocNode"},"TocResponse":{"properties":{"daftar":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Daftar"},"nodes":{"items":{"$ref":"#/components/schemas/TocNode"},"type":"array","title":"Nodes"}},"type":"object","required":["nodes"],"title":"TocResponse"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"VerifyMatch":{"properties":{"citation":{"type":"string","title":"Citation"},"mesra1":{"type":"string","title":"Mesra1"},"mesra2":{"type":"string","title":"Mesra2"},"similarity":{"type":"number","title":"Similarity"},"match_kind":{"type":"string","title":"Match Kind","description":"'exact' or 'fuzzy'"}},"type":"object","required":["citation","mesra1","mesra2","similarity","match_kind"],"title":"VerifyMatch"},"VerifyResponse":{"properties":{"status":{"type":"string","title":"Status","description":"'exact', 'fuzzy', or 'not_found'"},"matches":{"items":{"$ref":"#/components/schemas/VerifyMatch"},"type":"array","title":"Matches","default":[]},"notes":{"type":"string","title":"Notes","default":""},"query_normalized":{"type":"string","title":"Query Normalized","default":""}},"type":"object","required":["status"],"title":"VerifyResponse"}}}}