{"openapi":"3.1.0","info":{"title":"uYao public read API","version":"1.1.0","summary":"GET /api/catalog and GET /api/pharmacies only. Not live inventory.","description":"Public read contract for agents. Two GET endpoints.\n\n- uYao has no live inventory for any pharmacy. This API never returns price, stock, or availability, and no response may be presented as confirmed stock.\n- These responses repeat fields the catalog and pharmacy pages already render.\n- They are not a diagnosis API and not a Store OS control plane. Store OS is a prototype.\n- Clients may send X-uYao-API-Version: 1.1.0. Omitting the header selects the current version for backward compatibility. Every response returns the selected version. Before a version is retired, uYao will publish the migration path at /docs and signal it with the Deprecation and Sunset response headers.","contact":{"email":"uyao@agentmail.to","url":"https://uyaohealth.com/en"},"license":{"name":"Catalog and pharmacy data are published for reference; attribute uYao when reused.","url":"https://uyaohealth.com/en/evidence"}},"servers":[{"url":"https://uyaohealth.com","description":"Unified public host for the consumer service and company information."},{"url":"https://store.uyaohealth.com","description":"Store OS host. Same public read API surface; signed-in Store OS actions are not public."}],"externalDocs":{"url":"https://uyaohealth.com/docs","description":"Human-readable notes for these two GETs"},"tags":[{"name":"catalog","description":"Partner-listed catalog items. Read-only. Not live inventory."},{"name":"pharmacies","description":"Public pharmacy records. Read-only. Not live inventory."}],"paths":{"/api/catalog":{"get":{"tags":["catalog"],"operationId":"listCatalog","summary":"List every catalog item","description":"Returns the catalog records partner pharmacies provided. uYao has no live inventory for any pharmacy. This API never returns price, stock, or availability, and no response may be presented as confirmed stock. Cached at the edge for one hour and CORS-open. No authentication and no cookies. Rate-limited per client IP; successful and quota-checked error responses carry RateLimit-Policy and RateLimit using the current IETF HTTPAPI draft syntax, plus legacy compatibility fields. A 429 also carries Retry-After. The response contains only data these pages already render publicly.","parameters":[{"name":"X-uYao-API-Version","in":"header","required":false,"description":"Optional API contract version. Omit it to use the current 1.1.0 contract. Unsupported values return an RFC 9457 JSON problem.","schema":{"type":"string","enum":["1.1.0"],"default":"1.1.0"}},{"name":"locale","in":"query","required":false,"description":"Response language. Anything other than `en` returns Traditional Chinese.","schema":{"type":"string","enum":["zh","en"],"default":"zh"}}],"responses":{"200":{"description":"The full catalog. Not live inventory.","headers":{"X-uYao-API-Version":{"schema":{"type":"string","enum":["1.1.0"]},"description":"The API contract version used for this response."},"Link":{"schema":{"type":"string"},"description":"Link to the versioning and deprecation policy. This link alone does not mean the endpoint is deprecated."},"RateLimit-Policy":{"schema":{"type":"string","example":"\"public-read\";q=120;w=3600"},"description":"Stable public-read quota policy using the current IETF HTTPAPI RateLimit draft syntax."},"RateLimit":{"schema":{"type":"string","example":"\"public-read\";r=119;t=3600"},"description":"Remaining public-read quota and effective window using the current IETF HTTPAPI RateLimit draft syntax."},"RateLimit-Limit":{"schema":{"type":"integer","example":120},"description":"Legacy compatibility field: request quota for the window."},"RateLimit-Remaining":{"schema":{"type":"integer","example":119},"description":"Legacy compatibility field: requests remaining in the window."},"RateLimit-Reset":{"schema":{"type":"integer","example":3600},"description":"Legacy compatibility field: seconds until the quota window resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogList"}},"text/markdown":{"schema":{"type":"string"}}}},"400":{"description":"Unsupported API version. RFC 9457 JSON problem.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited. JSON error body plus RateLimit headers.","headers":{"X-uYao-API-Version":{"schema":{"type":"string","enum":["1.1.0"]},"description":"The API contract version used for this response."},"Link":{"schema":{"type":"string"},"description":"Link to the versioning and deprecation policy. This link alone does not mean the endpoint is deprecated."},"RateLimit-Policy":{"schema":{"type":"string","example":"\"public-read\";q=120;w=3600"},"description":"Stable public-read quota policy using the current IETF HTTPAPI RateLimit draft syntax."},"RateLimit":{"schema":{"type":"string","example":"\"public-read\";r=119;t=3600"},"description":"Remaining public-read quota and effective window using the current IETF HTTPAPI RateLimit draft syntax."},"RateLimit-Limit":{"schema":{"type":"integer","example":120},"description":"Legacy compatibility field: request quota for the window."},"RateLimit-Remaining":{"schema":{"type":"integer","example":119},"description":"Legacy compatibility field: requests remaining in the window."},"RateLimit-Reset":{"schema":{"type":"integer","example":3600},"description":"Legacy compatibility field: seconds until the quota window resets."},"Retry-After":{"schema":{"type":"integer","example":3600},"description":"Seconds the client should wait before retrying after a 429 response."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/pharmacies":{"get":{"tags":["pharmacies"],"operationId":"listPharmacies","summary":"List public pharmacy records","description":"Pharmacy records assembled from Taiwan government open data. The pharmacist-in-charge name is deliberately not exposed. When `hoursSource` is `nhi`, hours are National Health Insurance dispensing hours and are not store opening hours. Cached at the edge for one hour and CORS-open. No authentication and no cookies. Rate-limited per client IP; successful and quota-checked error responses carry RateLimit-Policy and RateLimit using the current IETF HTTPAPI draft syntax, plus legacy compatibility fields. A 429 also carries Retry-After. The response contains only data these pages already render publicly.","parameters":[{"name":"area","in":"query","required":false,"description":"Restrict to one service area.","schema":{"type":"string","enum":["datong","linkou","luzhou","xinzhuang","zhongshan","shilin","xitun","miaoli","yilan","luodong"]}},{"name":"X-uYao-API-Version","in":"header","required":false,"description":"Optional API contract version. Omit it to use the current 1.1.0 contract. Unsupported values return an RFC 9457 JSON problem.","schema":{"type":"string","enum":["1.1.0"],"default":"1.1.0"}},{"name":"locale","in":"query","required":false,"description":"Response language. Anything other than `en` returns Traditional Chinese.","schema":{"type":"string","enum":["zh","en"],"default":"zh"}}],"responses":{"200":{"description":"Matching pharmacy records.","headers":{"X-uYao-API-Version":{"schema":{"type":"string","enum":["1.1.0"]},"description":"The API contract version used for this response."},"Link":{"schema":{"type":"string"},"description":"Link to the versioning and deprecation policy. This link alone does not mean the endpoint is deprecated."},"RateLimit-Policy":{"schema":{"type":"string","example":"\"public-read\";q=120;w=3600"},"description":"Stable public-read quota policy using the current IETF HTTPAPI RateLimit draft syntax."},"RateLimit":{"schema":{"type":"string","example":"\"public-read\";r=119;t=3600"},"description":"Remaining public-read quota and effective window using the current IETF HTTPAPI RateLimit draft syntax."},"RateLimit-Limit":{"schema":{"type":"integer","example":120},"description":"Legacy compatibility field: request quota for the window."},"RateLimit-Remaining":{"schema":{"type":"integer","example":119},"description":"Legacy compatibility field: requests remaining in the window."},"RateLimit-Reset":{"schema":{"type":"integer","example":3600},"description":"Legacy compatibility field: seconds until the quota window resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PharmacyList"}}}},"400":{"description":"Unknown area slug. JSON error body.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited. JSON error body plus RateLimit headers.","headers":{"X-uYao-API-Version":{"schema":{"type":"string","enum":["1.1.0"]},"description":"The API contract version used for this response."},"Link":{"schema":{"type":"string"},"description":"Link to the versioning and deprecation policy. This link alone does not mean the endpoint is deprecated."},"RateLimit-Policy":{"schema":{"type":"string","example":"\"public-read\";q=120;w=3600"},"description":"Stable public-read quota policy using the current IETF HTTPAPI RateLimit draft syntax."},"RateLimit":{"schema":{"type":"string","example":"\"public-read\";r=119;t=3600"},"description":"Remaining public-read quota and effective window using the current IETF HTTPAPI RateLimit draft syntax."},"RateLimit-Limit":{"schema":{"type":"integer","example":120},"description":"Legacy compatibility field: request quota for the window."},"RateLimit-Remaining":{"schema":{"type":"integer","example":119},"description":"Legacy compatibility field: requests remaining in the window."},"RateLimit-Reset":{"schema":{"type":"integer","example":3600},"description":"Legacy compatibility field: seconds until the quota window resets."},"Retry-After":{"schema":{"type":"integer","example":3600},"description":"Seconds the client should wait before retrying after a 429 response."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"schemas":{"Error":{"type":"object","description":"RFC 9457 problem details with stable uYao compatibility fields and a machine-actionable resolution hint.","properties":{"type":{"type":"string","format":"uri-reference"},"title":{"type":"string"},"status":{"type":"integer","minimum":400,"maximum":599},"detail":{"type":"string"},"error":{"type":"string","description":"Backward-compatible stable error code."},"code":{"type":"string","description":"Stable machine-readable error code."},"message":{"type":"string","description":"Short human-readable error summary."},"resolution":{"type":"string","description":"Action the caller can take to resolve the error."}},"required":["type","title","status","detail","error","code","message","resolution"]},"ResponseEnvelope":{"type":"object","properties":{"version":{"type":"string","description":"Payload shape version."},"locale":{"type":"string","enum":["zh","en"]},"disclaimer":{"type":"string","description":"Boundary text that must survive any summary of this response. Present on every read response."}},"required":["version","locale","disclaimer"]},"CatalogList":{"allOf":[{"$ref":"#/components/schemas/ResponseEnvelope"},{"type":"object","properties":{"count":{"type":"integer"},"items":{"type":"array","items":{"$ref":"#/components/schemas/CatalogItem"}}},"required":["count","items"]}]},"CatalogItem":{"type":"object","description":"A catalog record. Carries no price, stock, or availability, by design.","properties":{"slug":{"type":"string"},"url":{"type":"string","format":"uri","description":"Canonical page for this item."},"name":{"type":"string"},"catalogRecordUpdatedOn":{"type":"string","format":"date","description":"Date when this catalog record's public product content last changed. This is not an inventory scan timestamp, stock freshness signal, or availability confirmation."},"nameEn":{"type":"string","description":"Present only when a real English product name exists."},"form":{"type":"string"},"spec":{"type":"string"},"drugClass":{"type":"string","description":"Regulatory class. `待確認` / `Classification pending` means public data cannot determine it; it is never guessed."},"category":{"type":"string"},"ingredients":{"type":"array","items":{"type":"string"}},"nutritionFocus":{"type":"string","description":"Everyday nutrition positioning. Not an approved indication and not a treatment claim."},"manufacturer":{"type":"string"},"origin":{"type":"string"},"licenseNo":{"type":"string","description":"Ministry of Health and Welfare licence number. Omitted rather than guessed when unknown."},"image":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"kind":{"type":"string","enum":["illustration","packshot"],"description":"`illustration` is a generated image and does not depict real packaging. `packshot` is a real photograph."},"alt":{"type":"string"}},"required":["url","kind","alt"]},"source":{"type":"object","description":"Where the product details came from.","properties":{"label":{"type":"string"},"url":{"type":"string","format":"uri"},"kind":{"type":"string","enum":["public","partner"]}},"required":["label"]}},"required":["slug","url","name","catalogRecordUpdatedOn","form","spec","drugClass","category","ingredients","nutritionFocus"]},"PharmacyList":{"allOf":[{"$ref":"#/components/schemas/ResponseEnvelope"},{"type":"object","properties":{"count":{"type":"integer"},"pharmacies":{"type":"array","items":{"$ref":"#/components/schemas/Pharmacy"}}},"required":["count","pharmacies"]}]},"Pharmacy":{"type":"object","description":"A public pharmacy record. The pharmacist-in-charge name is deliberately not exposed.","properties":{"slug":{"type":"string"},"url":{"type":"string","format":"uri"},"name":{"type":"string"},"area":{"type":"string","enum":["datong","linkou","luzhou","xinzhuang","zhongshan","shilin","xitun","miaoli","yilan","luodong"]},"district":{"type":"string"},"address":{"type":"string"},"phone":{"type":"string"},"nhiCode":{"type":["string","null"],"description":"National Health Insurance institution code. Stable across renames."},"nhiContracted":{"type":"boolean"},"businessStatus":{"type":["string","null"],"description":"Google business status. Anything other than `OPERATIONAL` needs care."},"hoursSource":{"type":"string","enum":["google","nhi","partner","none"],"description":"`nhi` means National Health Insurance dispensing hours, which are not store opening hours. Never present them as a guarantee that the pharmacy is open."},"hours":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"hours":{"type":"string"}},"required":["label","hours"]}},"mapsUrl":{"type":"string","format":"uri"},"location":{"type":["object","null"],"properties":{"lat":{"type":"number"},"lng":{"type":"number"}},"required":["lat","lng"]}},"required":["slug","url","name","area","district","address","nhiCode","nhiContracted","businessStatus","hoursSource","hours","mapsUrl","location"]}}}}