{"openapi":"3.1.0","info":{"title":"AcuiQ API","version":"2.1.0","description":"Acupuncture protocol matching API. Search symptoms, browse meridians, find treatment protocols and search the reference wiki – no account and no API key. Two bulk exports carry a per-request charge over MPP (Machine Payments Protocol), paid through Stripe; every per-query endpoint is free. Licence scope: AcuiQ-authored prose (symptom and meridian descriptions, the wiki, the auricular crosswalk) is licensed CC-BY-4.0: https://creativecommons.org/licenses/by/4.0/. The assembled protocol compilation is not: build on it with attribution, but do not redistribute it whole as a dataset – https://acuiq.com/terms. The underlying findings are the cited sources' claims – each entry carries its citation; verify against the source before relying on it. Not medical advice: https://acuiq.com/terms","contact":{"name":"AcuiQ","url":"https://acuiq.com"},"license":{"name":"Creative Commons Attribution 4.0 International","identifier":"CC-BY-4.0"}},"servers":[{"url":"https://acuiq.com","description":"Production"}],"paths":{"/api/symptoms":{"get":{"operationId":"searchSymptoms","summary":"Search or list symptoms","description":"Fuzzy-search symptom names or get trending symptoms. Rows are identical to the MCP search_symptoms tool. Rate limit: 500 req/min.","parameters":[{"name":"query","in":"query","schema":{"type":"string"},"description":"Partial symptom name (e.g. \"head\")"},{"name":"popular","in":"query","schema":{"type":"string","enum":["true"]},"description":"Set to \"true\" to get top 12 trending symptoms"},{"name":"points","in":"query","schema":{"type":"string","enum":["1"]},"description":"Set to \"1\" to append matching acupoints (by code, name, Chinese name or pinyin) as rows with kind: \"point\""}],"responses":{"200":{"description":"Symptom rows","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SymptomListResponse"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/meridians":{"get":{"operationId":"getMeridians","summary":"List all meridians","description":"Returns all TCM meridians with descriptions and element associations. The whole point catalogue in one response. Rate limit: 100 req/min. Priced at $0.50 over MPP (Machine Payments Protocol); a payment does not lift the rate limit, and a throttled payment is refunded.","x-payment-info":{"method":"stripe","intent":"charge","amount":"50","currency":"usd","description":"The whole AcuiQ point catalogue in one response."},"security":[{"payment":[]}],"responses":{"200":{"description":"Meridian list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeridianListResponse"}}}},"402":{"description":"Payment required. The WWW-Authenticate: Payment header carries the challenge; the body states the price and lists the free alternatives.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/protocols":{"get":{"operationId":"searchProtocols","summary":"Search treatment protocols by symptoms","description":"Find acupuncture protocols matching the given symptoms, optionally filtered by age and sex. Returns up to 50 matches ranked by relevance, each carrying provenance (sourceKind, source, caveat). The same ranked pipeline as the MCP search_protocols tool, which returns a compact projection of these rows. Rate limit: 200 req/min.","parameters":[{"name":"symptoms","in":"query","required":true,"schema":{"type":"string"},"description":"Comma-separated symptom names (max 10)"},{"name":"age","in":"query","schema":{"type":"number","minimum":0,"maximum":130},"description":"Patient age"},{"name":"sex","in":"query","schema":{"type":"string","enum":["male","female"]},"description":"Patient sex"}],"responses":{"200":{"description":"Matching protocols","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResultResponse"}}}},"400":{"description":"Invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/wiki":{"get":{"operationId":"searchWiki","summary":"Search the reference wiki","description":"Keyword search over wiki titles and prose, with an English full-text fallback for questions the literal match cannot answer. Ranked titles starting with the term, titles containing it, literal prose hits, then full-text hits by relevance. Rows are identical to the MCP search_wiki tool. Rate limit: 60 req/min.","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string"},"description":"A keyword, phrase or question (e.g. \"moxibustion\")"},{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"pageSize","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":10}}],"responses":{"200":{"description":"Matching pages","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WikiSearchResponse"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/checkout":{"post":{"operationId":"createCheckout","summary":"Create a Stripe checkout session","description":"Initiates a purchase of one AcuiQ product. Agents should prefer the create_checkout MCP tool, which wraps this handler and returns the Checkout URL for a human to complete.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["product"],"properties":{"product":{"type":"string","enum":["press-needles","treatment-guide","practitioner-edition","point-reference","atlas-charts","corpus-licence","mini-headache","mini-back","mini-neck-joints","mini-sleep-mood","mini-digestion","mini-ear-eye","mini-skin-nerves","mini-womens","mini-heart","mini-urinary"],"description":"Product to purchase"},"quantity":{"type":"integer","minimum":1,"maximum":20,"default":1,"description":"Quantity (physical products only; a digital product is always 1)"},"source":{"type":"string","description":"Optional: the page path the buyer came from, recorded in the session metadata so the sale can be attributed. Never personal data."}}}}}},"responses":{"200":{"description":"Checkout session URL","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"url":{"type":"string","format":"uri","nullable":true},"sessionId":{"type":"string","description":"Stripe Checkout session id; pass to the get_order MCP tool to confirm payment and retrieve the delivery link"}}}}}}}},"400":{"description":"Invalid product","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/reviews":{"post":{"operationId":"submitProductRating","summary":"Submit a 1–5 star product rating","description":"Records one genuine rating per order per product (re-rating updates, never inflates the count). Needs the order token from the buyer's download page. Returns the fresh aggregate. Rate limit: 20 req/min.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["product","rating","token"],"properties":{"product":{"type":"string","enum":["press-needles","treatment-guide","practitioner-edition","point-reference","atlas-charts","corpus-licence","mini-headache","mini-back","mini-neck-joints","mini-sleep-mood","mini-digestion","mini-ear-eye","mini-skin-nerves","mini-womens","mini-heart","mini-urinary"]},"rating":{"type":"integer","minimum":1,"maximum":5},"token":{"type":"string","description":"The order token, the last segment of the download page URL"}}}}}},"responses":{"200":{"description":"Fresh aggregate","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"average":{"type":"number"},"count":{"type":"integer"}}}}}}}},"400":{"description":"Invalid product, rating or order token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/mcp":{"post":{"operationId":"mcpServer","summary":"Model Context Protocol server – JSON-RPC 2.0 over streamable HTTP. Tools: search_symptoms, search_protocols, get_meridians, get_symptom_detail, get_point, create_checkout, get_order, search_wiki, get_page, get_pages, list_pages, get_categories, get_recent_changes, get_full_corpus, get_page_history.","description":"MCP 2026-07-28, 2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05, on one endpoint. Batch requests capped at 20. Rate limit: 60 requests per minute per IP.","requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"JSON-RPC response"}}}},"/llms.txt":{"get":{"operationId":"getLlmsTxt","summary":"LLM briefing document – overview, products, licence, symptom index","description":"Serves ETag and Last-Modified; conditional requests are answered with 304.","responses":{"200":{"description":"Plain text briefing","content":{"text/plain":{}}},"304":{"description":"Not modified"}}}},"/api/corpus":{"get":{"operationId":"getCorpus","summary":"The complete protocol corpus as JSONL","description":"Every extracted protocol with its resolved source, credibility score, reported course length, catalogue point codes and canonical symptom names – one JSON object per line. The same rows as protocols.jsonl in the corpus licence. Priced at $1.00 over MPP (Machine Payments Protocol).","x-payment-info":{"method":"stripe","intent":"charge","amount":"100","currency":"usd","description":"The complete AcuiQ protocol corpus as JSONL."},"security":[{"payment":[]}],"responses":{"200":{"description":"JSONL corpus: header lines beginning with \"#\", then one CorpusLine per line","content":{"application/x-ndjson":{"schema":{"$ref":"#/components/schemas/CorpusLine"}}}},"402":{"description":"Payment required. The WWW-Authenticate: Payment header carries the challenge; the body states the price and lists the free alternatives.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Payment verification temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}},"components":{"schemas":{"Symptom":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"}},"required":["id","name"]},"SymptomRow":{"type":"object","description":"The shared symptom-search row (GET /api/symptoms and the MCP search_symptoms tool).","properties":{"name":{"type":"string","description":"Display label (displayName when present, else the taxonomy key)"},"displayName":{"type":"string","nullable":true},"url":{"type":"string","format":"uri","description":"Canonical symptom page"}},"required":["name","displayName","url"]},"Meridian":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"element":{"type":"string","nullable":true}},"required":["id","name"]},"Treatment":{"type":"object","properties":{"id":{"type":"integer"},"code":{"type":"string"},"name":{"type":"string","nullable":true},"type":{"type":"string"},"chineseName":{"type":"string","nullable":true},"pinyin":{"type":"string","nullable":true},"location":{"type":"string","nullable":true},"warnings":{"type":"string","nullable":true},"meridian":{"$ref":"#/components/schemas/Meridian"},"indications":{"type":"array","items":{"$ref":"#/components/schemas/Symptom"}}},"required":["id","code","type","indications"]},"ProtocolTreatment":{"type":"object","properties":{"id":{"type":"integer"},"treatment":{"$ref":"#/components/schemas/Treatment"}},"required":["id","treatment"]},"Protocol":{"type":"object","properties":{"id":{"type":"integer"},"ref":{"type":"string","nullable":true,"description":"Source reference"},"cred":{"type":"integer","nullable":true,"description":"Credibility score"},"modality":{"type":"array","items":{"type":"string","enum":["needling","electroacupuncture","moxibustion","acupressure","press-needle","teas","laser","embedding","injection","application","bloodletting","cupping"]},"description":"How the source delivered the points; empty when it does not say"},"sessions":{"type":"integer","nullable":true,"description":"Treatment sessions in the course the source ran"},"courseDays":{"type":"integer","nullable":true,"description":"Calendar length of that course in days, follow-up excluded"},"outcome":{"type":"string","enum":["positive","no-effect","unreported","not-tested"],"description":"What the source reported for this arm; not-tested is a textbook or web indication. Search returns positive and not-tested rows, and no-effect rows whose comparator is sham"},"comparator":{"type":"string","nullable":true,"enum":["sham","active","usual-care","waitlist","none"],"description":"What the arm was measured against; none is a single-arm before-and-after study. Null where the result has not been read"},"note":{"type":"string","nullable":true,"description":"An erratum in the source, or how this row relates to sibling rows from the same paper"},"sex":{"type":"string","nullable":true},"age":{"type":"number","nullable":true,"description":"Recorded cohort age, often a mean"},"symptoms":{"type":"array","items":{"$ref":"#/components/schemas/Symptom"}},"protocolTreatments":{"type":"array","items":{"$ref":"#/components/schemas/ProtocolTreatment"}}},"required":["id","protocol","symptoms","protocolTreatments"]},"CorpusLine":{"type":"object","description":"One line of GET /api/corpus and of protocols.jsonl in the corpus zip: one source reporting one point selection for these symptoms. It is not evidence the selection worked.","properties":{"id":{"type":"integer"},"ref":{"type":"string","nullable":true,"description":"Source reference as extracted"},"source":{"type":"object","description":"The reference as the site classifies it. kind study means the ref resolves to a DOI or a PubMed record, not that the finding was positive","properties":{"kind":{"type":"string","enum":["study","text","web","unsourced"]},"label":{"type":"string"},"url":{"type":"string","description":"Present when the source is directly reachable"}},"required":["kind","label"]},"cred":{"type":"integer","nullable":true,"description":"Credibility score of the source, not of the finding"},"modality":{"type":"array","items":{"type":"string","enum":["needling","electroacupuncture","moxibustion","acupressure","press-needle","teas","laser","embedding","injection","application","bloodletting","cupping"]}},"sessions":{"type":"integer","nullable":true},"courseDays":{"type":"integer","nullable":true},"sex":{"type":"string","nullable":true},"age":{"type":"number","nullable":true,"description":"Recorded cohort age, often a mean"},"outcome":{"type":"string","enum":["positive","no-effect","unreported","not-tested"]},"comparator":{"type":"string","nullable":true,"enum":["sham","active","usual-care","waitlist","none"],"description":"Null where the result has not been read"},"note":{"type":"string","description":"Absent when the row has none"},"points":{"type":"array","items":{"type":"string"},"description":"Catalogue point codes"},"symptoms":{"type":"array","items":{"type":"string"},"description":"Canonical symptom names"},"raw":{"type":"string","nullable":true,"description":"The treatments as the source wrote them"}},"required":["id","ref","source","cred","modality","sessions","courseDays","sex","age","outcome","comparator","points","symptoms","raw"]},"ProtocolMatch":{"type":"object","properties":{"protocol":{"$ref":"#/components/schemas/Protocol"},"score":{"type":"number","minimum":0,"maximum":1,"description":"Fuzzy match relevance score"},"sourceKind":{"type":"string","enum":["study","text","web","unsourced"],"description":"How the source reference was classified"},"source":{"type":"string","description":"Human-readable source label"},"caveat":{"type":"string","description":"Plain-language statement of what this row is"},"substantiation":{"type":"object","description":"Which of this row's points a study-reported protocol for the same query also chose. On a study-reported row it compares against every OTHER study, matched on distinct reference so a paper carrying several prescriptions cannot corroborate itself; on any other row it compares against all of them. Absent when no study but this row's own covers the query (see studyBacked). An empty `points` array is meaningful: studies cover the query and none used any of these points. Two limits travel with it — a shared point is not an endorsement of the prescription, because no study tested it; and a second reference is not necessarily a second research group.","properties":{"points":{"type":"array","items":{"type":"string"},"description":"Point codes shared with a study-reported protocol"},"study":{"type":"object","properties":{"label":{"type":"string"},"url":{"type":"string","description":"Present when the study is directly reachable"}},"required":["label"]}},"required":["points","study"]}},"required":["protocol","score","sourceKind","source","caveat"]},"SearchResult":{"type":"object","properties":{"matches":{"type":"array","items":{"$ref":"#/components/schemas/ProtocolMatch"}},"directMatches":{"type":"array","items":{"$ref":"#/components/schemas/Treatment"},"description":"Points whose indications list the searched symptoms, returned only when no protocol matched. Index entries, not prescriptions."},"studyBacked":{"type":"boolean","description":"Whether any study-reported protocol covers this query at all, decided over the whole ranked candidate set rather than the page returned. False means every prescription on offer comes from a clinical text or a website."},"query":{"type":"array","items":{"type":"string"},"description":"Normalized symptom names"},"queryAge":{"type":"integer","nullable":true},"querySex":{"type":"string","nullable":true}},"required":["matches","query"]},"SymptomListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SymptomRow"}},"error":{"type":"string"},"code":{"type":"string"}}},"MeridianListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object"}},"error":{"type":"string"},"code":{"type":"string"}}},"SearchResultResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SearchResult"},"error":{"type":"string"},"code":{"type":"string"}}},"WikiSearchRow":{"type":"object","description":"The shared wiki-search row (GET /api/wiki?q= and the MCP search_wiki tool).","properties":{"path":{"type":"string","description":"Section and slug, e.g. \"safety/pregnancy-and-the-forbidden-points\""},"title":{"type":"string"},"snippet":{"type":"string","description":"The passage that matched, else the page description"},"basis":{"type":"string"},"audience":{"type":"string"},"lastVerified":{"type":["string","null"],"format":"date","description":"When the page was last checked against its sources; null if it never has been"},"url":{"type":"string","format":"uri"},"markdown":{"type":"string","format":"uri","description":"The whole page as markdown"}},"required":["path","title","snippet","basis","audience","lastVerified","url","markdown"]},"WikiSearchResponse":{"type":"object","properties":{"query":{"type":"string"},"total":{"type":"integer"},"page":{"type":"integer"},"pageSize":{"type":"integer"},"totalPages":{"type":"integer"},"hasMore":{"type":"boolean"},"nextPage":{"type":"integer"},"pages":{"type":"array","items":{"$ref":"#/components/schemas/WikiSearchRow"}}},"required":["query","total","page","pageSize","totalPages","hasMore","pages"]},"ErrorResponse":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["RATE_LIMITED","INVALID_PARAMS","NOT_FOUND","SERVICE_ERROR","PAYMENT_REQUIRED"]}},"required":["error"]}},"securitySchemes":{"payment":{"type":"http","scheme":"Payment","description":"MPP (Machine Payments Protocol) (https://mpp.dev), method \"stripe\", paid with a Stripe shared payment token (SPT), single use scoped to Stripe profile profile_61VcHMvCI7idwYC2zA6VcHMv8oE9roGsBkZRtDHSi0ng. Request the resource without it, answer the WWW-Authenticate challenge from the 402, and retry with Authorization: Payment. Only the two bulk exports use this; everything else on this spec is free and anonymous."}}}}