{"count":138,"docs":"/docs","openapi":"/openapi.json","routes":[{"path":"/api","methods":["GET"],"summary":"Liệt kê mọi endpoint /api (path + method + tóm tắt) — sinh động từ app.routes,"},{"path":"/api/account/data","methods":["GET"],"summary":"Bạn đang giữ những gì của tôi — và cái gì sẽ mất nếu tôi xoá. CHỈ ĐỌC."},{"path":"/api/account/delete","methods":["POST"],"summary":"Xoá TOÀN BỘ dữ-liệu của người đang đăng-nhập. BẤT-KHẢ-HỒI."},{"path":"/api/account/resolve","methods":["GET"],"summary":"Tra owner-ref của 1 tài-khoản theo USERNAME chính-xác → để chủ MỜI công-nhân (nhập tên thay"},{"path":"/api/admin/activity","methods":["GET"],"summary":"ADMIN: tổng hợp hoạt động TỪNG user."},{"path":"/api/admin/deploy_history","methods":["GET"],"summary":"Những lần server bị đụng tới: chạy lại, dừng, chết, deploy mã mới, sửa bản khai."},{"path":"/api/admin/feedback","methods":["GET"],"summary":"ADMIN: danh sách góp ý nông dân (mới nhất trước). KHÔNG lộ owner thô/secret."},{"path":"/api/admin/logs","methods":["GET"],"summary":"Log gần nhất (mới nhất CUỐI danh sách) từ ring-buffer + đuôi file nếu cấu-hình."},{"path":"/api/admin/server_status","methods":["GET"],"summary":"Sức khoẻ máy chủ: máy, tiến-trình, card đồ-hoạ, đĩa, kho dữ-liệu, lưu-lượng, mạng, hàng đợi."},{"path":"/api/admin/showcase/{tree_id}","methods":["POST"],"summary":"ADMIN (secret): tạo xuất xứ + 3D + quả + neo cho 1 cây CÓ SẴN (legacy) để trưng bày."},{"path":"/api/admin/storage_status","methods":["GET"],"summary":"Ảnh mới lưu có rời khỏi máy này không, và nếu KHÔNG thì đã bao lâu rồi. CHỈ ĐỌC."},{"path":"/api/anchor/pending","methods":["GET"],"summary":"Danh sách cây cần neo — worker (máy có khoá) đọc rồi ký + submit. CẦN BÍ MẬT."},{"path":"/api/anchor/status","methods":["GET"],"summary":"Sức khoẻ đường NEO: mạng, hàng đợi, mốc neo gần nhất, số cây kẹt, lý do 403 gần nhất,"},{"path":"/api/anchor/submit","methods":["POST"],"summary":"Worker ghi kết quả neo về. Cần ANCHOR_WORKER_SECRET khớp (chặn POST giả)."},{"path":"/api/animal/demo","methods":["GET"],"summary":""},{"path":"/api/animal/detect","methods":["POST"],"summary":"Quyết định loài cho luồng 1-nút:"},{"path":"/api/animal/drift/report","methods":["GET"],"summary":"Quét trại: cá thể nào cần chụp lại (đã drift) + cặp nào sắp NHẦM (gap co lại) + kênh"},{"path":"/api/animal/enroll","methods":["POST"],"summary":""},{"path":"/api/animal/fee/estimate","methods":["GET"],"summary":""},{"path":"/api/animal/field","methods":["GET"],"summary":""},{"path":"/api/animal/identify","methods":["POST"],"summary":""},{"path":"/api/animal/identify_verdict","methods":["POST"],"summary":"MCR-PoC-Animal L2 — GHI GROUND-TRUTH cho 1 lượt /animal/identify hoặc /animal/scan"},{"path":"/api/animal/list","methods":["GET"],"summary":""},{"path":"/api/animal/provenance/demo","methods":["GET"],"summary":"Sinh 1 chuỗi lineage mẫu + inclusion proof thật để minh hoạ luồng người tiêu dùng."},{"path":"/api/animal/rename","methods":["POST"],"summary":"Đổi tên một cá thể."},{"path":"/api/animal/scan","methods":["POST"],"summary":""},{"path":"/api/animal/trust/tiers","methods":["GET"],"summary":""},{"path":"/api/animal/trust/verify-inclusion","methods":["POST"],"summary":"Verify 1 record thuộc Merkle root đã neo Cardano — bất kỳ ai cũng gọi được."},{"path":"/api/animal/verify","methods":["POST"],"summary":""},{"path":"/api/animal/{animal_did}","methods":["DELETE"],"summary":""},{"path":"/api/animal/{animal_did}","methods":["GET"],"summary":"?describe=1 (LAZY, mặc-định TẮT): thêm `features_vi` — câu tiếng Việt nói phần nào của"},{"path":"/api/animal/{animal_did}/model3d","methods":["GET"],"summary":"Cửa 3D của con vật — CÙNG hình-dạng với cửa cây và cửa quả, và nói ĐÚNG thứ có trên đĩa."},{"path":"/api/auth/did/challenge","methods":["GET"],"summary":"Phát challenge nonce. Rate-limit nhẹ theo IP (chống bơm-cạn bộ-nhớ challenge)."},{"path":"/api/auth/did/verify","methods":["POST"],"summary":"Verify chữ-ký DID trên challenge → cấp token field-reid."},{"path":"/api/backfill/{tree_id}","methods":["POST"],"summary":"Tạo xuất xứ (mã+LampNet+bản ghi) cho 1 cây ĐÃ đăng ký trước đây + dựng 3D."},{"path":"/api/booth/create","methods":["POST"],"summary":"Tạo phiên trưng bày rỗng → trả mã khách + URL trang quét (đem in QR)."},{"path":"/api/booth/img/{token}","methods":["GET"],"summary":"Ảnh gallery phục vụ bằng MÃ theo lượt quét (S7): không đoán được, hết hạn, thu hồi được."},{"path":"/api/booth/list","methods":["GET"],"summary":"Các phiên của tài khoản (mới nhất trước)."},{"path":"/api/booth/public/{code}","methods":["GET"],"summary":"Thông tin tối thiểu cho trang quét của khách. KHÔNG trả danh sách quả (không đưa"},{"path":"/api/booth/{booth_id}","methods":["GET"],"summary":"Chi tiết phiên + danh sách quả (tên, cây mẹ, ảnh) để chủ soát trước giờ mở cửa."},{"path":"/api/booth/{booth_id}/close","methods":["POST"],"summary":"ĐÓNG phiên — MỘT CHIỀU: mã hết quét được VÀ hết mở được ảnh (đây là chỗ thu hồi)."},{"path":"/api/booth/{booth_id}/fruits/add","methods":["POST"],"summary":"Thêm quả vào phiên. CHỈ nhận quả của chính chủ — quả lạ bị bỏ và báo lại rõ ràng."},{"path":"/api/booth/{booth_id}/fruits/remove","methods":["POST"],"summary":"Bớt quả khỏi phiên (quả đã bán / đã bổ)."},{"path":"/api/booth/{booth_id}/lock","methods":["POST"],"summary":"KHOÁ danh sách (chốt trước giờ mở cửa) — vẫn quét được. locked=0 để mở khoá lại."},{"path":"/api/booth/{code}/img/{fruit_id}/{idx}","methods":["GET"],"summary":"Ảnh đã đăng ký của 1 quả — CHỈ khi quả đó thuộc đúng phiên `code` và phiên còn mở."},{"path":"/api/booth/{code}/tree_img/{tree_id}/{idx}","methods":["GET"],"summary":"Ảnh CÂY MẸ — chỉ cây có quả trong phiên `code`."},{"path":"/api/build3d/{tree_id}","methods":["POST"],"summary":"Dựng (hoặc dựng lại) 3D cho 1 cây — chạy nền."},{"path":"/api/capture/plan","methods":["GET"],"summary":"Còn thiếu gì và nên chụp gì TIẾP — một cửa cho cả cây, quả lẫn con vật. ĐỌC-ONLY, additive."},{"path":"/api/capture_guidance/{tree_id}","methods":["GET"],"summary":"Gợi-ý GÓC-HỞ cho app chụp bù (next-best-view #81) — ĐỌC-ONLY, additive."},{"path":"/api/care/banned","methods":["GET"],"summary":"Danh mục hoạt chất bị cấm hoặc hạn chế trong nông nghiệp — trồng trọt, chăn nuôi và"},{"path":"/api/care/delete","methods":["POST"],"summary":""},{"path":"/api/care/events","methods":["GET"],"summary":""},{"path":"/api/care/log","methods":["POST"],"summary":""},{"path":"/api/care/match","methods":["POST"],"summary":"Trả danh sách ứng viên (tên + thông tin), KHÔNG có score. Có text → match thẳng;"},{"path":"/api/care/products","methods":["GET"],"summary":""},{"path":"/api/care/withdrawal","methods":["GET"],"summary":""},{"path":"/api/delete","methods":["POST"],"summary":""},{"path":"/api/enroll","methods":["POST"],"summary":""},{"path":"/api/events","methods":["GET"],"summary":"Tải toàn bộ nhật ký theo thời gian (cho phân tích thí nghiệm)."},{"path":"/api/farm","methods":["POST"],"summary":"Tạo FARM mới. owner_did LẤY TỪ AUTH (không nhận từ client). name vệ-sinh ở biên (rỗng→400)."},{"path":"/api/farm/layout","methods":["GET"],"summary":"Sơ-đồ KHÔNG-GIAN cây trong vườn: chiếu GPS ra mét tương-đối quanh TÂM (centroid)."},{"path":"/api/farm/{farm_id}","methods":["DELETE"],"summary":"Xoá CHỈ farm (KHÔNG xoá cây). Cây trong farm thành farm_id=null (mồ-côi, vẫn truy được)."},{"path":"/api/farm/{farm_id}","methods":["GET"],"summary":"Chi-tiết 1 farm + cây + con thuộc farm. Owner-guard: farm không thuộc bạn → 403"},{"path":"/api/farm/{farm_id}/map","methods":["GET"],"summary":"Sơ đồ vườn cho app: MÉT tương đối so với gốc vườn, kèm gốc, kèm nguồn của từng chấm."},{"path":"/api/farm/{farm_id}/media","methods":["GET"],"summary":"Media đã gắn cho vườn — CHỈ CHỦ. Mỗi mục `{cid, sha256, kind, size, at}`."},{"path":"/api/farm/{farm_id}/photos","methods":["POST"],"summary":"Gắn ẢNH vào vườn (toàn cảnh, bờ ranh, biển vườn, thiệt hại sau bão…)."},{"path":"/api/farm/{farm_id}/update","methods":["POST"],"summary":"Cập-nhật farm (chỉ field GỬI mới đổi). Owner-guard. name nếu gửi thì vệ-sinh (rỗng→400)."},{"path":"/api/farm/{farm_id}/video","methods":["POST"],"summary":"Gắn một CLIP vào vườn. Cặp song sinh của `/api/tree/{id}/video`, trừ phần engine."},{"path":"/api/farms","methods":["GET"],"summary":"Liệt-kê farm CỦA owner đăng-nhập, mỗi farm kèm counts {n_trees, n_animals}."},{"path":"/api/feedback","methods":["POST"],"summary":"Nông dân gửi góp ý. note bắt buộc (đã strip, chặn rỗng). Lưu 1 dòng vào feedback.jsonl."},{"path":"/api/fruit/add_view","methods":["POST"],"summary":"Bổ sung góc chụp thêm cho quả đã đăng ký (weekly rescan xác nhận)."},{"path":"/api/fruit/candidates","methods":["POST"],"summary":"XẾP-HẠNG ứng-viên quả của 1 CÂY theo độ giống ảnh truy vấn (UX redesign quả)."},{"path":"/api/fruit/detect","methods":["POST"],"summary":"Phát hiện quả sầu riêng trong ảnh → trả danh sách bbox."},{"path":"/api/fruit/enroll","methods":["POST"],"summary":"Đăng ký 1 quả sầu riêng lên cây tree_id."},{"path":"/api/fruit/identify","methods":["POST"],"summary":"Nhận diện lại quả sầu riêng (chỉ trong vườn của tài khoản — chống IDOR)."},{"path":"/api/fruit/identify_verdict","methods":["POST"],"summary":"MCR-PoC-Fruit L2 — GHI GROUND-TRUTH cho 1 lượt /api/fruit/identify (join bằng query_id)."},{"path":"/api/fruit/list","methods":["GET"],"summary":"List quả. tree_id: chỉ quả của cây đó; bỏ trống: toàn vườn CỦA TÀI KHOẢN."},{"path":"/api/fruit/lookup","methods":["POST"],"summary":"NGƯỜI LẠ chụp một quả → tối đa 5 ứng viên KÈM ẢNH trong tập quả CÔNG KHAI, để tự đối chiếu."},{"path":"/api/fruit/lookup/img/{token}","methods":["GET"],"summary":"Ảnh gallery cho lane công khai — mã cấp theo LƯỢT TRA CỨU: không đoán được, hết hạn."},{"path":"/api/fruit/scan","methods":["POST"],"summary":"KHÁCH THAM QUAN quét vỏ một quả đang bày → NĂM ỨNG VIÊN KÈM ẢNH để khách tự đối chiếu."},{"path":"/api/fruit/scan/choose","methods":["POST"],"summary":"KHÁCH CHỌN quả nào giống (hoặc \"không quả nào\") → hồ sơ quả + MỘT MẪU CÓ NHÃN."},{"path":"/api/fruit/{fruit_id}","methods":["DELETE"],"summary":"Xóa quả (farmer nhập nhầm)."},{"path":"/api/fruit/{fruit_id}","methods":["GET"],"summary":"Chi tiết 1 quả."},{"path":"/api/fruit/{fruit_id}/model3d","methods":["GET"],"summary":"Hình-học 3D của MỘT quả cho app dựng bằng mã gốc (#281) — CHỈ ĐỌC, chỉ chủ vườn."},{"path":"/api/fruit/{fruit_id}/status","methods":["PATCH"],"summary":"Cập nhật trạng thái quả: on_tree → harvested | lost."},{"path":"/api/fruit/{fruit_id}/views","methods":["GET"],"summary":"Danh sách ảnh các góc của 1 quả (để web hiện thumbnail quả-cũ INLINE khi chọn quả)."},{"path":"/api/grant","methods":["POST"],"summary":"Chủ CẤP quyền cho owner KHÁC trên VƯỜN (farm) hoặc CÂY (tree) của mình. grantor LẤY TỪ"},{"path":"/api/grant/{grant_id}","methods":["DELETE"],"summary":"Thu-hồi grant. CHỈ người CẤP (grantor) mới thu-hồi được — người khác → 404 (không lộ"},{"path":"/api/grants","methods":["GET"],"summary":"Grant mà người đăng-nhập là grantor HOẶC grantee (mới nhất trước). Làm giàu nhãn người +"},{"path":"/api/health","methods":["GET"],"summary":"CÔNG KHAI (KHÔNG auth) — app mobile kiểm KẾT NỐI + khám phá NĂNG LỰC + phiên bản"},{"path":"/api/identify","methods":["POST"],"summary":""},{"path":"/api/identify/auto","methods":["POST"],"summary":"MỘT cửa cho MỌI loại thực thể: gửi ảnh, máy tự biết đang nhìn cây, quả hay con vật rồi"},{"path":"/api/identify/video","methods":["POST"],"summary":"ĐỊNH-DANH bằng VIDEO (MVP) — nông dân quay 1 vòng quanh cây → chắt vài khung đại-diện → ĐÚNG"},{"path":"/api/identify_verdict","methods":["POST"],"summary":"PoC-Tree §3 L2 — GHI GROUND-TRUTH cho 1 lượt /api/identify (join bằng query_id)."},{"path":"/api/kind","methods":["POST"],"summary":"MỘT tấm ảnh → máy tự nói đây là CÂY, QUẢ hay CON VẬT, rồi chỉ sang cửa định-danh đúng."},{"path":"/api/login","methods":["POST"],"summary":""},{"path":"/api/logout","methods":["POST"],"summary":""},{"path":"/api/logout-all","methods":["POST"],"summary":""},{"path":"/api/me","methods":["GET"],"summary":""},{"path":"/api/population/alerts/{farm_id}","methods":["GET"],"summary":"Danh sách alerts chưa resolved trong 48h (vườn của mình)."},{"path":"/api/population/count","methods":["POST"],"summary":"Ghi số lượng đếm, trả về alerts phát sinh (nếu có). Chỉ chủ vườn ghi được."},{"path":"/api/population/farm/{farm_id}","methods":["GET"],"summary":"Dashboard tổng hợp: tổng đầu con + trạng thái từng zone (vườn của mình)."},{"path":"/api/provenance/{tree_id}","methods":["GET"],"summary":"Xuất xứ 1 cây theo tree_id (mã, CID ảnh, CID bản ghi, hash, trạng thái neo)."},{"path":"/api/remove_views","methods":["POST"],"summary":"Xoá các ảnh user chọn (điểm thấp / bấm nhầm) → cây tự cải thiện."},{"path":"/api/rename","methods":["POST"],"summary":"Sửa tên cây (user đặt nhầm / trùng tên). Chỉ đổi tên, giữ nguyên ảnh + chữ ký."},{"path":"/api/residue/interpret","methods":["POST"],"summary":"Diễn-giải tập phép đo (đã đọc từ VeData) → verdict + FarmerAlert."},{"path":"/api/residue/interpret-by-stamps","methods":["POST"],"summary":"Diễn-giải lô theo TẬP stamp_id: server resolve qua Query rồi decode → verdict."},{"path":"/api/resolve/{code}","methods":["GET"],"summary":"Cổng truy xuất — bản JSON. Cùng ba trạng thái, cùng luật, cùng hàm `_resolve_any`."},{"path":"/api/scan","methods":["POST"],"summary":"Nhận ảnh → chạy detector loài cây → trả scan_token (giữ tạm) + species_guess + top_k."},{"path":"/api/scan/confirm","methods":["POST"],"summary":"Chốt loài cho 1 scan_token → trả hướng-dẫn route sang định-danh cây (/api/identify + species)."},{"path":"/api/signup","methods":["POST"],"summary":""},{"path":"/api/species/catalog","methods":["GET"],"summary":"Danh mục loài + hoạt động (catalog/*.json) cho web dựng bộ chọn loài/hoạt động."},{"path":"/api/tree/marker","methods":["POST"],"summary":"Thêm 1 mốc ngữ-cảnh quanh cây (bồn xanh • trái...) cho sơ-đồ KHÔNG-GIAN. Chỉ chủ vườn."},{"path":"/api/tree/set_farm","methods":["POST"],"summary":"[B2] Gán/đổi FARM cho cây ĐÃ đăng-ký — BACKFILL cây mồ-côi (tạo trước khi có vườn, hoặc"},{"path":"/api/tree/set_position","methods":["POST"],"summary":"GHI vị trí người trong vườn đặt tay cho một cây. Cửa THÊM MỚI (#522)."},{"path":"/api/tree/set_species","methods":["POST"],"summary":"Gán/đổi LOÀI cho cây đã có (để gate UI: loài không-quả ẩn nút quả). Cây cũ thiếu loài"},{"path":"/api/tree/set_visibility","methods":["POST"],"summary":"Đổi VISIBILITY cây đã có — KHÔNG cần nạp ảnh lại (chủ cafe bật công-khai cây đã đăng-ký)."},{"path":"/api/tree/{tree_id}/fruit_video","methods":["POST"],"summary":"VIDEO QUẢ gắn CÂY — nông dân quay chùm quả rồi tự gắn cho cây; hệ nhận-diện SAU."},{"path":"/api/tree/{tree_id}/growth","methods":["GET"],"summary":"Chuỗi các lượt dựng-3D của một cây theo thời gian — ĐỌC-ONLY."},{"path":"/api/tree/{tree_id}/layout","methods":["GET"],"summary":"Sơ-đồ KHÔNG-GIAN quả trên 1 cây: thống-kê + vị-trí từng quả + mốc ngữ-cảnh."},{"path":"/api/tree/{tree_id}/model3d","methods":["GET"],"summary":"Dữ-liệu 3D của 1 cây cho app tự dựng cảnh native (#281, chị Thư) — CHỈ ĐỌC, additive."},{"path":"/api/tree/{tree_id}/profile","methods":["GET"],"summary":"Đọc lại HỒ-SƠ SINH-TRƯỞNG đã lưu — để app đối-chiếu với `AsyncStorage` trên máy, thay vì"},{"path":"/api/tree/{tree_id}/profile","methods":["POST"],"summary":"Ghi HỒ-SƠ SINH-TRƯỞNG của cây — CẢ KHỐI một lượt (giống/tuổi/sức-khỏe/ngày-hái/ghi-chú)."},{"path":"/api/tree/{tree_id}/video","methods":["POST"],"summary":"GĐ1 — NẠP VIDEO bổ-sung góc cho cây đã có: clip → chắt-lọc khung-hình đại-diện"},{"path":"/api/tree_by_code/{code}","methods":["GET"],"summary":""},{"path":"/api/tree_by_code/{code}/model3d","methods":["GET"],"summary":"Dữ-liệu 3D của cây theo MÃ — cho app dựng cảnh native ở lane KHÁCH VÃNG-LAI. CHỈ ĐỌC."},{"path":"/api/tree_drift/{tree_id}","methods":["GET"],"summary":"ĐO BIẾN THIÊN chữ-ký cây theo từng kênh + dự đoán vùng dễ-đổi / vùng-bền."},{"path":"/api/tree_views","methods":["GET"],"summary":"Danh sách ảnh của 1 cây + ĐIỂM mỗi ảnh (khớp với phần còn lại) — để user xem/xoá."},{"path":"/api/trees","methods":["GET"],"summary":""},{"path":"/api/update_location","methods":["POST"],"summary":"Cây ĐÃ DỜI → cập nhật vị trí mới (giữ chữ ký, ghi lịch sử di chuyển)."},{"path":"/api/verify_add","methods":["POST"],"summary":"Người dùng XÁC NHẬN cây → chụp thêm góc → hệ XÁC THỰC rồi mới bổ sung vào ĐÚNG cây."},{"path":"/api/{entity_type}/{entity_id}/did","methods":["GET"],"summary":"Đối tượng này có did:phoenix chưa. Chưa có KHÔNG phải lỗi — xem `public_view`."},{"path":"/api/{entity_type}/{entity_id}/did/request","methods":["POST"],"summary":"BƯỚC 1 — trả THÁCH-ĐỐ cho app ký bằng khoá sinh trắc của nông dân."},{"path":"/api/{entity_type}/{entity_id}/did/submit","methods":["POST"],"summary":"BƯỚC 2 — nhận chữ ký của nông dân, điền vào payload đã giữ, POST lên PhoenixKey, lưu DID."},{"path":"/api/{entity_type}/{entity_id}/event","methods":["POST"],"summary":"Ghi sự-kiện. owner TỪ auth (chống IDOR)."},{"path":"/api/{entity_type}/{entity_id}/event/{event_id}/anchor","methods":["POST"],"summary":"CHỈ chủ entity neo-mốc. Gộp toàn-bộ event tới hiện-tại thành 1 root → neo (nhãn 1455)."},{"path":"/api/{entity_type}/{entity_id}/proof/{event_id}","methods":["GET"],"summary":"Audit path chứng-minh event thuộc Merkle root chuỗi HIỆN-TẠI (so root đã neo on-chain)."},{"path":"/api/{entity_type}/{entity_id}/timeline","methods":["GET"],"summary":"Khách thấy public+approved; chủ thấy hết. verify_chain báo toàn-vẹn chuỗi GỐC."}]}