{"openapi":"3.1.0","info":{"title":"SODINHDANH.COM API","version":"1.0.0","description":"MVP. API JSON công khai có giới hạn. Không tìm người, không sinh mã cá nhân. Danh mục hành chính chỉ là bộ mẫu 6 bản ghi dẫn nguồn. Không bật CORS mặc định."},"servers":[{"url":"/"}],"paths":{"/api/v1/entries":{"get":{"operationId":"listEntries","summary":"Nội dung đã xuất bản, kèm nguồn","parameters":[{"name":"kind","in":"query","schema":{"enum":["encyclopedia","term","legal"]},"required":false},{"name":"q","in":"query","schema":{"type":"string","maxLength":80,"description":"Chỉ tên chủ đề, từ chối chuỗi 6 số liên tiếp."},"required":false},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":49,"default":20},"required":false},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0,"maximum":10000,"default":0},"required":false}],"responses":{"200":{"description":"Danh sách","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/EntrySummary"}},"meta":{"type":"object","properties":{"limit":{"type":"integer"},"offset":{"type":"integer"},"nextOffset":{"type":["integer","null"]}},"required":["limit","offset","nextOffset"]}},"required":["data","meta"]}}}},"400":{"description":"Lỗi không chứa mã đã nhập hoặc chi tiết nội bộ.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Lỗi không chứa mã đã nhập hoặc chi tiết nội bộ.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Lỗi không chứa mã đã nhập hoặc chi tiết nội bộ.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/entries/{kind}/{slug}":{"get":{"operationId":"getEntry","summary":"Chi tiết nội dung công khai","parameters":[{"name":"kind","in":"path","schema":{"enum":["encyclopedia","term","legal"]},"required":true},{"name":"slug","in":"path","schema":{"type":"string","maxLength":120},"required":true}],"responses":{"200":{"description":"Nội dung","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/EntryDetail"}},"required":["data"]}}}},"400":{"description":"Lỗi không chứa mã đã nhập hoặc chi tiết nội bộ.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Lỗi không chứa mã đã nhập hoặc chi tiết nội bộ.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Lỗi không chứa mã đã nhập hoặc chi tiết nội bộ.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Lỗi không chứa mã đã nhập hoặc chi tiết nội bộ.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/administrative-units":{"get":{"operationId":"listAdministrativeUnits","summary":"Tra cứu bộ mẫu mã hành chính","parameters":[{"name":"code","in":"query","schema":{"type":"string","pattern":"^(\\d{2}|\\d{5})$"},"required":false},{"name":"at","in":"query","schema":{"type":"string","format":"date"},"required":false}],"responses":{"200":{"description":"Bộ mẫu, không tìm thấy không có nghĩa mã không tồn tại","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AdministrativeUnit"}},"meta":{"type":"object","properties":{"coverage":{"const":"sample_subset"},"complete":{"const":false},"notFoundMeans":{"const":"not_in_this_dataset"},"asOf":{"type":"string","format":"date"},"note":{"type":"string"}},"required":["coverage","complete","notFoundMeans","asOf","note"]}},"required":["data","meta"]}}}},"400":{"description":"Lỗi không chứa mã đã nhập hoặc chi tiết nội bộ.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Lỗi không chứa mã đã nhập hoặc chi tiết nội bộ.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Lỗi không chứa mã đã nhập hoặc chi tiết nội bộ.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/validate":{"post":{"operationId":"validateFormat","summary":"Kiểm tra định dạng, không xác thực danh tính","description":"JSON POST tối đa 1024 byte. Không lưu hoặc trả lại đầu vào. Giao diện kiểm tra ngay tại trình duyệt. Mã thuế: chỉ cấu trúc tổ chức, không kiểm tra checksum. 30 yêu cầu/phút.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"kind":{"enum":["personal","tax","province","commune"]},"value":{"type":"string","maxLength":32}},"required":["kind","value"],"additionalProperties":false},"example":{"kind":"province","value":"01"}}}},"responses":{"200":{"description":"Kết quả","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/FormatResult"},"meta":{"type":"object","properties":{"inputStored":{"const":false},"inputEchoed":{"const":false}},"required":["inputStored","inputEchoed"]}},"required":["data","meta"]}}}},"400":{"description":"Lỗi không chứa mã đã nhập hoặc chi tiết nội bộ.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Lỗi không chứa mã đã nhập hoặc chi tiết nội bộ.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Lỗi không chứa mã đã nhập hoặc chi tiết nội bộ.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Lỗi không chứa mã đã nhập hoặc chi tiết nội bộ.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Lỗi không chứa mã đã nhập hoặc chi tiết nội bộ.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/mapsviet/businesses/{taxCode}":{"get":{"operationId":"lookupMapsVietBusiness","summary":"Doanh nghiệp công khai từ MapsViet","description":"Yêu cầu URL API, đường dẫn và token thực tế. Không giả định endpoint nguồn. Chỉ nhận entityType=organization; bỏ các trường cá nhân. 15 yêu cầu/phút.","parameters":[{"name":"taxCode","in":"path","schema":{"type":"string","pattern":"^(\\d{10}|\\d{13}|\\d{10}-\\d{3})$"},"required":true}],"responses":{"200":{"description":"Doanh nghiệp do nguồn trả về","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Business"},"meta":{"type":"object","properties":{"source":{"const":"MapsViet"},"retrievedAt":{"type":"string","format":"date-time"},"verification":{"const":"source_reported"},"personalDataExcluded":{"const":true}},"required":["source","retrievedAt","verification","personalDataExcluded"]}},"required":["data","meta"]}}}},"400":{"description":"Lỗi không chứa mã đã nhập hoặc chi tiết nội bộ.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Lỗi không chứa mã đã nhập hoặc chi tiết nội bộ.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Lỗi không chứa mã đã nhập hoặc chi tiết nội bộ.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Lỗi không chứa mã đã nhập hoặc chi tiết nội bộ.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Lỗi không chứa mã đã nhập hoặc chi tiết nội bộ.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/health":{"get":{"operationId":"readiness","summary":"Kiểm tra DB và schema","responses":{"200":{"description":"Sẵn sàng","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"const":"ok"},"database":{"const":"reachable"},"version":{"type":"string"}},"required":["status","database","version"]}}}},"503":{"description":"Chưa sẵn sàng","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"const":"unavailable"}},"required":["status"]}}}}}}}},"components":{"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"requestId":{"type":"string","format":"uuid"}},"required":["code","message","requestId"]}},"required":["error"]},"Source":{"type":"object","properties":{"title":{"type":"string"},"url":{"type":"string","format":"uri"},"checkedAt":{"type":"string","format":"date-time"},"publisher":{"type":"string"},"locator":{"type":"string"}},"required":["title","url","checkedAt"]},"EntrySummary":{"type":"object","properties":{"slug":{"type":"string"},"kind":{"enum":["encyclopedia","term","legal"]},"title":{"type":"string"},"summary":{"type":"string"},"url":{"type":"string"},"isSample":{"type":"boolean"},"source":{"$ref":"#/components/schemas/Source"}},"required":["slug","kind","title","summary","url","isSample","source"]},"EntryDetail":{"type":"object","properties":{"slug":{"type":"string"},"kind":{"type":"string"},"title":{"type":"string"},"summary":{"type":"string"},"body":{"type":"array","items":{"type":"object","properties":{"heading":{"type":"string"},"text":{"type":"string"}},"required":["heading","text"]}},"legal":{"type":["object","null"]},"isSample":{"type":"boolean"},"updatedAt":{"type":"string","format":"date-time"},"source":{"$ref":"#/components/schemas/Source"}},"required":["slug","kind","title","summary","body","legal","isSample","updatedAt","source"]},"AdministrativeUnit":{"type":"object","properties":{"code":{"type":"string"},"name":{"type":"string"},"level":{"enum":["province","commune"]},"parent_code":{"type":["string","null"]},"valid_from":{"type":"string"},"valid_to":{"type":["string","null"]},"source_id":{"type":"string"},"source_url":{"type":"string","format":"uri"},"source_title":{"type":"string"},"is_sample":{"type":"boolean"}},"required":["code","name","level","parent_code","valid_from","valid_to","source_id","source_url","source_title","is_sample"]},"FormatResult":{"type":"object","properties":{"formatValid":{"type":"boolean"},"scope":{"const":"format_only"},"message":{"type":"string"},"rulesVersion":{"type":"string"},"sourceUrl":{"type":"string","format":"uri"},"checks":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"passed":{"type":"boolean"}},"required":["label","passed"]}}},"required":["formatValid","scope","message","rulesVersion","sourceUrl","checks"]},"Business":{"type":"object","properties":{"entityType":{"const":"organization"},"taxCode":{"type":"string"},"name":{"type":"string"},"url":{"type":"string","format":"uri"},"provinceCode":{"type":"string"}},"required":["entityType","taxCode","name","url"],"additionalProperties":false}}}}