{"openapi":"3.1.0","info":{"title":"01 Spatial Visual Positioning Server","description":"01spatial Visual Positioning System Server","version":"0.1.0"},"paths":{"/health":{"get":{"tags":["system"],"summary":"Health","description":"Health check endpoint.\n\n阶段1 E″: 附带 localization 子状态（LocLoop 心跳年龄/在途数/最老在途时长）。\n定位挪出主循环后 /health 恒快——没有子状态的话定位 wedge 会变成无声故障\n（历史上\"/health 变慢\"正是发现本 bug 的信号）。wedge 判据：\nin_flight==0 且 heartbeat_age 大，或 oldest_inflight_s > 硬上限(~180s)。","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Health Health Get"}}}}}}},"/version":{"get":{"tags":["system"],"summary":"Version","description":"Get version information.\n\nPrioritizes reading /01/version.json (production environment).\nIf it doesn't exist, returns version from application config.","operationId":"version_version_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Version Version Get"}}}}}}},"/healthz/gpu":{"get":{"tags":["system"],"summary":"Healthz Gpu","description":"GPU resource health check (L7 observability).\n\nNo auth required. Ops / monitoring systems can poll this to observe:\n- Per-GPU `is_building`, `active_requests`, `mem_free_mb`\n- Resident model keys in the shared_models pool (config_hash tags)\n- Cumulative event counters (OOM, build acquisition failures, session\n  evictions, orphan recoveries, drain timeouts)","operationId":"healthz_gpu_healthz_gpu_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Healthz Gpu Healthz Gpu Get"}}}}}}},"/debug/gpu-mark-building":{"post":{"tags":["debug"],"summary":"Gpu Mark Building","description":"Mark a GPU as 'building' (debug/testing use).\n\nBody:\n- gpu_id: int — the GPU ID to mark\n\nUsed to test the scenario where localization is blocked during a build.","operationId":"gpu_mark_building_debug_gpu_mark_building_post","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Request"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Gpu Mark Building Debug Gpu Mark Building Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/debug/gpu-mark-available":{"post":{"tags":["debug"],"summary":"Gpu Mark Available","description":"Mark a GPU as available (debug/testing use).\n\nBody:\n- gpu_id: int — the GPU ID to mark\n\nUsed to test the recovery scenario after a build completes and localization resumes.","operationId":"gpu_mark_available_debug_gpu_mark_available_post","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Request"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Gpu Mark Available Debug Gpu Mark Available Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/debug/resume-pending-jobs":{"post":{"tags":["debug"],"summary":"Resume Pending Jobs","description":"Re-queue pending build jobs (debug / recovery use).\n\nCall this after a server restart to resume jobs that were queued before the restart.","operationId":"resume_pending_jobs_debug_resume_pending_jobs_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Resume Pending Jobs Debug Resume Pending Jobs Post"}}}}}}},"/auth/legal/current":{"get":{"tags":["authentication"],"summary":"Current registration legal documents","description":"返回注册必须接受/确认的当前不可变法律文件版本。","operationId":"current_legal_documents_auth_legal_current_get","parameters":[{"name":"locale","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":16},{"type":"null"}],"title":"Locale"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/legal/documents/{kind}":{"get":{"tags":["authentication"],"summary":"Redirect to current legal document","operationId":"current_legal_document_redirect_auth_legal_documents__kind__get","parameters":[{"name":"kind","in":"path","required":true,"schema":{"enum":["user-agreement","privacy-notice"],"type":"string","title":"Kind"}},{"name":"locale","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":16},{"type":"null"}],"title":"Locale"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/legal/documents/{kind}/{version}":{"get":{"tags":["authentication"],"summary":"Redirect versioned legal document to a language","description":"兼容旧链接，但将其收敛到带明确语言的不可变 URL。","operationId":"versioned_legal_document_redirect_auth_legal_documents__kind___version__get","parameters":[{"name":"kind","in":"path","required":true,"schema":{"enum":["user-agreement","privacy-notice"],"type":"string","title":"Kind"}},{"name":"version","in":"path","required":true,"schema":{"type":"string","title":"Version"}},{"name":"locale","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":16},{"type":"null"}],"title":"Locale"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/legal/documents/{kind}/{version}/{locale}":{"get":{"tags":["authentication"],"summary":"Versioned and localized legal document","description":"提供版本、语言和哈希共同标识的只读法律文件。","operationId":"legal_document_auth_legal_documents__kind___version___locale__get","parameters":[{"name":"kind","in":"path","required":true,"schema":{"enum":["user-agreement","privacy-notice"],"type":"string","title":"Kind"}},{"name":"version","in":"path","required":true,"schema":{"type":"string","title":"Version"}},{"name":"locale","in":"path","required":true,"schema":{"type":"string","title":"Locale"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/legal/status":{"get":{"tags":["authentication"],"summary":"Current user's legal acceptance status","description":"返回当前用户是否已接受当前版本；待重签 token 也允许访问。","operationId":"current_user_legal_status_auth_legal_status_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"locale","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":16},{"type":"null"}],"title":"Locale"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/legal/assent/{version}/{locale}":{"get":{"tags":["authentication"],"summary":"Versioned clickwrap statement","description":"返回用户实际勾选声明的不可变版本，供历史证据重建。","operationId":"legal_assent_statement_auth_legal_assent__version___locale__get","parameters":[{"name":"version","in":"path","required":true,"schema":{"type":"string","title":"Version"}},{"name":"locale","in":"path","required":true,"schema":{"type":"string","title":"Locale"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/legal/accept":{"post":{"tags":["authentication"],"summary":"Accept current legal documents","description":"为已登录用户记录重签，并换发解除业务闸门的新 token。","operationId":"accept_current_legal_documents_auth_legal_accept_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegalAcceptanceCreate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/auth/register":{"post":{"tags":["authentication"],"summary":"User Registration","description":"Create a new user account","operationId":"register_auth_register_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserCreate"}}},"required":true},"responses":{"200":{"description":"User registered successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponse"},"example":{"id":1,"name":"John Doe","email":"john@example.com","provider":"local","created_at":"2025-01-20T10:30:00Z"}}}},"400":{"description":"Email already registered","content":{"application/json":{"example":{"detail":"Email already registered"}}}},"422":{"description":"Validation error - invalid email or password","content":{"application/json":{"example":{"detail":[{"loc":["body","email"],"msg":"value is not a valid email address","type":"value_error.email"}]}}}}}}},"/auth/verify-email":{"post":{"tags":["authentication"],"summary":"Verify Email","operationId":"verify_email_auth_verify_email_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailVerificationRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/resend-verification":{"post":{"tags":["authentication"],"summary":"Resend Verification","operationId":"resend_verification_auth_resend_verification_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/auth/login":{"post":{"tags":["authentication"],"summary":"User Login","description":"Authenticate user and return JWT access token","operationId":"login_auth_login_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserLogin"}}},"required":true},"responses":{"200":{"description":"Login successful","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Token"},"example":{"access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...","token_type":"bearer","expires_in":28800}}}},"401":{"description":"Authentication failed - incorrect email or password","content":{"application/json":{"example":{"detail":"Incorrect email or password"}}}},"422":{"description":"Validation error - invalid request format","content":{"application/json":{"example":{"detail":[{"loc":["body","email"],"msg":"field required","type":"value_error.missing"}]}}}}}}},"/auth/me":{"get":{"tags":["authentication"],"summary":"Get Current User","description":"Retrieve current authenticated user information","operationId":"get_current_user_auth_me_get","responses":{"200":{"description":"User information retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponse"},"example":{"id":1,"name":"John Doe","email":"john@example.com","avatar":"https://example.com/avatar.jpg","provider":"local","created_at":"2025-01-20T10:30:00Z","api_key":"ajDloeXgHNFGAHY2eFTtWlDzvfa6wfpAErKRh3QF9Q"}}}},"401":{"description":"Not authenticated - missing or invalid token","content":{"application/json":{"example":{"detail":"Not authenticated"}}}},"404":{"description":"User not found","content":{"application/json":{"example":{"detail":"User not found"}}}}},"security":[{"HTTPBearer":[]}]}},"/auth/refresh":{"post":{"tags":["authentication"],"summary":"Refresh Access Token","description":"用当前未过期的 token 换发一个新的 access token（滑动续期）。token 已过期/无效则 401。","operationId":"refresh_access_token_auth_refresh_post","responses":{"200":{"description":"New token issued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Token"}}}},"401":{"description":"Token expired, invalid, or missing"},"404":{"description":"User not found"}},"security":[{"HTTPBearer":[]}]}},"/auth/update-profile":{"post":{"tags":["authentication"],"summary":"Update User Profile","description":"Update current user's profile information (name)","operationId":"update_profile_auth_update_profile_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserUpdate"}}},"required":true},"responses":{"200":{"description":"Profile updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponse"},"example":{"id":1,"name":"New Name","email":"john@example.com","provider":"local","created_at":"2025-01-20T10:30:00Z","api_key":"ajDloeXgHNFGAHY2eFTtWlDzvfa6wfpAErKRh3QF9Q"}}}},"401":{"description":"Not authenticated"},"404":{"description":"User not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/auth/stats":{"get":{"tags":["authentication"],"summary":"Get User Stats","description":"Get statistics for the current user.\n\nReturns project count, map count, and total image count.","operationId":"get_user_stats_auth_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/auth/usage":{"get":{"tags":["authentication"],"summary":"User usage statistics (build/localization/storage)","description":"Comprehensive usage stats for current user.\n\nBuild counts (project/map), localization counts (total + this month),\nstorage breakdown (build artifacts / 3D content / loc-archive images / total).\n\nFilesystem walk cached 5min per-user. ?no_cache=true 强制重算。","operationId":"get_user_usage_endpoint_auth_usage_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"no_cache","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"No Cache"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/api-key/generate":{"post":{"tags":["authentication"],"summary":"Generate API Key","description":"Generate or regenerate user API key for authentication","operationId":"generate_api_key_auth_api_key_generate_post","responses":{"200":{"description":"API Key generated successfully","content":{"application/json":{"schema":{},"example":{"api_key":"ajDloeXgHNFGAHY2eFTtWlDzvfa6wfpAErKRh3QF9Q","message":"API Key generated successfully"}}}},"401":{"description":"Not authenticated - missing or invalid token","content":{"application/json":{"example":{"detail":"Not authenticated"}}}},"404":{"description":"User not found","content":{"application/json":{"example":{"detail":"User not found"}}}}},"security":[{"HTTPBearer":[]}]}},"/auth/logout":{"post":{"tags":["authentication"],"summary":"Logout","description":"User logout.\n\nClient should delete locally stored Token.\nServer does nothing (JWT is stateless).","operationId":"logout_auth_logout_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/auth/delete-account":{"post":{"tags":["authentication"],"summary":"Permanently close the current account","description":"关闭空账号、撤销全部凭证并最小化直接身份信息。\n\n活跃项目或地图必须先走其各自的删除/转移状态机，避免关闭账号时绕过建图、\n存储和计费清理。密码账号必须再次提供当前密码；OAuth-only 账号依靠当前\nprovider 登录会话和精确确认词。","operationId":"delete_account_auth_delete_account_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountClosureRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/auth/change-password":{"post":{"tags":["authentication"],"summary":"Change Password","description":"Change password.\n\nRequires current password for verification.","operationId":"change_password_auth_change_password_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PasswordChange"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/auth/providers":{"get":{"tags":["authentication"],"summary":"List Oauth Providers","description":"List OAuth providers enabled for this server (per-region allowlist).\n\nThe server's `oauth.enabled` config (e.g. EU=[\"google\",\"apple\"], CN=[\"wechat\"])\ndecides which providers are exposed. Providers not in the allowlist are simply\nnot returned, so the frontend never offers a login button the server cannot honor.\n\nRate-limited (auth_login bucket) to prevent enumeration / probe spam.","operationId":"list_oauth_providers_auth_providers_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/auth/login/{provider}":{"get":{"tags":["authentication"],"summary":"Oauth Login","description":"OAuth Login Entry Point — redirect to third-party authorization page.\n\nThe callback URL is server-derived (not caller-controlled): OAuth requires\nthat authorize.redirect_uri == callback.redirect_uri, and the callback\nhandler can't read query params from the original /auth/login call. If\nwe ever need per-client callback URLs, encode them inside the CSRF state.\n\nRate-limited (auth_login bucket): each call consumes one CSRF state slot\n(5000 max), so without this limit an attacker could evict legitimate users'\nstates by hammering this endpoint.","operationId":"oauth_login_auth_login__provider__get","parameters":[{"name":"provider","in":"path","required":true,"schema":{"type":"string","title":"Provider"}},{"name":"intent","in":"query","required":false,"schema":{"enum":["login","register"],"type":"string","default":"login","title":"Intent"}},{"name":"legal_accepted","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Legal Accepted"}},{"name":"user_agreement_version","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"User Agreement Version"}},{"name":"privacy_notice_version","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Privacy Notice Version"}},{"name":"assent_version","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Assent Version"}},{"name":"document_locale","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":16},{"type":"null"}],"title":"Document Locale"}},{"name":"business_capacity_confirmed","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Business Capacity Confirmed"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/callback/{provider}":{"get":{"tags":["authentication"],"summary":"Oauth Callback Get","description":"OAuth callback handler (GET method).\n\nGoogle and WeChat use GET method for callback. Rate-limited so this\nendpoint can't be turned into a third-party-API amplifier (each call\ntriggers a real HTTPS request to the OAuth provider).","operationId":"oauth_callback_get_auth_callback__provider__get","parameters":[{"name":"provider","in":"path","required":true,"schema":{"type":"string","title":"Provider"}},{"name":"code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code"}},{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"}},{"name":"error","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},{"name":"error_description","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Description"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["authentication"],"summary":"Oauth Callback Post","description":"OAuth callback handler (POST method).\n\nApple uses form_post method for callback. Rate-limited per the same\nrationale as the GET handler.","operationId":"oauth_callback_post_auth_callback__provider__post","parameters":[{"name":"provider","in":"path","required":true,"schema":{"type":"string","title":"Provider"}}],"requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_oauth_callback_post_auth_callback__provider__post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/oauth-config":{"get":{"tags":["authentication"],"summary":"Get Oauth Config","description":"Get per-server OAuth client_ids for the frontend.\n\nOnly providers in this server's `oauth.enabled` allowlist are included\n(e.g. EU returns google+apple, CN returns wechat). The frontend uses the\nreturned client_id values to render native Sign-In buttons / SDKs.","operationId":"get_oauth_config_auth_oauth_config_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/auth/link/{provider}":{"post":{"tags":["authentication"],"summary":"Link Oauth Provider","description":"已登录用户启动 OAuth 账号关联流程。\n\n返回 {authorize_url}, 前端收到后 window.location.assign(url), 跳 Google/\nApple/WeChat 授权, 回调到 /auth/callback/{provider} 时 verify_state 会拿到\nlink_user_id, 走 _handle_link_callback 把 (provider, oauth_id) 绑到当前用户。","operationId":"link_oauth_provider_auth_link__provider__post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"provider","in":"path","required":true,"schema":{"type":"string","title":"Provider"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/unlink/{provider}":{"post":{"tags":["authentication"],"summary":"Unlink Oauth Provider","description":"解绑 OAuth 账号。\n\n要求:必须还有可用登录方式 (user.password 非空),否则解绑后用户无法再登录 →\n拒绝操作。回答是 403 + errorKey=unlink_no_password_fallback。","operationId":"unlink_oauth_provider_auth_unlink__provider__post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"provider","in":"path","required":true,"schema":{"type":"string","title":"Provider"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/avatar":{"post":{"tags":["authentication"],"summary":"Upload Avatar","description":"用户上传自定义头像。\n\n流程:\n  1. 大小 / MIME 初筛\n  2. Pillow 解码 → 中心裁剪 → 512×512 → WebP (off event loop, asyncio.to_thread)\n  3. atomic write 到 avatar_dir/{user_id}_{ts}{rand}.webp (off event loop)\n  4. 更新 user.avatar + avatar_source='custom' (sticky)\n  5. flush 失败 → 清新文件; 成功 → 删旧 custom 文件\n  6. 返完整 UserResponse, 前端不需要再调 /auth/me\n\n安全:\n  * 不信任 Content-Type header (客户端可伪造), 真正用 Pillow decode 验证\n  * 文件名用 {user_id}_{ts}_{rand} — 没有用户可控部分, 杜绝 path traversal\n  * 最终统一 WebP 扩展名, 杜绝 .php/.html 等可执行扩展\n  * tempfile + atomic rename 防止并发写入截断","operationId":"upload_avatar_auth_avatar_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_avatar_auth_avatar_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]},"delete":{"tags":["authentication"],"summary":"Delete Avatar","description":"清除自定义头像。\n\n语义:\n  * OAuth 账户 → avatar=null, 下次 OAuth 登录会重新同步 picture (source='oauth')\n  * 本地账户 → avatar=null, source=null, UI 回退到首字母\n\n返完整 UserResponse, 前端 setState 直接刷新, 省掉 /auth/me round trip。","operationId":"delete_avatar_auth_avatar_delete","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/auth/check-password-strength":{"post":{"tags":["authentication"],"summary":"Check Password Strength","description":"Check password strength without creating an account","operationId":"check_password_strength_endpoint_auth_check_password_strength_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_check_password_strength_endpoint_auth_check_password_strength_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/project/":{"get":{"tags":["project"],"summary":"List Projects","description":"Retrieve all projects owned by the current user","operationId":"list_projects_project__get","responses":{"200":{"description":"Projects retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectListResponse"},"example":{"projects":[{"id":1,"name":"Downtown Mapping","desc":"City center navigation project","user_id":123,"created_at":"2025-01-20T10:30:00Z"}],"total":1}}}},"401":{"description":"Not authenticated","content":{"application/json":{"example":{"detail":"Not authenticated"}}}}},"security":[{"HTTPBearer":[]}]}},"/project/create":{"post":{"tags":["project"],"summary":"Create Project","description":"Create a new project to organize maps","operationId":"create_project_project_create_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectCreate"}}},"required":true},"responses":{"200":{"description":"Project created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"},"example":{"id":1,"name":"Downtown Mapping","desc":"City center navigation project","user_id":123,"created_at":"2025-01-20T10:30:00Z"}}}},"401":{"description":"Not authenticated","content":{"application/json":{"example":{"detail":"Not authenticated"}}}},"422":{"description":"Validation error","content":{"application/json":{"example":{"detail":[{"loc":["body","name"],"msg":"field required","type":"value_error.missing"}]}}}}},"security":[{"HTTPBearer":[]}]}},"/project/{project_id}/update":{"post":{"tags":["project"],"summary":"Update Project","description":"Update project name or description","operationId":"update_project_project__project_id__update_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","title":"Project Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectUpdate"}}}},"responses":{"200":{"description":"Project updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"},"example":{"id":1,"name":"Updated Name","desc":"Updated description","user_id":123,"created_at":"2025-01-20T10:30:00Z"}}}},"401":{"description":"Not authenticated"},"403":{"description":"Not authorized to update this project"},"404":{"description":"Project not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/project/{project_id}/delete":{"post":{"tags":["project"],"summary":"Delete Project","description":"Delete a project container and its project-level index data. Map rows are not deleted.","operationId":"delete_project_project__project_id__delete_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","title":"Project Id"}}],"responses":{"200":{"description":"Project deleted successfully","content":{"application/json":{"schema":{},"example":{"message":"Project deleted successfully"}}}},"401":{"description":"Not authenticated"},"403":{"description":"Not authorized to delete this project"},"404":{"description":"Project not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/project/{project_id}/maps":{"get":{"tags":["project"],"summary":"List Project Maps","description":"Retrieve all maps belonging to a specific project","operationId":"list_project_maps_project__project_id__maps_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","title":"Project Id"}}],"responses":{"200":{"description":"Maps retrieved successfully","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MapResponse"},"title":"Response List Project Maps Project  Project Id  Maps Get"},"example":[{"id":123,"name":"Floor 1","desc":"First floor mapping","type":"sfm-refine","input":"images","project_id":1,"creator_id":123,"status":"ready","image_num":150,"created_at":"2025-01-20T10:30:00Z"}]}}},"401":{"description":"Not authenticated"},"403":{"description":"Not authorized to access this project"},"404":{"description":"Project not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/project/{project_id}/build-index":{"post":{"tags":["project"],"summary":"Build Project Index","description":"Trigger a rebuild of the project-level unified Faiss index (used for cross-map localization).","operationId":"build_project_index_project__project_id__build_index_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","title":"Project Id"}}],"responses":{"200":{"description":"Index build succeeded or was scheduled","content":{"application/json":{"schema":{},"example":{"status":"success","project_id":1,"total_descriptors":5000,"map_count":3}}}},"403":{"description":"Not authorized"},"404":{"description":"Project not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/project/{project_id}/index-status":{"get":{"tags":["project"],"summary":"Project Index Status","description":"Query the current state of the project-level unified index.","operationId":"project_index_status_project__project_id__index_status_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","title":"Project Id"}}],"responses":{"200":{"description":"Index state","content":{"application/json":{"schema":{},"example":{"status":"ready","project_id":1,"total_descriptors":5000,"map_count":3}}}},"403":{"description":"Not authorized"},"404":{"description":"Project not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/project/{project_id}/project-key":{"get":{"tags":["project"],"summary":"Get Project Key","description":"Get the encrypted project_key used by clients for cross-map localization.","operationId":"get_project_key_project__project_id__project_key_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","title":"Project Id"}}],"responses":{"200":{"description":"project_key retrieved","content":{"application/json":{"schema":{},"example":{"project_id":1,"project_key":"aBcDeFgHiJkLmNoPqRsT..."}}}},"403":{"description":"Not authorized"},"404":{"description":"Project not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/configurator-capabilities":{"get":{"tags":["map"],"summary":"Configurator Capabilities","description":"Map Configurator 与 Pipeline28 共用的版本化手工约束上限。","operationId":"configurator_capabilities_map_configurator_capabilities_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/map/create":{"post":{"tags":["map"],"summary":"Create Map","description":"Create a new map record with unique timestamp identifier","operationId":"create_map_map_create_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MapCreate"}}},"required":true},"responses":{"200":{"description":"Map created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MapResponse"},"example":{"id":123,"name":"Downtown Office Building","desc":"3rd floor mapping project","type":"","input":"images","project_id":45,"creator_id":1,"status":"created","latitude":37.7749,"longitude":-122.4194,"altitude":10.5,"dir":"20250120-143025123","map_key":"ajDloeXgHNFGAHY2eFTtWlDzvfa6wfpAErKRh3QF9Q","image_num":0,"created_at":"2025-01-20T14:30:25Z"}}}},"401":{"description":"Not authenticated","content":{"application/json":{"example":{"detail":"Not authenticated"}}}},"422":{"description":"Validation error - invalid request data","content":{"application/json":{"example":{"detail":[{"loc":["body","name"],"msg":"field required","type":"value_error.missing"}]}}}}},"security":[{"HTTPBearer":[]}]}},"/map/{map_id}/update":{"post":{"tags":["map"],"summary":"Update Map","description":"Update map name, description, or location information","operationId":"update_map_map__map_id__update_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MapUpdate"}}}},"responses":{"200":{"description":"Map updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MapResponse"},"example":{"id":123,"name":"Updated Map Name","desc":"Updated description","type":"sfm-refine","input":"images","status":"ready","latitude":37.7749,"longitude":-122.4194}}}},"401":{"description":"Not authenticated"},"403":{"description":"Not authorized to access this map"},"404":{"description":"Map not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/delete":{"post":{"tags":["map"],"summary":"Delete Map","description":"Delete a map and all associated files","operationId":"delete_map_map__map_id__delete_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"responses":{"200":{"description":"Map deleted successfully","content":{"application/json":{"schema":{},"example":{"message":"Map deleted successfully","deleted_clone_ids":[456]}}}},"400":{"description":"Cannot delete while building","content":{"application/json":{"example":{"detail":"Cannot delete map while it is building or queued. Please cancel the build first."}}}},"401":{"description":"Not authenticated"},"403":{"description":"Not authorized to access this map"},"404":{"description":"Map not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/upload-priors":{"post":{"tags":["map"],"summary":"Upload Prior Poses","description":"Upload prior pose information as a JSON file for map building","operationId":"upload_priors_map__map_id__upload_priors_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_priors_map__map_id__upload_priors_post"}}}},"responses":{"200":{"description":"Priors uploaded successfully","content":{"application/json":{"schema":{},"example":{"message":"Priors file uploaded successfully","path":"/tmp/vps_staging/123/456/priors.json","size":15234}}}},"400":{"description":"Invalid request","content":{"application/json":{"examples":{"building":{"value":{"detail":"Cannot upload priors while map is building or queued"}},"invalid_json":{"value":{"detail":"Invalid JSON format: Expecting property name..."}},"not_json":{"value":{"detail":"File must be a JSON file"}}}}}},"413":{"description":"File too large","content":{"application/json":{"example":{"detail":"JSON file too large. Maximum: 100 MB"}}}},"401":{"description":"Not authenticated"},"403":{"description":"Not authorized to access this map"},"404":{"description":"Map not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/delete-priors":{"post":{"tags":["map"],"summary":"Delete Priors","description":"Delete uploaded prior poses JSON file.\n\nRemoves priors.json file from both staging and source directories.","operationId":"delete_priors_map__map_id__delete_priors_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/upload-status":{"get":{"tags":["map"],"summary":"Get Upload Status","description":"Get upload status.\n\nCheck files in staging or source directory.\n- If map is building or completed, check source directory\n- If created status, check source directory first (files in source after Cancel), then check staging","operationId":"get_upload_status_map__map_id__upload_status_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/clear-staging":{"post":{"tags":["map"],"summary":"Clear Staging","description":"Clear staging area.\n\nUsed to clean up previous staged files when canceling or re-uploading.","operationId":"clear_staging_map__map_id__clear_staging_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/upload-e57":{"post":{"tags":["map"],"summary":"Upload E57","description":"Upload a NavVis E57 ZIP.\n\nZIP is streamed to disk, extracted, the first .e57 is saved as navvis.e57\nand a navvis_config.json is written (point-cloud presence auto-detected).","operationId":"upload_e57_map__map_id__upload_e57_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_e57_map__map_id__upload_e57_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/upload-hexagon":{"post":{"tags":["map"],"summary":"Upload Hexagon","description":"Upload a Hexagon E57 ZIP.\n\nSame E57 schema as NavVis (images2D + data3D); reuses _upload_and_extract_e57_zip().\nReturns `with_pointcloud` so the frontend can prompt when the cloud is missing.","operationId":"upload_hexagon_map__map_id__upload_hexagon_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_hexagon_map__map_id__upload_hexagon_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/upload-matterport":{"post":{"tags":["map"],"summary":"Upload Matterport","description":"Upload a Matterport E57 ZIP.\n\nZIP is streamed to disk and the first .e57 is saved as matterport.e57.\nThe E57 carries images, poses and the point cloud — no other files needed.","operationId":"upload_matterport_map__map_id__upload_matterport_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_matterport_map__map_id__upload_matterport_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/upload-leica":{"post":{"tags":["map"],"summary":"Upload Leica","description":"Upload a Leica RTC360 E57 ZIP.\n\nZIP is streamed to disk and the first .e57 is saved as leica.e57.\nThe E57 carries cubemap images, poses and the point cloud — self-contained.","operationId":"upload_leica_map__map_id__upload_leica_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_leica_map__map_id__upload_leica_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/upload-polycam":{"post":{"tags":["map"],"summary":"Upload Polycam","description":"上传 Polycam ZIP，并按实际内容路由到 Raw Data 或 Mesh 存储。","operationId":"upload_polycam_map__map_id__upload_polycam_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_polycam_map__map_id__upload_polycam_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/upload-osv":{"post":{"tags":["map"],"summary":"Upload Osv","description":"[遗留 API,前端无调用方] 上传 360 视频文件（dual-fisheye 全局闭环 SfM 建图输入）。\n\n输入可为厂商 equirect mp4（反切共光心虚拟鱼眼，内容探测决定）或 DJI raw .osv（物理解码）。\n流式写入 staging/{map_id}/dual_fisheye_input.<ext>（run_dual_fisheye_sfm.sh 在 source 下 glob），\n并写 dual_fisheye_config.json，供 trigger_build 的 dual-fisheye 检测识别。pipeline28 路由由 build 请求的\npipeline_version 或 config default_pipeline_version 决定（此遗留端点不写 .pipeline_version dotfile）。\n（新流程请用 POST /upload-360 + /parse；本端点保留路由名向后兼容。）\n\ncharuco_board（可选，如 \"a4\"）：声明场景含该规格 ChArUco 板 → build_service 触发加权 BA metric 对齐\n（消 drift + datum 定坐标系）；未声明则跳过对齐（arbitrary scale，同今日默认）。","operationId":"upload_osv_map__map_id__upload_osv_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_osv_map__map_id__upload_osv_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/upload-video":{"post":{"tags":["map"],"summary":"Upload Pinhole Video","description":"上传普通手机 pinhole 视频；解析与建图由后续 ``POST /parse`` 驱动。","operationId":"upload_pinhole_video_map__map_id__upload_video_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_pinhole_video_map__map_id__upload_video_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/upload-360":{"post":{"tags":["map"],"summary":"Upload 360 Zip","description":"上传 ERP 全景视频 zip(内含厂商导出的 equirectangular mp4)→ 解压取 mp4 → source/dual_fisheye_input.<ext>\n+ dual_fisheye_config.json + .pipeline_version=28。之后 POST /map/{id}/parse 触发解析。","operationId":"upload_360_zip_map__map_id__upload_360_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_360_zip_map__map_id__upload_360_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/upload-erp-images":{"post":{"tags":["map"],"summary":"Upload Erp Images Zip","description":"上传 ERP 全景**图片** zip(旧地图只有图片、无视频时的重建捷径)→ 解压所有全景图 → source/erp_images/\n+ dual_fisheye_config.json(source_kind=erp_images)+ .pipeline_version=28。之后 POST /map/{id}/parse 触发解析\n(解析阶段识别\"输入是目录\"走 ingest_image_dir,跳过视频抽帧,产物与视频路径同构 → 建图 pipeline 一行不改)。","operationId":"upload_erp_images_zip_map__map_id__upload_erp_images_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_erp_images_zip_map__map_id__upload_erp_images_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/prepare-input":{"post":{"tags":["map"],"summary":"Prepare Mapping Input","description":"把 app/scanner 原始上传异步归一为报价与建图共同消费的不可变物理输入快照。","operationId":"prepare_mapping_input_map__map_id__prepare_input_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"input","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Input"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/parse":{"post":{"tags":["map"],"summary":"Trigger Parse 360","description":"触发解析(后台):抽帧→equirect+缩略图→反切 dual-fisheye→charuco 完整检测→parse_report。\n自动检测 charuco(缺省用标准 a4 board 规格);完成后 map.status=parsed,前端轮询 /parse-status。","operationId":"trigger_parse_360_map__map_id__parse_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/parse-status":{"get":{"tags":["map"],"summary":"Parse Status 360","description":"轮询解析进度(两阶段进度条阶段2)。parsed 时附 parse_report(帧数 + charuco 检测结果)。","operationId":"parse_status_360_map__map_id__parse_status_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/parse-cancel":{"post":{"tags":["map"],"summary":"Cancel Parse 360","description":"取消进行中的解析；存在旧发布快照时恢复 parsed，否则退回 created。","operationId":"cancel_parse_360_map__map_id__parse_cancel_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/equirect-thumbs":{"get":{"tags":["map"],"summary":"Equirect Thumbs 360","description":"configurator 拖动条:列 equirect 缩略图帧名(默认加载缩略图,原图按需 Load)。","operationId":"equirect_thumbs_360_map__map_id__equirect_thumbs_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/pinhole-thumbs":{"get":{"tags":["map"],"summary":"Pinhole Thumbs Video","description":"列出手机视频动态抽取的 pinhole 缩略帧。","operationId":"pinhole_thumbs_video_map__map_id__pinhole_thumbs_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/configurator-config":{"get":{"tags":["map"],"summary":"Get Configurator Config","description":"返回该地图最后一次 configured 建图使用的人工约束配置。","operationId":"get_configurator_config_map__map_id__configurator_config_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MapConfiguratorConfigResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/equirect/{kind}/{frame}":{"get":{"tags":["map"],"summary":"Equirect Image 360","description":"serve equirect 缩略图(kind=thumb)或全分辨率原图(kind=full)。configurator 点缩略图 Load 取 full。","operationId":"equirect_image_360_map__map_id__equirect__kind___frame__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"kind","in":"path","required":true,"schema":{"type":"string","title":"Kind"}},{"name":"frame","in":"path","required":true,"schema":{"type":"string","title":"Frame"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/pinhole/{kind}/{frame}":{"get":{"tags":["map"],"summary":"Pinhole Image Video","description":"为 Configurator 提供 pinhole 缩略图或全分辨率抽帧。","operationId":"pinhole_image_video_map__map_id__pinhole__kind___frame__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"kind","in":"path","required":true,"schema":{"type":"string","title":"Kind"}},{"name":"frame","in":"path","required":true,"schema":{"type":"string","title":"Frame"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/upload-kiri":{"post":{"tags":["map"],"summary":"Upload Kiri","description":"Upload a KIRI Engine Raw Data ZIP.\n\nStreamed to the staging directory; a kiri_config.json is also written\nto record the upload parameters.","operationId":"upload_kiri_map__map_id__upload_kiri_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_kiri_map__map_id__upload_kiri_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/submit-cloud-link":{"post":{"tags":["map"],"summary":"Submit Cloud Link","description":"Submit a cloud-drive link (gdrive / dropbox / aliyun). The server downloads asynchronously to staging; the frontend later calls /build.\n\nFlow:\n1. Verify map ownership + state + region + brand + API key readiness.\n2. Idempotency: if the map already has a pending/downloading job, return 409.\n3. Google Drive: pre-fetch metadata (name/size/mimeType), validate type + size cap.\n4. Clear stale files in staging + write the input brand marker.\n5. Enqueue the background download job.\n\nSupported cloud_type values:\n- gdrive: Google Drive public share link (EU region)\n- dropbox: Dropbox public share link\n- aliyun: Aliyun Drive file_id (CN region; OAuth required first)","operationId":"submit_cloud_link_map__map_id__submit_cloud_link_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CloudLinkSubmitRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/submit-cloud-mesh":{"post":{"tags":["map"],"summary":"Submit Cloud Mesh","description":"Synchronously download a Polycam/Kiri mesh (.glb, or .zip with a single .glb) from the cloud.\n\nDifferences from submit-cloud-link:\n- Synchronous (blocking): downloads inline, returns 200 (meshes are usually <100 MB, takes seconds).\n- Does not create a DB job: no progress tracking, no cancel (not needed for small files).\n- Reuses `_download_via_provider`: same provider dispatch + range-downloader\n  (parallel chunks + retries) — same throughput as the main download path.\n- Output lands at staging/{user}/{map}/polycam_scene.glb;\n  after the build finishes, build_service auto-copies it to map/mesh/polycam_scene.glb.\n\nFlow mirrors the upload-polycam-mesh endpoint — only the input source\nchanges from UploadFile to a cloud URL.","operationId":"submit_cloud_mesh_map__map_id__submit_cloud_mesh_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CloudMeshSubmitRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/cloud-download-status":{"get":{"tags":["map"],"summary":"Cloud Download Status","description":"Latest cloud-download progress for this map (frontend polls every 1-3 s).","operationId":"cloud_download_status_map__map_id__cloud_download_status_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/cancel-cloud-download":{"post":{"tags":["map"],"summary":"Cancel Cloud Download","description":"Cancel an in-flight cloud download for this map. Idempotent — already-terminal\ndownloads return 200 (already_terminal) rather than 400, because the frontend's\npoll+cancel race can deliver the cancel right as the download finishes and we\ndon't want to report that as a failure.","operationId":"cancel_cloud_download_map__map_id__cancel_cloud_download_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/set-navvis-path":{"post":{"tags":["map"],"summary":"Set Navvis Path","description":"Set the server-side absolute path of a NavVis .e57 file (admin alternative to upload).\n\nCreates a symlink to the existing file so huge uploads are avoided.\nPoint-cloud presence is auto-detected.","operationId":"set_navvis_path_map__map_id__set_navvis_path_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_set_navvis_path_map__map_id__set_navvis_path_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/set-polycam-path":{"post":{"tags":["map"],"summary":"Set Polycam Path","description":"Set the server-side absolute path of a Polycam ZIP (admin alternative to upload).\n\nCreates a symlink to the existing file so huge uploads are avoided.","operationId":"set_polycam_path_map__map_id__set_polycam_path_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_set_polycam_path_map__map_id__set_polycam_path_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/upload-chcnav-poses":{"post":{"tags":["map"],"summary":"Upload Chcnav Poses","description":"Validate a CHCNAV Metashape.txt pose file against the panorama set on disk.\n\nAccepts server-side paths to the panorama directory and the pose file,\nchecks format + match rate, stages the files for /build.","operationId":"upload_chcnav_poses_map__map_id__upload_chcnav_poses_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_upload_chcnav_poses_map__map_id__upload_chcnav_poses_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/upload-chcnav":{"post":{"tags":["map"],"summary":"Upload Chcnav","description":"Upload CHCNAV panoramas + Metashape.txt pose file together.\n\nStreams both to the staging directory and validates format + match rate\nbefore accepting.","operationId":"upload_chcnav_map__map_id__upload_chcnav_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_chcnav_map__map_id__upload_chcnav_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/upload-xgrid":{"post":{"tags":["map"],"summary":"Upload Xgrid","description":"Upload an XGRID E57 ZIP.\n\nZIP is streamed to disk, the first .e57 is saved as xgrid.e57, and an\nxgrid_config.json is written (point-cloud presence auto-detected).\nThe E57 carries panoramas (images2D spherical), poses and point cloud (data3D).","operationId":"upload_xgrid_map__map_id__upload_xgrid_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_xgrid_map__map_id__upload_xgrid_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/upload-fjd":{"post":{"tags":["map"],"summary":"Upload Fjd","description":"Upload an FJD ZIP (panoramas + CSV poses + E57 point cloud).\n\nFJD ZIP layout:\n- *.jpg / *.jpeg / *.png  → staging/pano/         (panoramas)\n- pano-pose-info.csv      → staging/pano-pose-info.csv  (poses)\n- *.e57                   → staging/fjd.e57         (point cloud, optional)\n- Ignored: __MACOSX, *.fjdata, *.txt and similar metadata","operationId":"upload_fjd_map__map_id__upload_fjd_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_fjd_map__map_id__upload_fjd_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/upload-faro":{"post":{"tags":["map"],"summary":"Upload Faro","description":"Upload a FARO ZIP containing one .e57 per scan station.\n\nFARO ZIP layout:\n- *.e57              → staging/e57/  (each E57 contains panoramas + point cloud + poses)\n- Ignored:           __MACOSX, .DS_Store, ._* and similar metadata files","operationId":"upload_faro_map__map_id__upload_faro_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_faro_map__map_id__upload_faro_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/browse-directory":{"post":{"tags":["map"],"summary":"Browse Directory","description":"Browse a server-side directory; returns subdirs, files and image counts. (Admin / Configurator only.)\n\nArgs:\n    path: Absolute server-side directory path to browse.\n    file_extensions: Optional whitelist of extensions to list (e.g. [\".txt\", \".json\"]).\n                     When None, the file list is omitted and only image counts are returned.","operationId":"browse_directory_map_browse_directory_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_browse_directory_map_browse_directory_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/map/serve-file":{"post":{"tags":["map"],"summary":"Serve File","description":"Stream a server-side file by absolute path — used by the Configurator to load images already on disk.","operationId":"serve_file_map_serve_file_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_serve_file_map_serve_file_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/map/{map_id}/build-quote":{"post":{"tags":["map"],"summary":"Create Build Quote","description":"用 pipeline 已发布的物理单元清单生成不可变建图报价。","operationId":"create_build_quote_map__map_id__build_quote_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BuildQuoteRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/build":{"post":{"tags":["map"],"summary":"Trigger Map Building","description":"Start the map building process using uploaded images and priors","operationId":"trigger_build_map__map_id__build_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"input","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Input source: images, 360_video, polycam, kiri, navvis, matterport, faro, hexagon, leica, chcnav, xgrid, fjd, dual_fisheye(360 视频 build regime)","title":"Input"},"description":"Input source: images, 360_video, polycam, kiri, navvis, matterport, faro, hexagon, leica, chcnav, xgrid, fjd, dual_fisheye(360 视频 build regime)"}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BuildRequest"},{"type":"null"}],"title":"Build Request"}}}},"responses":{"200":{"description":"Build job started or queued","content":{"application/json":{"schema":{},"examples":{"started":{"summary":"Build started","value":{"message":"Build job started","job_id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","status":"RUNNING"}},"queued":{"summary":"Build queued (concurrent limit reached)","value":{"message":"Build job queued","job_id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","status":"PENDING","note":"Concurrent limit reached, task queued"}}}}}},"400":{"description":"Invalid request - missing files or already building","content":{"application/json":{"examples":{"no_images":{"summary":"No images uploaded","value":{"detail":"No images uploaded. Please upload images first."}},"no_priors":{"summary":"No priors file","value":{"detail":"No priors file uploaded. Please upload priors.json first."}},"already_building":{"summary":"Already building","value":{"detail":"A build job is already in progress for this map"}}}}}},"401":{"description":"Not authenticated","content":{"application/json":{"example":{"detail":"Not authenticated"}}}},"403":{"description":"Not authorized to access this map","content":{"application/json":{"example":{"detail":"Not authorized to access this map"}}}},"404":{"description":"Map not found","content":{"application/json":{"example":{"detail":"Map not found"}}}},"500":{"description":"Server error - map directory issue","content":{"application/json":{"example":{"detail":"Map directory timestamp not found. Please recreate the map."}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/status":{"get":{"tags":["map"],"summary":"Get Build Status","description":"Retrieve current status and progress of map building","operationId":"get_build_status_map__map_id__status_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"responses":{"200":{"description":"Status retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MapStatus"},"examples":{"building":{"summary":"Map is building","value":{"map_id":123,"status":"building","progress":45,"stage":"Feature Matching","created_at":"2025-01-20T14:35:00Z"}},"ready":{"summary":"Build completed","value":{"map_id":123,"status":"ready","progress":100,"stage":"Completed","created_at":"2025-01-20T14:35:00Z","finished_at":"2025-01-20T15:12:34Z"}},"failed":{"summary":"Build failed","value":{"map_id":123,"status":"failed","progress":67,"stage":"SfM Reconstruction","error_msg":"Insufficient feature matches","created_at":"2025-01-20T14:35:00Z","finished_at":"2025-01-20T15:03:21Z"}}}}}},"401":{"description":"Not authenticated","content":{"application/json":{"example":{"detail":"Not authenticated"}}}},"403":{"description":"Not authorized to access this map","content":{"application/json":{"example":{"detail":"Not authorized to access this map"}}}},"404":{"description":"Map not found","content":{"application/json":{"example":{"detail":"Map not found"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/logs":{"get":{"tags":["map"],"summary":"Get Build Logs","description":"Build console output for this map (last `tail` lines, default 500, max 5000).","operationId":"get_build_logs_map__map_id__logs_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"tail","in":"query","required":false,"schema":{"type":"integer","default":500,"title":"Tail"}}],"responses":{"200":{"description":"Logs retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BuildLogsResponse"},"example":{"map_id":123,"logs":"[2025-01-20 10:00:00] Step 1: Rendering pinhole views...\n...","log_file":"pipeline.log","last_modified":"2025-01-20T10:05:00Z"}}}},"404":{"description":"Map or log file not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/cancel-build":{"post":{"tags":["map"],"summary":"Cancel Build","description":"Cancel an ongoing or queued map building task","operationId":"cancel_build_map__map_id__cancel_build_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"responses":{"200":{"description":"Build cancelled successfully","content":{"application/json":{"schema":{},"example":{"message":"Build job cancelled"}}}},"400":{"description":"No active build to cancel","content":{"application/json":{"examples":{"no_job":{"value":{"detail":"No active build job to cancel"}},"already_changed":{"value":{"detail":"Cannot cancel: map status has changed to 'ready'"}}}}}},"401":{"description":"Not authenticated"},"403":{"description":"Not authorized to access this map"},"404":{"description":"Map not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/build-log":{"get":{"tags":["map"],"summary":"Get Build Log","description":"Retrieve the build log for debugging and monitoring","operationId":"get_build_log_map__map_id__build_log_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"lines","in":"query","required":false,"schema":{"type":"integer","default":100,"title":"Lines"}}],"responses":{"200":{"description":"Log retrieved successfully","content":{"application/json":{"schema":{},"examples":{"with_log":{"value":{"map_id":123,"log":"[2025-01-20 14:35:00] Starting build...\n[2025-01-20 14:35:05] Rendering panoramas...","total_lines":150}},"no_log":{"value":{"map_id":123,"log":"","message":"No build log available"}}}}}},"401":{"description":"Not authenticated"},"403":{"description":"Not authorized to access this map"},"404":{"description":"Map not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/cleanup-preview":{"get":{"tags":["map"],"summary":"Preview Cleanup","description":"Preview what files would be deleted and space freed by cleanup","operationId":"preview_cleanup_map__map_id__cleanup_preview_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"responses":{"200":{"description":"Cleanup preview generated","content":{"application/json":{"schema":{},"example":{"map_id":123,"current_size_mb":2048.5,"estimated_size_after_mb":512.3,"space_to_free_mb":1536.2,"files_to_delete":["render/","sfm_dryrun/","logs/"]}}}},"401":{"description":"Not authenticated"},"403":{"description":"Not authorized to access this map"},"404":{"description":"Map not found or directory not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/cleanup":{"post":{"tags":["map"],"summary":"Cleanup Map Files","description":"Delete intermediate build files to free disk space","operationId":"trigger_cleanup_map__map_id__cleanup_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"keep_logs","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Keep Logs"}}],"responses":{"200":{"description":"Cleanup completed","content":{"application/json":{"schema":{},"example":{"map_id":123,"freed_space_bytes":1610612736,"freed_space_mb":1536.0,"final_size_bytes":536870912,"final_size_mb":512.0,"deleted_paths":["render/","sfm_dryrun/","logs/"]}}}},"400":{"description":"Cannot cleanup while building","content":{"application/json":{"example":{"detail":"Cannot cleanup while map is building or queued"}}}},"401":{"description":"Not authenticated"},"403":{"description":"Not authorized to access this map"},"404":{"description":"Map or directory not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/ply":{"get":{"tags":["map"],"summary":"Download Point Cloud","description":"Download the 3D point cloud file (PLY format) for visualization","operationId":"get_map_ply_map__map_id__ply_get","parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"api_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Api Key"}},{"name":"source","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"}}],"responses":{"200":{"description":"PLY file download","content":{"application/json":{"schema":{}},"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Map not ready","content":{"application/json":{"example":{"detail":"Map is not ready. PLY file only available for completed maps."}}}},"401":{"description":"Not authenticated"},"403":{"description":"Not authorized to access this map"},"404":{"description":"Not found","content":{"application/json":{"examples":{"no_map":{"value":{"detail":"Map not found"}},"no_dir":{"value":{"detail":"Map directory not found"}},"no_ply":{"value":{"detail":"PLY file not found in map directory"}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/poses":{"get":{"tags":["map"],"summary":"Get Camera Poses","description":"Get the camera poses used during map building for visualization","operationId":"get_map_poses_map__map_id__poses_get","parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"api_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Api Key"}}],"responses":{"200":{"description":"Camera poses JSON","content":{"application/json":{"schema":{},"example":[{"id":"pano_camera0/frame_00001.jpg","image":"pano_camera0/frame_00001.jpg","camera_to_world":{"translation":{"x":1.23,"y":4.56,"z":7.89},"matrix_column_major":[1,0,0,0,0,1,0,0,0,0,1,0,1.23,4.56,7.89,1]}}]}}},"400":{"description":"Map not ready","content":{"application/json":{"example":{"detail":"Map is not ready. Poses only available for completed maps."}}}},"401":{"description":"Not authenticated"},"403":{"description":"Not authorized to access this map"},"404":{"description":"Not found","content":{"application/json":{"examples":{"no_map":{"value":{"detail":"Map not found"}},"no_dir":{"value":{"detail":"Map directory not found"}},"no_poses":{"value":{"detail":"Poses file not found (older map version)"}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/thumbnail/{image_path}":{"get":{"tags":["map"],"summary":"Get Image Thumbnail","description":"Get a thumbnail image for visualization in SpaceViewer","operationId":"get_map_thumbnail_map__map_id__thumbnail__image_path__get","parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"image_path","in":"path","required":true,"schema":{"type":"string","title":"Image Path"}},{"name":"api_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Api Key"}}],"responses":{"200":{"description":"Thumbnail image","content":{"application/json":{"schema":{}},"image/jpeg":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Map not ready","content":{"application/json":{"example":{"detail":"Map is not ready. Thumbnails only available for completed maps."}}}},"401":{"description":"Not authenticated"},"403":{"description":"Not authorized to access this map"},"404":{"description":"Not found","content":{"application/json":{"examples":{"no_map":{"value":{"detail":"Map not found"}},"no_thumbnail":{"value":{"detail":"Thumbnail not found"}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/transfer":{"post":{"tags":["map"],"summary":"Create Map Transfer Offer","description":"Create a 72-hour transfer offer. Ownership and billing do not change until the recipient accepts.","operationId":"transfer_map_map__map_id__transfer_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MapTransferRequest"}}}},"responses":{"200":{"description":"Transfer offer created","content":{"application/json":{"schema":{}}}},"400":{"description":"Cannot transfer: invalid state or self-transfer"},"401":{"description":"Not authenticated"},"403":{"description":"Not authorized to access this map"},"404":{"description":"Map or target user not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/transfer/{offer_id}/accept":{"post":{"tags":["map"],"summary":"Accept Map Transfer","description":"受让人确认后，在一个事务中切换 owner、Project 和 BillingAssignment。","operationId":"accept_map_transfer_map__map_id__transfer__offer_id__accept_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"offer_id","in":"path","required":true,"schema":{"type":"string","title":"Offer Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/transfer/{offer_id}/reject":{"post":{"tags":["map"],"summary":"Reject Map Transfer","description":"受让人拒绝邀请；所有权和计费区间保持不变。","operationId":"reject_map_transfer_map__map_id__transfer__offer_id__reject_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"offer_id","in":"path","required":true,"schema":{"type":"string","title":"Offer Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/move":{"post":{"tags":["map"],"summary":"Move Map to Project","description":"Move a map to another project owned by the same user.","operationId":"move_map_map__map_id__move_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MapMoveRequest"}}}},"responses":{"200":{"description":"Map moved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MapResponse"}}}},"400":{"description":"Cannot move: invalid state"},"401":{"description":"Not authenticated"},"403":{"description":"Not authorized to access this map or target project"},"404":{"description":"Map or target project not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/resolve":{"get":{"tags":["map"],"summary":"Resolve map_key to map_id","description":"Resolve an opaque map_key to its numeric map_id (so clients don't need to know the internal id).","operationId":"resolve_map_key_map_resolve_get","parameters":[{"name":"map_key","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":1024,"title":"Map Key"}},{"name":"api_key","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":128,"title":"Api Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/info":{"get":{"tags":["map"],"summary":"Get Map Info","description":"Full map detail (API-key authenticated). Used by viewers to load origin_pose, bbox, render_params, ...","operationId":"get_map_info_map__map_id__info_get","parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"api_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Api Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MapResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/render-params":{"get":{"tags":["map"],"summary":"Get Map Render Params","description":"Virtual-pinhole intrinsics used during build (width/height/fx/fy/cx/cy/camera_model). This data is also embedded in /info's render_params field — this endpoint is a shortcut for SDKs that don't need the full MapResponse.","operationId":"get_map_render_params_map__map_id__render_params_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"api_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Api Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RenderParams"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/mesh/info":{"get":{"tags":["map"],"summary":"Get Mesh Info","description":"Mesh metadata: face/vertex counts, generation parameters, available variants.","operationId":"get_mesh_info_map__map_id__mesh_info_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"api_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Api Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/mesh/chunks/index":{"get":{"tags":["map"],"summary":"Get Mesh Chunks Index","description":"Spatial chunk index — list of tiles with their AABB and file size.","operationId":"get_mesh_chunks_index_map__map_id__mesh_chunks_index_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"api_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Api Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/mesh/chunks/{resource_type}/{tile_id}":{"get":{"tags":["map"],"summary":"Download Mesh Chunk Tile","description":"Download a single spatial tile (occlusion GLB, surface-grid/wireframe BIN or pointcloud BIN).","operationId":"get_mesh_chunk_tile_map__map_id__mesh_chunks__resource_type___tile_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"resource_type","in":"path","required":true,"schema":{"type":"string","title":"Resource Type"}},{"name":"tile_id","in":"path","required":true,"schema":{"type":"string","title":"Tile Id"}},{"name":"asset_revision","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Asset Revision"}},{"name":"api_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Api Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/mesh/{mesh_type}":{"get":{"tags":["map"],"summary":"Download Mesh GLB","description":"Download a scene mesh (mesh_type = scene / scene_textured / occlusion / polycam_scene) as a GLB file.","operationId":"get_mesh_file_map__map_id__mesh__mesh_type__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"mesh_type","in":"path","required":true,"schema":{"type":"string","title":"Mesh Type"}},{"name":"api_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Api Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/upload-polycam-mesh":{"post":{"tags":["map"],"summary":"Upload Polycam Mesh","description":"Upload a Polycam/Kiri-exported GLTF/GLB mesh file (or a ZIP containing a single .glb).","operationId":"upload_polycam_mesh_map__map_id__upload_polycam_mesh_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_polycam_mesh_map__map_id__upload_polycam_mesh_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/admin/clone-map":{"post":{"tags":["map"],"summary":"Admin Clone Map","description":"Admin: shallow-clone a map into the admin's 'Received Maps' project (zero disk cost; new DB row points at canonical source data).","operationId":"admin_clone_map_map_admin_clone_map_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MapCloneRequest"}}},"required":true},"responses":{"200":{"description":"Cloned","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MapResponse"}}}},"400":{"description":"Source map state not eligible for cloning"},"401":{"description":"Not authenticated"},"403":{"description":"Admin only"},"404":{"description":"Source map not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/map/{map_id}/pano_tour/info":{"get":{"tags":["map"],"summary":"Get Pano Tour Info","description":"Panorama tour manifest (pano_tour.json).","operationId":"get_pano_tour_info_map__map_id__pano_tour_info_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"api_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Api Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/pano_tour/image/{image_path}":{"get":{"tags":["map"],"summary":"Get Pano Tour Image","description":"Download a single panorama-tour image (path comes from the manifest).","operationId":"get_pano_tour_image_map__map_id__pano_tour_image__image_path__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"image_path","in":"path","required":true,"schema":{"type":"string","title":"Image Path"}},{"name":"api_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Api Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/admin/repair-status":{"post":{"tags":["map"],"summary":"Admin Repair Map Status","description":"Admin: verify on-disk map data integrity and flip status back to ready (recovers from false-failed builds). Only allowed when sfm/cameras.bin + mesh/mesh_info.json + indices are all present. Use case: build_service falsely marks a build as failed when on-disk data is actually complete (e.g. shell hot-replace bugs).","operationId":"admin_repair_map_status_map__map_id__admin_repair_status_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"responses":{"200":{"description":"Status repaired","content":{"application/json":{"schema":{}}}},"400":{"description":"On-disk data incomplete; cannot repair"},"403":{"description":"Admin only"},"404":{"description":"Map not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/mesh/regenerate":{"post":{"tags":["maps"],"summary":"Regenerate Mesh Assets","description":"重新生成 LiDAR mesh 展示资产，不重建定位索引。","operationId":"regenerate_mesh_assets_map__map_id__mesh_regenerate_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/mesh/regenerate-360":{"post":{"tags":["maps"],"summary":"Regenerate 360 Mesh Assets","description":"对已有 360(dual_fisheye) 地图【只重生成带纹理 mesh】,复用其 SfM + Path-B 针孔渲染图。\n\n不重跑 SfM、不重建定位索引、不改坐标系 —— 纯新增 mesh 展示 + 遮挡资产。\n走 build_service 的隔离 mesh 子进程(看门狗 + _active_mesh,cancel/shutdown 可杀),\n满足\"建图必须走 build_service\"铁律。GPU 在此获取(标 building),跑完由后台线程释放。","operationId":"regenerate_360_mesh_assets_map__map_id__mesh_regenerate_360_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/mesh/regenerate/cancel":{"post":{"tags":["maps"],"summary":"Cancel Mesh Regeneration","description":"取消正在运行的 mesh-only 重生成任务(360 或 LiDAR),覆盖 /mesh/regenerate 与 /mesh/regenerate-360。\n\n与 /cancel-build 的本质区别:mesh regen 全程让 map.status 保持 ready(mesh 是纯附加资产,地图本身\n可用于定位)。因此【不能】走 /cancel-build —— 它用 `map.status IN (building,pending)` 把门,ready 会被\nrowcount==0 直接 400 拒(根本调不到 cancel_build);且它的清理块会 rmtree sfm/features/retrieval/track3d\n摧毁既有定位资产。本端点只杀 mesh 子进程组 + reap CUDA,绝不触碰 map.status / 定位资产;job 终态由\n后台 regen 线程作为【唯一状态写者】观测 task.cancelled 后落 CANCELLED(与主建图 mesh 段同一约定,\n避免双写者把 SUCCESS 覆盖成 CANCELLED 或反之的竞态)。","operationId":"cancel_mesh_regeneration_map__map_id__mesh_regenerate_cancel_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/geometry/status":{"get":{"tags":["geometry"],"summary":"Get published geometry status","description":"返回 latest candidate、三个独立 active product 与最新构建尝试。","operationId":"get_geometry_status_map__map_id__geometry_status_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"api_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Api Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeometryStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/geometry/request":{"get":{"tags":["geometry"],"summary":"Get desired geometry certification request","operationId":"get_geometry_request_map__map_id__geometry_request_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"api_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Api Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeometryRequestState"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["geometry"],"summary":"Save desired geometry certification request with CAS","operationId":"put_geometry_request_map__map_id__geometry_request_put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"api_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Api Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeometryRequestUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeometryRequestState"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/geometry/request/bootstrap":{"put":{"tags":["geometry"],"summary":"Save the first geometry proposal for a historical RGB360 map","description":"在 foundation apply 前保存首份显式执行 ROI，不赋予 completeness authority。","operationId":"bootstrap_geometry_request_map__map_id__geometry_request_bootstrap_put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"api_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Api Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeometryRequestBootstrapUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeometryRequestBootstrapState"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/geometry/certify":{"post":{"tags":["geometry"],"summary":"Sign an exact owner-submitted geometry proposal","description":"独立 certifier 只能签名精确 proposal 的显式 assertion，不能隐式扩大权限。","operationId":"certify_geometry_request_map__map_id__geometry_certify_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"api_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Api Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeometryCertificationIssue"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeometryRequestState"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/geometry/regenerate":{"post":{"tags":["geometry"],"summary":"Regenerate geometry evidence products","description":"对 ready 地图启动独立 geometry regen；旧 revision 在新版本发布前继续服务。","operationId":"regenerate_geometry_map__map_id__geometry_regenerate_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"foundation_plan_revision","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Foundation Plan Revision"}},{"name":"api_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Api Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/geometry/cancel":{"post":{"tags":["geometry"],"summary":"Cancel active geometry generation","description":"只取消 geometry 子进程，不改变 ready Map 或删除定位资产。","operationId":"cancel_geometry_map__map_id__geometry_cancel_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"api_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Api Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/geometry/{revision}/asset/{asset_path}":{"get":{"tags":["geometry"],"summary":"Download an immutable geometry revision asset","description":"下载已由精确 SUCCESS Job 提交的 revision 显式声明 asset。\n\n``latest.json`` 只决定 Space Studio candidate；产品 active 由独立 pointer 决定。历史 revision 在 GC 前仍可\n通过不可变 URL 下载。发送前会重新校验 manifest revision、路径边界、文件大小与 SHA-256。","operationId":"get_geometry_revision_asset_map__map_id__geometry__revision__asset__asset_path__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"revision","in":"path","required":true,"schema":{"type":"string","title":"Revision"}},{"name":"asset_path","in":"path","required":true,"schema":{"type":"string","title":"Asset Path"}},{"name":"api_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Api Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/billing/pricing":{"get":{"tags":["billing"],"summary":"Pricing","operationId":"pricing_billing_pricing_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/billing/summary":{"get":{"tags":["billing"],"summary":"Summary","operationId":"summary_billing_summary_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingSummaryResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/billing/notifications":{"get":{"tags":["billing"],"summary":"Notifications","operationId":"notifications_billing_notifications_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/billing/notifications/{notification_id}/read":{"post":{"tags":["billing"],"summary":"Read Notification","operationId":"read_notification_billing_notifications__notification_id__read_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"notification_id","in":"path","required":true,"schema":{"type":"string","title":"Notification Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/billing/maps/{map_id}/recovery-hold/restore":{"post":{"tags":["billing"],"summary":"Restore From Recovery Hold","operationId":"restore_from_recovery_hold_billing_maps__map_id__recovery_hold_restore_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecoveryRestoreRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/billing/archive/capability":{"get":{"tags":["billing"],"summary":"Archive Capability","operationId":"archive_capability_billing_archive_capability_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/billing/maps/{map_id}/storage":{"get":{"tags":["billing"],"summary":"Map Storage Status","operationId":"map_storage_status_billing_maps__map_id__storage_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/billing/maps/{map_id}/storage/quote":{"post":{"tags":["billing"],"summary":"Storage Quote","operationId":"storage_quote_billing_maps__map_id__storage_quote_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StorageQuoteRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StorageQuoteResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/billing/maps/{map_id}/recovery-hold/archive/quote":{"post":{"tags":["billing"],"summary":"Recovery Hold Archive Quote","description":"确认把已具备冗余的 Recovery Hold 转为正常付费 Archive。","operationId":"recovery_hold_archive_quote_billing_maps__map_id__recovery_hold_archive_quote_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecoveryRestoreRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StorageQuoteResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/billing/storage-quotes/{quote_id}/recovery-hold/archive/accept":{"post":{"tags":["billing"],"summary":"Accept Recovery Hold Archive","operationId":"accept_recovery_hold_archive_billing_storage_quotes__quote_id__recovery_hold_archive_accept_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"quote_id","in":"path","required":true,"schema":{"type":"string","title":"Quote Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecoveryRestoreRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecoveryHoldArchiveResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/billing/storage-quotes/{quote_id}/accept":{"post":{"tags":["billing"],"summary":"Accept Storage Operation","operationId":"accept_storage_operation_billing_storage_quotes__quote_id__accept_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"quote_id","in":"path","required":true,"schema":{"type":"string","title":"Quote Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StorageOperationAcceptRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StorageOperationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/billing/storage-operations/{operation_id}":{"get":{"tags":["billing"],"summary":"Storage Operation","operationId":"storage_operation_billing_storage_operations__operation_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"operation_id","in":"path","required":true,"schema":{"type":"string","title":"Operation Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StorageOperationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/billing/storage-operations/{operation_id}/cancel":{"post":{"tags":["billing"],"summary":"Cancel Storage Operation Route","operationId":"cancel_storage_operation_route_billing_storage_operations__operation_id__cancel_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"operation_id","in":"path","required":true,"schema":{"type":"string","title":"Operation Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StorageOperationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/billing/maps/{map_id}/archive-copy/release":{"post":{"tags":["billing"],"summary":"Release Archive Copy","operationId":"release_archive_copy_billing_maps__map_id__archive_copy_release_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecoveryRestoreRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/billing/daily":{"get":{"tags":["billing"],"summary":"Daily Usage","operationId":"daily_usage_billing_daily_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":90,"minimum":1,"default":30,"title":"Days"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/billing/maps":{"get":{"tags":["billing"],"summary":"Map Costs","operationId":"map_costs_billing_maps_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/billing/forecast":{"get":{"tags":["billing"],"summary":"Forecast","operationId":"forecast_billing_forecast_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/billing/transactions":{"get":{"tags":["billing"],"summary":"Transactions","operationId":"transactions_billing_transactions_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cursor"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingTransactionPage"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/billing/payment-options":{"get":{"tags":["billing"],"summary":"Payment Options","operationId":"payment_options_billing_payment_options_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/billing/transfer-offers":{"get":{"tags":["billing"],"summary":"Incoming Transfer Offers","operationId":"incoming_transfer_offers_billing_transfer_offers_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/billing/checkout-sessions":{"post":{"tags":["billing"],"summary":"Create Checkout Session","operationId":"create_checkout_session_billing_checkout_sessions_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutSessionRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutSessionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/billing/payments":{"get":{"tags":["billing"],"summary":"Payments","operationId":"payments_billing_payments_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cursor"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentPage"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/billing/payments/{payment_id}":{"get":{"tags":["billing"],"summary":"Payment Status","operationId":"payment_status_billing_payments__payment_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"payment_id","in":"path","required":true,"schema":{"type":"string","title":"Payment Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/billing/accounts":{"get":{"tags":["billing-admin"],"summary":"List Accounts","operationId":"list_accounts_admin_billing_accounts_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"query","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Query"}},{"name":"cursor","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Cursor"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/billing/accounts/{public_id}/payments":{"get":{"tags":["billing-admin"],"summary":"List Account Payments","operationId":"list_account_payments_admin_billing_accounts__public_id__payments_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"public_id","in":"path","required":true,"schema":{"type":"string","title":"Public Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/billing/accounts/{public_id}/refunds":{"get":{"tags":["billing-admin"],"summary":"List Account Refunds","operationId":"list_account_refunds_admin_billing_accounts__public_id__refunds_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"public_id","in":"path","required":true,"schema":{"type":"string","title":"Public Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/billing/payments/{payment_public_id}/refunds":{"post":{"tags":["billing-admin"],"summary":"Refund Payment","operationId":"refund_payment_admin_billing_payments__payment_public_id__refunds_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"payment_public_id","in":"path","required":true,"schema":{"type":"string","title":"Payment Public Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminPaymentRefundRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentRefundResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/billing/accounts/{public_id}/adjustments":{"post":{"tags":["billing-admin"],"summary":"Adjust Account","operationId":"adjust_account_admin_billing_accounts__public_id__adjustments_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"public_id","in":"path","required":true,"schema":{"type":"string","title":"Public Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAdjustmentRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/billing/transactions/{transaction_id}/reverse":{"post":{"tags":["billing-admin"],"summary":"Reverse Transaction","operationId":"reverse_transaction_admin_billing_transactions__transaction_id__reverse_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"transaction_id","in":"path","required":true,"schema":{"type":"string","title":"Transaction Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminReversalRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/billing/accounts/{public_id}/plan":{"post":{"tags":["billing-admin"],"summary":"Change Plan","operationId":"change_plan_admin_billing_accounts__public_id__plan_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"public_id","in":"path","required":true,"schema":{"type":"string","title":"Public Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminPlanRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/billing/accounts/{public_id}/status":{"post":{"tags":["billing-admin"],"summary":"Change Status","operationId":"change_status_admin_billing_accounts__public_id__status_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"public_id","in":"path","required":true,"schema":{"type":"string","title":"Public Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminStatusRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/billing/reconciliation":{"get":{"tags":["billing-admin"],"summary":"Reconciliation","operationId":"reconciliation_admin_billing_reconciliation_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/admin/billing/capacity":{"get":{"tags":["billing-admin"],"summary":"Capacity","description":"与建图 admission guard 完全相同的区域容量口径。","operationId":"capacity_admin_billing_capacity_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/healthz/billing":{"get":{"tags":["billing"],"summary":"Billing Health","description":"不泄露数据库 URL/密钥的 Billing 基础健康状态。","operationId":"billing_health_healthz_billing_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/legal/acceptances":{"get":{"tags":["legal-admin"],"summary":"List Legal Acceptances","operationId":"list_legal_acceptances_admin_legal_acceptances_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"account_user_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"title":"Account User Id"}},{"name":"cursor","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Cursor"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/legal/holds":{"get":{"tags":["legal-admin"],"summary":"List Legal Holds","operationId":"list_legal_holds_admin_legal_holds_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"active_only","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Active Only"}},{"name":"review_due_only","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Review Due Only"}},{"name":"cursor","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Cursor"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["legal-admin"],"summary":"Create Hold","operationId":"create_hold_admin_legal_holds_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegalHoldCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/legal/holds/{hold_id}/release":{"post":{"tags":["legal-admin"],"summary":"Release Hold","operationId":"release_hold_admin_legal_holds__hold_id__release_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"hold_id","in":"path","required":true,"schema":{"type":"integer","title":"Hold Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegalHoldRelease"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/content/upload":{"post":{"tags":["content"],"summary":"Upload Content","description":"Upload a 3D model file (GLB / GLTF / KTX2 / texture images) attached to a map.\n\nSingle GLB file upload via multipart/form-data.\nPose parameters are passed as JSON array strings.","operationId":"upload_content_map__map_id__content_upload_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_content_map__map_id__content_upload_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentUploadResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/content":{"get":{"tags":["content"],"summary":"List Content","description":"列出地图下所有 3D 内容资产和已保存场景；支持 JWT 或 API Key。","operationId":"list_content_map__map_id__content_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"api_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Api Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/content/scene":{"put":{"tags":["content"],"summary":"Update Scene","description":"保存场景对象列表，覆盖 manifest 的 scene 字段。","operationId":"update_scene_map__map_id__content_scene_put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SceneUpdateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/content/{content_id}/file":{"get":{"tags":["content"],"summary":"Download Content File","description":"Download a content asset's main file.\n\nReturns the GLB/GLTF; supports HTTP caching headers and Range requests.","operationId":"download_content_file_map__map_id__content__content_id__file_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"content_id","in":"path","required":true,"schema":{"type":"string","title":"Content Id"}},{"name":"api_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Api Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/content/{content_id}/file/{sub_path}":{"get":{"tags":["content"],"summary":"Download Content Sub File","description":"Download a GLTF-associated file (.bin, textures, etc.).","operationId":"download_content_sub_file_map__map_id__content__content_id__file__sub_path__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"content_id","in":"path","required":true,"schema":{"type":"string","title":"Content Id"}},{"name":"sub_path","in":"path","required":true,"schema":{"type":"string","title":"Sub Path"}},{"name":"api_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Api Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/content/{content_id}":{"put":{"tags":["content"],"summary":"Update Content","description":"更新内容资产的名称、位姿、缩放或行为配置。","operationId":"update_content_map__map_id__content__content_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"content_id","in":"path","required":true,"schema":{"type":"string","title":"Content Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentUpdateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["content"],"summary":"Delete Content","description":"Delete a content item and its underlying files.","operationId":"delete_content_map__map_id__content__content_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"content_id","in":"path","required":true,"schema":{"type":"string","title":"Content Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/localize/config":{"get":{"tags":["localization"],"summary":"Get Localization Client Config","description":"Resolve map_key/project_key and return the render policy clients should use for pixel-density matching before sending the first localization frame.","operationId":"get_localize_config_localize_config_get","parameters":[{"name":"map_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Map Key"}},{"name":"project_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Key"}},{"name":"api_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Api Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Localize Config Localize Config Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/localize":{"post":{"tags":["localization"],"summary":"Visual Localization","description":"Localize a query image using visual features to determine 6-DoF camera pose.\n\n## Authentication Modes\n\n**Mode 1: Production (Recommended)**\n- Use `map_key` + `api_key`\n- `map_key`: Encrypted map identifier (obtained after map build completes)\n- `api_key`: User API key (from user profile page)\n\n**Mode 2: Development**\n- Use `map_dir` directly\n- `map_dir`: Absolute path to map directory on server\n- For local testing only, no authentication required\n\n## Request Formats\n\n1. **Multipart/Form-Data**: Traditional file upload with form fields\n2. **Binary Protocol**: JSON header + `\\0` + raw image bytes (high performance)","operationId":"localize_localize_post","responses":{"200":{"description":"Localization successful","content":{"application/json":{"schema":{},"example":{"status":"success","pose":{"qvec":[0.707,0,0,0.707],"tvec":[1.23,4.56,7.89]},"num_inliers":234,"stage":"instant","latency_ms":287.5}}}},"400":{"description":"Invalid parameters or malformed request","content":{"application/json":{"examples":{"missing_params":{"summary":"Missing required parameter","value":{"detail":"Missing required parameter: fx"}},"invalid_map_key":{"summary":"Invalid map key","value":{"detail":{"error":"invalid map key"}}},"missing_map_target":{"summary":"Missing map target","value":{"detail":{"error":"missing map target"}}},"conflicting_map_target":{"summary":"Conflicting map target","value":{"detail":{"error":"conflicting map target"}}}}}}},"401":{"description":"Authentication failed - invalid or missing API key","content":{"application/json":{"examples":{"missing_api_key":{"summary":"API key required when using map key","value":{"detail":{"error":"api key required when using map key"}}},"invalid_api_key":{"summary":"Invalid API key","value":{"detail":{"error":"invalid api key"}}}}}}},"403":{"description":"Permission denied - not authorized to localize this map","content":{"application/json":{"example":{"detail":{"error":"not authorized to localize this map"}}}}},"500":{"description":"Internal server error","content":{"application/json":{"example":{"detail":"Localization service not initialized"}}}}},"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["fx","fy","cx","cy","image_path"],"properties":{"map_key":{"type":"string","title":"Map Key","description":"Encrypted map identifier (Production mode). Required with api_key."},"api_key":{"type":"string","title":"API Key","description":"User API key (Production mode). Required when using map_key."},"map_dir":{"type":"string","title":"Map Directory","description":"Absolute path to map directory (Development mode only)."},"fx":{"type":"number","title":"Focal Length X","description":"Focal length X in pixels (required)"},"fy":{"type":"number","title":"Focal Length Y","description":"Focal length Y in pixels (required)"},"cx":{"type":"number","title":"Principal Point X","description":"Principal point X (image center). Alias: ox"},"cy":{"type":"number","title":"Principal Point Y","description":"Principal point Y (image center). Alias: oy"},"image_path":{"type":"string","format":"binary","title":"Query Image","description":"Query image file (required)"},"camera_model":{"type":"string","title":"Camera Model","default":"PINHOLE","description":"Camera model type (default: PINHOLE)"},"min_inliers":{"type":"integer","title":"Min Inliers","default":150,"description":"Override min inliers (debug only; auto-set by map type)"},"try_rotations":{"type":"boolean","title":"Try Rotations","default":false,"description":"Try 0°/90°/-90°/180° rotations if initial fails"},"try_stages":{"type":"boolean","title":"Try Stages","default":false,"description":"Multi-stage: instant → standard → dense"},"try_exhaustive":{"type":"boolean","title":"Try Exhaustive","default":false,"description":"Exhaustive: instant → standard → dense → cascade (implies try_stages)"}}}}}}}},"/localize_rig":{"post":{"tags":["localization"],"summary":"Multi-frame rig localization","description":"rig.v2: send 2-6 versioned image/K/tracking-epoch frames. Each frame uses the latency-bounded instant stage; one reliable view can return coverage success, consistent views are cross-validated and bounded-refined, and strong conflicts fail closed. Length-prefixed binary protocol.","operationId":"localize_rig_endpoint_localize_rig_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/localize_rig/ack":{"post":{"tags":["localization"],"summary":"Report whether a rig result was applied by the client","description":"记录“服务端成功”之后客户端是否真正应用了位姿。\n\nACK 只进入结构化日志，不改变地图或计费状态；因此它是 best-effort，客户端\n上报失败不会影响定位。所有自由文本均截断，避免现场诊断字段污染日志。","operationId":"localize_rig_client_ack_localize_rig_ack_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/map/{map_id}/saas/toggle":{"post":{"tags":["saas"],"summary":"Toggle Space Analytics","operationId":"toggle_saas_map__map_id__saas_toggle_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaasToggleRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/saas/status":{"get":{"tags":["saas"],"summary":"Space Analytics status","operationId":"saas_status_map__map_id__saas_status_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/saas/sessions":{"get":{"tags":["saas"],"summary":"Flat session list across all devices","description":"Return every session across devices, sorted by time descending.\n\nPrefers grouping by `session_id` (precise AR-session boundary from the client).\nFalls back to gap-based splitting for legacy records without session_id.","operationId":"list_all_sessions_map__map_id__saas_sessions_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"session_gap_minutes","in":"query","required":false,"schema":{"type":"integer","title":"Session Gap Minutes"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/saas/devices":{"get":{"tags":["saas"],"summary":"Device list (aggregated stats)","operationId":"list_devices_map__map_id__saas_devices_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/saas/devices/{device_id}/sessions":{"get":{"tags":["saas"],"summary":"Session list (computed on the fly)","operationId":"list_sessions_map__map_id__saas_devices__device_id__sessions_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"device_id","in":"path","required":true,"schema":{"type":"string","title":"Device Id"}},{"name":"session_gap_minutes","in":"query","required":false,"schema":{"type":"integer","title":"Session Gap Minutes"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/map/{map_id}/saas/devices/{device_id}/records":{"get":{"tags":["saas"],"summary":"Session detail (includes per-pose data for playback)","operationId":"list_records_map__map_id__saas_devices__device_id__records_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"map_id","in":"path","required":true,"schema":{"type":"integer","title":"Map Id"}},{"name":"device_id","in":"path","required":true,"schema":{"type":"string","title":"Device Id"}},{"name":"start","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"ISO-8601 start datetime (inclusive)","title":"Start"},"description":"ISO-8601 start datetime (inclusive)"},{"name":"end","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"ISO-8601 end datetime (inclusive)","title":"End"},"description":"ISO-8601 end datetime (inclusive)"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":5000,"default":1000,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/cloud/{provider}/authorize":{"get":{"tags":["cloud-auth"],"summary":"Cloud Authorize","description":"Generate an OAuth authorize URL. The frontend opens it with window.open(url) so the user can sign in with the cloud provider.","operationId":"cloud_authorize_cloud__provider__authorize_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"provider","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z][a-z0-9_-]{1,31}$","title":"Provider"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/cloud/{provider}/callback":{"get":{"tags":["cloud-auth"],"summary":"Cloud Callback","description":"OAuth redirect target. Provider returns with code+state → exchange for token → persist → close popup.\n\nThis endpoint does NOT accept a Bearer header — identity is proven by the HMAC-signed state\n(the standard OAuth security model).","operationId":"cloud_callback_cloud__provider__callback_get","parameters":[{"name":"provider","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z][a-z0-9_-]{1,31}$","title":"Provider"}},{"name":"code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code"}},{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"}},{"name":"error","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},{"name":"error_description","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Description"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/cloud/{provider}/status":{"get":{"tags":["cloud-auth"],"summary":"Cloud Status","description":"Whether the current user has this cloud provider connected. Used by the frontend to decide if the 'Connect' button should be shown. Unknown providers return {connected: false}.","operationId":"cloud_status_cloud__provider__status_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"provider","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z][a-z0-9_-]{1,31}$","title":"Provider"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/cloud/{provider}/disconnect":{"post":{"tags":["cloud-auth"],"summary":"Cloud Disconnect","description":"Delete the user's binding with this cloud provider. Idempotent.","operationId":"cloud_disconnect_cloud__provider__disconnect_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"provider","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z][a-z0-9_-]{1,31}$","title":"Provider"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"AccountClosureRequest":{"properties":{"confirmation":{"type":"string","const":"DELETE","title":"Confirmation"},"current_password":{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"Current Password"}},"type":"object","required":["confirmation"],"title":"AccountClosureRequest","description":"不可逆关闭账号的显式确认。"},"ActiveJobInfo":{"properties":{"kind":{"type":"string","title":"Kind"},"status":{"type":"string","title":"Status"},"progress":{"type":"integer","title":"Progress"},"stage":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stage"}},"type":"object","required":["kind","status","progress"],"title":"ActiveJobInfo","description":"地图上正在运行的后台任务(合规:任何建图/mesh 进度必须在界面可见)。\n\n当前只承载 legacy_mesh_regen(MAP_BUILD 由 map.status 表达、geometry 走 /geometry/status\n独立通道,避免双重呈现)。"},"AdminAdjustmentRequest":{"properties":{"operation_id":{"type":"string","format":"uuid","title":"Operation Id"},"amount_milli_credit":{"type":"integer","maximum":9.223372036854776e+18,"minimum":-9.223372036854776e+18,"title":"Amount Milli Credit"},"reason":{"type":"string","maxLength":1000,"minLength":3,"title":"Reason"},"external_reference":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"External Reference"},"allow_negative_balance":{"type":"boolean","title":"Allow Negative Balance","default":false}},"type":"object","required":["operation_id","amount_milli_credit","reason"],"title":"AdminAdjustmentRequest"},"AdminPaymentRefundRequest":{"properties":{"operation_id":{"type":"string","format":"uuid","title":"Operation Id"},"amount_minor":{"type":"integer","maximum":9.223372036854776e+18,"minimum":1.0,"title":"Amount Minor"},"reason":{"type":"string","maxLength":1000,"minLength":3,"title":"Reason"}},"type":"object","required":["operation_id","amount_minor","reason"],"title":"AdminPaymentRefundRequest"},"AdminPlanRequest":{"properties":{"plan":{"$ref":"#/components/schemas/BillingPlan"},"payment_mode":{"$ref":"#/components/schemas/PaymentMode"},"credit_limit_milli_credit":{"type":"integer","maximum":9.223372036854776e+18,"minimum":0.0,"title":"Credit Limit Milli Credit"},"reason":{"type":"string","maxLength":1000,"minLength":3,"title":"Reason"}},"type":"object","required":["plan","payment_mode","credit_limit_milli_credit","reason"],"title":"AdminPlanRequest"},"AdminReversalRequest":{"properties":{"operation_id":{"type":"string","format":"uuid","title":"Operation Id"},"reason":{"type":"string","maxLength":1000,"minLength":3,"title":"Reason"}},"type":"object","required":["operation_id","reason"],"title":"AdminReversalRequest"},"AdminStatusRequest":{"properties":{"billing_status":{"$ref":"#/components/schemas/BillingStatus"},"reason":{"type":"string","maxLength":1000,"minLength":3,"title":"Reason"}},"type":"object","required":["billing_status","reason"],"title":"AdminStatusRequest"},"ArchiveOperationType":{"type":"string","enum":["archive_source","archive_full","restore_source","restore_full","recovery_hold"],"title":"ArchiveOperationType"},"BillingPlan":{"type":"string","enum":["free","payg","enterprise"],"title":"BillingPlan"},"BillingStatus":{"type":"string","enum":["active","past_due","suspended","closed"],"title":"BillingStatus"},"BillingSummaryResponse":{"properties":{"account_id":{"type":"string","title":"Account Id"},"region":{"type":"string","title":"Region"},"plan":{"$ref":"#/components/schemas/BillingPlan"},"billing_status":{"$ref":"#/components/schemas/BillingStatus"},"payment_mode":{"$ref":"#/components/schemas/PaymentMode"},"balance_milli_credit":{"type":"integer","title":"Balance Milli Credit"},"credit_limit_milli_credit":{"type":"integer","title":"Credit Limit Milli Credit"},"welcome_credit_granted_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Welcome Credit Granted At"},"email_verified_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Email Verified At"},"free_successful_maps_lifetime":{"type":"integer","title":"Free Successful Maps Lifetime","default":0},"free_successful_mu_milli_lifetime":{"type":"integer","title":"Free Successful Mu Milli Lifetime","default":0},"currently_owned_maps":{"type":"integer","title":"Currently Owned Maps","default":0},"mapping_meter_mode":{"type":"string","title":"Mapping Meter Mode","default":"disabled"},"localization_meter_mode":{"type":"string","title":"Localization Meter Mode","default":"disabled"},"hot_hosting_meter_mode":{"type":"string","title":"Hot Hosting Meter Mode","default":"disabled"},"restore_meter_mode":{"type":"string","title":"Restore Meter Mode","default":"disabled"},"past_due_since":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Past Due Since"},"suspended_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Suspended At"}},"type":"object","required":["account_id","region","plan","billing_status","payment_mode","balance_milli_credit","credit_limit_milli_credit","welcome_credit_granted_at","email_verified_at"],"title":"BillingSummaryResponse"},"BillingTransactionPage":{"properties":{"items":{"items":{"$ref":"#/components/schemas/BillingTransactionResponse"},"type":"array","title":"Items"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"}},"type":"object","required":["items","next_cursor"],"title":"BillingTransactionPage"},"BillingTransactionResponse":{"properties":{"id":{"type":"string","title":"Id"},"amount_milli_credit":{"type":"integer","title":"Amount Milli Credit"},"balance_after_milli_credit":{"type":"integer","title":"Balance After Milli Credit"},"account_sequence":{"type":"integer","title":"Account Sequence"},"kind":{"type":"string","title":"Kind"},"reversal_of_transaction_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reversal Of Transaction Id"},"pricing_version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pricing Version"},"metadata_json":{"type":"string","title":"Metadata Json"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","amount_milli_credit","balance_after_milli_credit","account_sequence","kind","reversal_of_transaction_id","pricing_version","metadata_json","created_at"],"title":"BillingTransactionResponse"},"Body_browse_directory_map_browse_directory_post":{"properties":{"path":{"type":"string","title":"Path","default":"/"},"file_extensions":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"File Extensions"}},"type":"object","title":"Body_browse_directory_map_browse_directory_post"},"Body_check_password_strength_endpoint_auth_check_password_strength_post":{"properties":{"password":{"type":"string","maxLength":1024,"minLength":1,"title":"Password"}},"type":"object","required":["password"],"title":"Body_check_password_strength_endpoint_auth_check_password_strength_post"},"Body_oauth_callback_post_auth_callback__provider__post":{"properties":{"code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"id_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id Token"},"user":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"error_description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Description"}},"type":"object","title":"Body_oauth_callback_post_auth_callback__provider__post"},"Body_serve_file_map_serve_file_post":{"properties":{"path":{"type":"string","title":"Path"}},"type":"object","required":["path"],"title":"Body_serve_file_map_serve_file_post"},"Body_set_navvis_path_map__map_id__set_navvis_path_post":{"properties":{"e57_path":{"type":"string","title":"E57 Path"},"with_pointcloud":{"type":"boolean","title":"With Pointcloud","default":false}},"type":"object","required":["e57_path"],"title":"Body_set_navvis_path_map__map_id__set_navvis_path_post"},"Body_set_polycam_path_map__map_id__set_polycam_path_post":{"properties":{"zip_path":{"type":"string","title":"Zip Path"}},"type":"object","required":["zip_path"],"title":"Body_set_polycam_path_map__map_id__set_polycam_path_post"},"Body_upload_360_zip_map__map_id__upload_360_post":{"properties":{"video_file":{"type":"string","format":"binary","title":"Video File"},"charuco_board":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Charuco Board"},"target_fps":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Target Fps"},"adaptive_sampling":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Adaptive Sampling"},"video_mode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Video Mode"}},"type":"object","required":["video_file"],"title":"Body_upload_360_zip_map__map_id__upload_360_post"},"Body_upload_avatar_auth_avatar_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","required":["file"],"title":"Body_upload_avatar_auth_avatar_post"},"Body_upload_chcnav_map__map_id__upload_chcnav_post":{"properties":{"poses_file":{"type":"string","format":"binary","title":"Poses File"},"pano_files":{"items":{"type":"string","format":"binary"},"type":"array","title":"Pano Files"},"las_file":{"anyOf":[{"type":"string","format":"binary"},{"type":"null"}],"title":"Las File"}},"type":"object","required":["poses_file","pano_files"],"title":"Body_upload_chcnav_map__map_id__upload_chcnav_post"},"Body_upload_chcnav_poses_map__map_id__upload_chcnav_poses_post":{"properties":{"pano_dir":{"type":"string","title":"Pano Dir"},"poses_path":{"type":"string","title":"Poses Path"}},"type":"object","required":["pano_dir","poses_path"],"title":"Body_upload_chcnav_poses_map__map_id__upload_chcnav_poses_post"},"Body_upload_content_map__map_id__content_upload_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"},"position":{"type":"string","title":"Position","default":"[0,0,0]"},"quaternion_xyzw":{"type":"string","title":"Quaternion Xyzw","default":"[0,0,0,1]"},"scale":{"type":"string","title":"Scale","default":"[1,1,1]"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"client_upload_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Upload Id"}},"type":"object","required":["file"],"title":"Body_upload_content_map__map_id__content_upload_post"},"Body_upload_e57_map__map_id__upload_e57_post":{"properties":{"zip_file":{"type":"string","format":"binary","title":"Zip File"}},"type":"object","required":["zip_file"],"title":"Body_upload_e57_map__map_id__upload_e57_post"},"Body_upload_erp_images_zip_map__map_id__upload_erp_images_post":{"properties":{"images_file":{"type":"string","format":"binary","title":"Images File"},"charuco_board":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Charuco Board"}},"type":"object","required":["images_file"],"title":"Body_upload_erp_images_zip_map__map_id__upload_erp_images_post"},"Body_upload_faro_map__map_id__upload_faro_post":{"properties":{"zip_file":{"type":"string","format":"binary","title":"Zip File"}},"type":"object","required":["zip_file"],"title":"Body_upload_faro_map__map_id__upload_faro_post"},"Body_upload_fjd_map__map_id__upload_fjd_post":{"properties":{"zip_file":{"type":"string","format":"binary","title":"Zip File"}},"type":"object","required":["zip_file"],"title":"Body_upload_fjd_map__map_id__upload_fjd_post"},"Body_upload_hexagon_map__map_id__upload_hexagon_post":{"properties":{"zip_file":{"type":"string","format":"binary","title":"Zip File"}},"type":"object","required":["zip_file"],"title":"Body_upload_hexagon_map__map_id__upload_hexagon_post"},"Body_upload_kiri_map__map_id__upload_kiri_post":{"properties":{"zip_file":{"type":"string","format":"binary","title":"Zip File"}},"type":"object","required":["zip_file"],"title":"Body_upload_kiri_map__map_id__upload_kiri_post"},"Body_upload_leica_map__map_id__upload_leica_post":{"properties":{"zip_file":{"type":"string","format":"binary","title":"Zip File"}},"type":"object","required":["zip_file"],"title":"Body_upload_leica_map__map_id__upload_leica_post"},"Body_upload_matterport_map__map_id__upload_matterport_post":{"properties":{"zip_file":{"type":"string","format":"binary","title":"Zip File"}},"type":"object","required":["zip_file"],"title":"Body_upload_matterport_map__map_id__upload_matterport_post"},"Body_upload_osv_map__map_id__upload_osv_post":{"properties":{"osv_file":{"type":"string","format":"binary","title":"Osv File"},"charuco_board":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Charuco Board"},"target_fps":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Target Fps"},"adaptive_sampling":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Adaptive Sampling"},"segmentation":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Segmentation"},"resize_max":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Resize Max"}},"type":"object","required":["osv_file"],"title":"Body_upload_osv_map__map_id__upload_osv_post"},"Body_upload_pinhole_video_map__map_id__upload_video_post":{"properties":{"video_file":{"type":"string","format":"binary","title":"Video File"}},"type":"object","required":["video_file"],"title":"Body_upload_pinhole_video_map__map_id__upload_video_post"},"Body_upload_polycam_map__map_id__upload_polycam_post":{"properties":{"zip_file":{"type":"string","format":"binary","title":"Zip File"}},"type":"object","required":["zip_file"],"title":"Body_upload_polycam_map__map_id__upload_polycam_post"},"Body_upload_polycam_mesh_map__map_id__upload_polycam_mesh_post":{"properties":{"mesh_file":{"type":"string","format":"binary","title":"Mesh File"}},"type":"object","required":["mesh_file"],"title":"Body_upload_polycam_mesh_map__map_id__upload_polycam_mesh_post"},"Body_upload_priors_map__map_id__upload_priors_post":{"properties":{"priors":{"type":"string","format":"binary","title":"Priors"}},"type":"object","required":["priors"],"title":"Body_upload_priors_map__map_id__upload_priors_post"},"Body_upload_xgrid_map__map_id__upload_xgrid_post":{"properties":{"zip_file":{"type":"string","format":"binary","title":"Zip File"}},"type":"object","required":["zip_file"],"title":"Body_upload_xgrid_map__map_id__upload_xgrid_post"},"BuildLogsResponse":{"properties":{"map_id":{"type":"integer","title":"Map Id"},"logs":{"type":"string","title":"Logs"},"log_file":{"type":"string","title":"Log File"},"last_modified":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Modified"}},"type":"object","required":["map_id","logs","log_file"],"title":"BuildLogsResponse","description":"Build-logs response."},"BuildQuoteRequest":{"properties":{"input_type":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Input Type"},"pipeline_version":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Pipeline Version"},"source_retention_policy":{"anyOf":[{"$ref":"#/components/schemas/SourceRetentionPolicy"},{"type":"null"}]},"operation_id":{"type":"string","format":"uuid","title":"Operation Id"}},"type":"object","required":["operation_id"],"title":"BuildQuoteRequest"},"BuildRequest":{"properties":{"source_dir":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Dir"},"priors_json":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Priors Json"},"control_points_file":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Control Points File"},"enable_track_extension":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Enable Track Extension"},"force_sfm":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Force Sfm"},"pipeline_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pipeline Type"},"metric_route":{"anyOf":[{"type":"string","enum":["charuco","configured"]},{"type":"null"}],"title":"Metric Route"},"pipeline_version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pipeline Version"},"sfm_backend":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sfm Backend"},"frame_stride":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Frame Stride"},"frame_offset":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Frame Offset"},"frame_limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Frame Limit"},"quote_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Quote Id"}},"type":"object","title":"BuildRequest","description":"Build request parameters."},"CheckoutSessionRequest":{"properties":{"sku":{"type":"string","maxLength":64,"minLength":2,"pattern":"^[a-z0-9][a-z0-9_-]+$","title":"Sku"},"provider":{"anyOf":[{"type":"string","enum":["stripe","wechatpay","alipay"]},{"type":"null"}],"title":"Provider"},"operation_id":{"type":"string","format":"uuid","title":"Operation Id"}},"type":"object","required":["sku","operation_id"],"title":"CheckoutSessionRequest"},"CheckoutSessionResponse":{"properties":{"payment_id":{"type":"string","title":"Payment Id"},"provider":{"type":"string","enum":["stripe","wechatpay","alipay"],"title":"Provider"},"presentation":{"type":"string","enum":["redirect","qr_code"],"title":"Presentation"},"checkout_url":{"type":"string","title":"Checkout Url"},"qr_code_data_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Qr Code Data Url"},"expires_at":{"type":"string","format":"date-time","title":"Expires At"},"replayed":{"type":"boolean","title":"Replayed","default":false}},"type":"object","required":["payment_id","provider","presentation","checkout_url","expires_at"],"title":"CheckoutSessionResponse"},"CloudLinkSubmitRequest":{"properties":{"cloud_type":{"type":"string","enum":["gdrive","dropbox","aliyun"],"title":"Cloud Type"},"brand":{"type":"string","title":"Brand"},"url":{"type":"string","title":"Url"},"video_mode":{"anyOf":[{"type":"string","enum":["normal","timelapse"]},{"type":"null"}],"title":"Video Mode"}},"type":"object","required":["cloud_type","brand","url"],"title":"CloudLinkSubmitRequest","description":"Request body for submitting a cloud-drive link (the server downloads from gdrive/dropbox/aliyun)."},"CloudMeshSubmitRequest":{"properties":{"cloud_type":{"type":"string","enum":["gdrive","dropbox","aliyun"],"title":"Cloud Type"},"url":{"type":"string","title":"Url"}},"type":"object","required":["cloud_type","url"],"title":"CloudMeshSubmitRequest","description":"Request body for cloud-direct download of a Polycam/Kiri mesh (.glb, or .zip containing a single .glb)."},"ContentItem":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"format":{"type":"string","title":"Format"},"file_size":{"type":"integer","title":"File Size"},"position":{"items":{"type":"number"},"type":"array","maxItems":3,"minItems":3,"title":"Position"},"quaternion_xyzw":{"items":{"type":"number"},"type":"array","maxItems":4,"minItems":4,"title":"Quaternion Xyzw"},"scale":{"items":{"type":"number"},"type":"array","maxItems":3,"minItems":3,"title":"Scale"},"behaviors":{"items":{"anyOf":[{"$ref":"#/components/schemas/OrbitBehavior"},{"$ref":"#/components/schemas/GenericBehavior"}]},"type":"array","maxItems":16,"title":"Behaviors"},"created":{"type":"string","title":"Created"},"modified":{"type":"string","title":"Modified"}},"type":"object","required":["id","name","format","file_size","position","quaternion_xyzw","scale","created","modified"],"title":"ContentItem","description":"返回给客户端的单个内容资产，不暴露服务器内部路径。"},"ContentListResponse":{"properties":{"version":{"type":"integer","title":"Version","default":1},"contents":{"items":{"$ref":"#/components/schemas/ContentItem"},"type":"array","title":"Contents"},"scene":{"anyOf":[{"items":{"$ref":"#/components/schemas/SceneItem"},"type":"array"},{"type":"null"}],"title":"Scene"}},"type":"object","title":"ContentListResponse","description":"内容列表响应：资产实例 + 场景对象。"},"ContentUpdateRequest":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"position":{"anyOf":[{"items":{"type":"number"},"type":"array","maxItems":3,"minItems":3},{"type":"null"}],"title":"Position"},"quaternion_xyzw":{"anyOf":[{"items":{"type":"number"},"type":"array","maxItems":4,"minItems":4},{"type":"null"}],"title":"Quaternion Xyzw"},"scale":{"anyOf":[{"items":{"type":"number"},"type":"array","maxItems":3,"minItems":3},{"type":"null"}],"title":"Scale"},"behaviors":{"anyOf":[{"items":{"anyOf":[{"$ref":"#/components/schemas/OrbitBehavior"},{"$ref":"#/components/schemas/GenericBehavior"}]},"type":"array","maxItems":16},{"type":"null"}],"title":"Behaviors"}},"type":"object","title":"ContentUpdateRequest","description":"更新内容资产名称、位姿或行为配置的请求。"},"ContentUploadResponse":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"format":{"type":"string","title":"Format"},"file_size":{"type":"integer","title":"File Size"},"position":{"items":{"type":"number"},"type":"array","title":"Position"},"quaternion_xyzw":{"items":{"type":"number"},"type":"array","title":"Quaternion Xyzw"},"scale":{"items":{"type":"number"},"type":"array","title":"Scale"}},"type":"object","required":["id","name","format","file_size","position","quaternion_xyzw","scale"],"title":"ContentUploadResponse","description":"内容上传响应。"},"EmailVerificationRequest":{"properties":{"token":{"type":"string","maxLength":4096,"minLength":32,"title":"Token"}},"type":"object","required":["token"],"title":"EmailVerificationRequest"},"GenericBehavior":{"properties":{"type":{"type":"string","maxLength":64,"minLength":1,"pattern":"^[A-Za-z][A-Za-z0-9_-]*$","title":"Type"},"schemaVersion":{"type":"integer","maximum":10.0,"minimum":1.0,"title":"Schemaversion","default":1},"enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Enabled"}},"additionalProperties":true,"type":"object","required":["type"],"title":"GenericBehavior","description":"未知 behavior 的扩展壳；客户端必须按能力忽略未知 type。"},"GeometryActiveProduct":{"properties":{"product":{"type":"string","enum":["navigation","occlusion","display"],"title":"Product"},"revision":{"type":"string","pattern":"^[0-9a-f]{64}$","title":"Revision"},"activated_at":{"type":"string","format":"date-time","title":"Activated At"},"source_revision":{"type":"string","title":"Source Revision"},"request_revision":{"type":"string","pattern":"^[0-9a-f]{64}$","title":"Request Revision"},"coordinate":{"$ref":"#/components/schemas/GeometryCoordinate"},"execution_provenance":{"anyOf":[{"oneOf":[{"$ref":"#/components/schemas/GeometryExecutionProvenanceV1"},{"$ref":"#/components/schemas/GeometryExecutionProvenanceV2"}],"discriminator":{"propertyName":"schema","mapping":{"01spatial.geometry-execution-provenance.v1":"#/components/schemas/GeometryExecutionProvenanceV1","01spatial.geometry-execution-provenance.v2":"#/components/schemas/GeometryExecutionProvenanceV2"}}},{"type":"null"}],"title":"Execution Provenance"},"capability":{"$ref":"#/components/schemas/GeometryProduct"},"source_current":{"type":"boolean","title":"Source Current","default":true},"request_current":{"type":"boolean","title":"Request Current","default":true},"stale_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stale Reason"}},"type":"object","required":["product","revision","activated_at","source_revision","request_revision","coordinate","capability"],"title":"GeometryActiveProduct","description":"经文件 pointer 与精确 SUCCESS Job 双门解析出的产品版本。"},"GeometryAssetDescriptor":{"properties":{"path":{"type":"string","maxLength":2048,"minLength":1,"title":"Path"},"sha256":{"type":"string","pattern":"^[0-9a-f]{64}$","title":"Sha256"},"bytes":{"type":"integer","minimum":0.0,"title":"Bytes"},"media_type":{"type":"string","maxLength":255,"minLength":3,"pattern":"^[A-Za-z0-9!#$&^_.+-]+/[A-Za-z0-9!#$&^_.+-]+$","title":"Media Type"},"bbox":{"anyOf":[{"items":{"items":{"type":"number"},"type":"array"},"type":"array"},{"type":"null"}],"title":"Bbox"}},"additionalProperties":false,"type":"object","required":["path","sha256","bytes","media_type"],"title":"GeometryAssetDescriptor","description":"product 显式声明的单个可下载资产。"},"GeometryAttempt":{"properties":{"job_id":{"type":"string","title":"Job Id"},"kind":{"type":"string","title":"Kind"},"status":{"type":"string","title":"Status"},"lifecycle":{"type":"string","enum":["queued","running","succeeded","failed","cancelled"],"title":"Lifecycle"},"progress":{"type":"integer","maximum":100.0,"minimum":0.0,"title":"Progress"},"progress_is_global":{"type":"boolean","const":false,"title":"Progress Is Global","default":false},"stage":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stage"},"stage_completed":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Stage Completed"},"stage_total":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Stage Total"},"heartbeat_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Heartbeat At"},"error_msg":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Msg"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"finished_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Finished At"},"source_revision":{"anyOf":[{"type":"string","pattern":"^[0-9a-f]{64}$"},{"type":"null"}],"title":"Source Revision"},"request_revision":{"anyOf":[{"type":"string","pattern":"^[0-9a-f]{64}$"},{"type":"null"}],"title":"Request Revision"},"geometry_revision":{"anyOf":[{"type":"string","pattern":"^[0-9a-f]{64}$"},{"type":"null"}],"title":"Geometry Revision"}},"type":"object","required":["job_id","kind","status","lifecycle","progress"],"title":"GeometryAttempt","description":"最新 geometry 尝试；未引入 Job.kind 前合法值为 ``null``。"},"GeometryCertificationIssue":{"properties":{"base_request_revision":{"type":"string","pattern":"^[0-9a-f]{64}$","title":"Base Request Revision"},"assertions":{"items":{"type":"string","enum":["complete_static_surface_inventory","complete_navigable_support_semantics","complete_critical_obstacle_inventory","total_geometry_uncertainty_model"]},"type":"array","minItems":1,"title":"Assertions"}},"additionalProperties":false,"type":"object","required":["base_request_revision","assertions"],"title":"GeometryCertificationIssue","description":"独立 certifier 只签发精确 proposal 中逐项显式选中的权限。"},"GeometryColmapProvenance":{"properties":{"version":{"type":"string","maxLength":128,"minLength":1,"title":"Version"},"sha256":{"type":"string","pattern":"^[0-9a-f]{64}$","title":"Sha256"}},"additionalProperties":false,"type":"object","required":["version","sha256"],"title":"GeometryColmapProvenance"},"GeometryCoordinate":{"properties":{"frame":{"type":"string","const":"map","title":"Frame"},"units":{"type":"string","const":"m","title":"Units"},"up_axis":{"type":"string","enum":["Y","Z"],"title":"Up Axis"},"metric_status":{"type":"string","maxLength":128,"minLength":1,"title":"Metric Status"},"gravity_error_deg_p95":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Gravity Error Deg P95"}},"additionalProperties":false,"type":"object","required":["frame","units","up_axis","metric_status"],"title":"GeometryCoordinate","description":"Geometry 窄腰使用的唯一坐标系契约。"},"GeometryDa3Provenance":{"properties":{"runtime_revision":{"type":"string","pattern":"^[0-9a-f]{64}$","title":"Runtime Revision"},"distribution_revision":{"type":"string","pattern":"^[0-9a-f]{64}$","title":"Distribution Revision"},"weights_revision":{"type":"string","pattern":"^[0-9a-f]{64}$","title":"Weights Revision"},"code_revision":{"type":"string","maxLength":128,"minLength":1,"title":"Code Revision"},"model_snapshot_revision":{"type":"string","maxLength":128,"minLength":1,"title":"Model Snapshot Revision"},"backend_revision":{"type":"string","maxLength":256,"minLength":1,"title":"Backend Revision"}},"additionalProperties":false,"type":"object","required":["runtime_revision","distribution_revision","weights_revision","code_revision","model_snapshot_revision","backend_revision"],"title":"GeometryDa3Provenance"},"GeometryDesiredState":{"properties":{"source_revision":{"type":"string","pattern":"^[0-9a-f]{64}$","title":"Source Revision"},"request_revision":{"anyOf":[{"type":"string","pattern":"^[0-9a-f]{64}$"},{"type":"null"}],"title":"Request Revision"},"state":{"type":"string","enum":["request_required","invalid","ready"],"title":"State"},"runnable":{"type":"boolean","title":"Runnable"},"stage":{"type":"string","title":"Stage"},"error_msg":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Msg"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["source_revision","state","runnable","stage","updated_at"],"title":"GeometryDesiredState","description":"当前 source revision 的配置意图，与执行 attempt 生命周期严格分离。"},"GeometryExecutionProvenanceV1":{"properties":{"schema":{"type":"string","const":"01spatial.geometry-execution-provenance.v1","title":"Schema"},"colmap":{"anyOf":[{"$ref":"#/components/schemas/GeometryColmapProvenance"},{"type":"null"}]},"da3":{"anyOf":[{"$ref":"#/components/schemas/GeometryDa3Provenance"},{"type":"null"}]}},"additionalProperties":false,"type":"object","required":["schema","colmap","da3"],"title":"GeometryExecutionProvenanceV1","description":"Manifest v3 的历史只读执行身份；字段集合不可扩展。"},"GeometryExecutionProvenanceV2":{"properties":{"schema":{"type":"string","const":"01spatial.geometry-execution-provenance.v2","title":"Schema"},"colmap":{"anyOf":[{"$ref":"#/components/schemas/GeometryColmapProvenance"},{"type":"null"}]},"da3":{"anyOf":[{"$ref":"#/components/schemas/GeometryDa3Provenance"},{"type":"null"}]},"execution_plan_revision":{"type":"string","pattern":"^[0-9a-f]{64}$","title":"Execution Plan Revision"},"plan_image_closure_revision":{"type":"string","pattern":"^[0-9a-f]{64}$","title":"Plan Image Closure Revision"},"patchmatch_depth_search_domain_revision":{"type":"string","pattern":"^[0-9a-f]{64}$","title":"Patchmatch Depth Search Domain Revision"},"patchmatch_cache_algorithm_revision":{"type":"string","pattern":"^[0-9a-f]{64}$","title":"Patchmatch Cache Algorithm Revision"},"execution_audit_revision":{"type":"string","pattern":"^[0-9a-f]{64}$","title":"Execution Audit Revision"}},"additionalProperties":false,"type":"object","required":["schema","colmap","da3","execution_plan_revision","plan_image_closure_revision","patchmatch_depth_search_domain_revision","patchmatch_cache_algorithm_revision","execution_audit_revision"],"title":"GeometryExecutionProvenanceV2","description":"Manifest v4 的内容寻址执行闭包；所有 revision 均为必填 SHA。"},"GeometryProduct":{"properties":{"build_status":{"type":"string","enum":["success","failed","not_requested"],"title":"Build Status"},"state":{"type":"string","enum":["ready","not_ready","unsupported","not_requested"],"title":"State"},"reason_codes":{"items":{"type":"string"},"type":"array","title":"Reason Codes"},"metrics":{"additionalProperties":true,"type":"object","title":"Metrics"},"quality":{"additionalProperties":true,"type":"object","title":"Quality"},"assets":{"items":{"$ref":"#/components/schemas/GeometryAssetDescriptor"},"type":"array","title":"Assets"}},"additionalProperties":false,"type":"object","required":["build_status","state"],"title":"GeometryProduct","description":"单个 geometry product 的构建结果与能力状态。"},"GeometryPublished":{"properties":{"revision":{"type":"string","pattern":"^[0-9a-f]{64}$","title":"Revision"},"published_at":{"type":"string","format":"date-time","title":"Published At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"source_revision":{"type":"string","title":"Source Revision"},"request_revision":{"type":"string","pattern":"^[0-9a-f]{64}$","title":"Request Revision"},"coordinate":{"$ref":"#/components/schemas/GeometryCoordinate"},"input_adapter":{"type":"string","title":"Input Adapter"},"evidence_revision":{"type":"string","title":"Evidence Revision"},"structure_revision":{"type":"string","title":"Structure Revision"},"execution_provenance":{"anyOf":[{"oneOf":[{"$ref":"#/components/schemas/GeometryExecutionProvenanceV1"},{"$ref":"#/components/schemas/GeometryExecutionProvenanceV2"}],"discriminator":{"propertyName":"schema","mapping":{"01spatial.geometry-execution-provenance.v1":"#/components/schemas/GeometryExecutionProvenanceV1","01spatial.geometry-execution-provenance.v2":"#/components/schemas/GeometryExecutionProvenanceV2"}}},{"type":"null"}],"title":"Execution Provenance"},"provenance_assets":{"items":{"$ref":"#/components/schemas/GeometryAssetDescriptor"},"type":"array","title":"Provenance Assets"},"products":{"additionalProperties":{"$ref":"#/components/schemas/GeometryProduct"},"type":"object","title":"Products"},"source_current":{"type":"boolean","title":"Source Current","default":true},"request_current":{"type":"boolean","title":"Request Current","default":true},"stale_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stale Reason"}},"type":"object","required":["revision","published_at","created_at","source_revision","request_revision","coordinate","input_adapter","evidence_revision","structure_revision","products"],"title":"GeometryPublished","description":"已由 SUCCESS Job 提交、可被 revision URL 精确寻址的 latest candidate。"},"GeometryRequestBootstrapState":{"properties":{"map_id":{"type":"integer","title":"Map Id"},"canonical_map_id":{"type":"integer","title":"Canonical Map Id"},"proposal_revision":{"type":"string","pattern":"^[0-9a-f]{64}$","title":"Proposal Revision"},"request":{"additionalProperties":true,"type":"object","title":"Request"},"foundation_migration":{"additionalProperties":true,"type":"object","title":"Foundation Migration"},"resource_preflight":{"additionalProperties":true,"type":"object","title":"Resource Preflight"}},"additionalProperties":false,"type":"object","required":["map_id","canonical_map_id","proposal_revision","request","foundation_migration","resource_preflight"],"title":"GeometryRequestBootstrapState","description":"Bootstrap 只产生 proposal revision，不冒充正式 request revision。"},"GeometryRequestBootstrapUpdate":{"properties":{"foundation_plan_revision":{"type":"string","pattern":"^[0-9a-f]{64}$","title":"Foundation Plan Revision"},"request":{"additionalProperties":true,"type":"object","title":"Request"}},"additionalProperties":false,"type":"object","required":["foundation_plan_revision","request"],"title":"GeometryRequestBootstrapUpdate","description":"历史地图在 source revision 建立前保存首份 desired-state。"},"GeometryRequestState":{"properties":{"map_id":{"type":"integer","title":"Map Id"},"canonical_map_id":{"type":"integer","title":"Canonical Map Id"},"source_revision":{"type":"string","pattern":"^[0-9a-f]{64}$","title":"Source Revision"},"request_revision":{"type":"string","pattern":"^[0-9a-f]{64}$","title":"Request Revision"},"explicit":{"type":"boolean","title":"Explicit"},"request":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Request"}},"additionalProperties":false,"type":"object","required":["map_id","canonical_map_id","source_revision","request_revision","explicit"],"title":"GeometryRequestState","description":"当前 desired geometry request；无显式文件时仍返回 auto policy revision。"},"GeometryRequestUpdate":{"properties":{"base_request_revision":{"type":"string","pattern":"^[0-9a-f]{64}$","title":"Base Request Revision"},"request":{"additionalProperties":true,"type":"object","title":"Request"}},"additionalProperties":false,"type":"object","required":["base_request_revision","request"],"title":"GeometryRequestUpdate","description":"用 request revision CAS 保存显式 geometry request。"},"GeometryStatusResponse":{"properties":{"map_id":{"type":"integer","title":"Map Id"},"canonical_map_id":{"type":"integer","title":"Canonical Map Id"},"latest_candidate":{"anyOf":[{"$ref":"#/components/schemas/GeometryPublished"},{"type":"null"}]},"active_products":{"additionalProperties":{"anyOf":[{"$ref":"#/components/schemas/GeometryActiveProduct"},{"type":"null"}]},"type":"object","title":"Active Products"},"published":{"anyOf":[{"$ref":"#/components/schemas/GeometryPublished"},{"type":"null"}]},"desired_state":{"anyOf":[{"$ref":"#/components/schemas/GeometryDesiredState"},{"type":"null"}]},"attempt":{"anyOf":[{"$ref":"#/components/schemas/GeometryAttempt"},{"type":"null"}]}},"type":"object","required":["map_id","canonical_map_id"],"title":"GeometryStatusResponse","description":"候选构建、三个独立 active 产品与最新尝试分离表达。"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"LegalAcceptanceCreate":{"properties":{"accepted":{"type":"boolean","const":true,"title":"Accepted"},"user_agreement_version":{"type":"string","maxLength":64,"minLength":1,"title":"User Agreement Version"},"privacy_notice_version":{"type":"string","maxLength":64,"minLength":1,"title":"Privacy Notice Version"},"assent_version":{"type":"string","maxLength":64,"minLength":1,"title":"Assent Version"},"document_locale":{"type":"string","maxLength":16,"minLength":2,"title":"Document Locale"},"business_capacity_confirmed":{"type":"boolean","const":true,"title":"Business Capacity Confirmed"}},"type":"object","required":["accepted","user_agreement_version","privacy_notice_version","assent_version","document_locale","business_capacity_confirmed"],"title":"LegalAcceptanceCreate","description":"注册时对当前用户协议的明确接受及对隐私告知的阅读确认。"},"LegalHoldCreate":{"properties":{"acceptance_id":{"type":"integer","minimum":1.0,"title":"Acceptance Id"},"reason":{"type":"string","maxLength":4000,"minLength":3,"title":"Reason"},"review_at":{"type":"string","format":"date-time","title":"Review At"},"expires_at":{"type":"string","format":"date-time","title":"Expires At"}},"type":"object","required":["acceptance_id","reason","review_at","expires_at"],"title":"LegalHoldCreate"},"LegalHoldRelease":{"properties":{"reason":{"type":"string","maxLength":4000,"minLength":3,"title":"Reason"}},"type":"object","required":["reason"],"title":"LegalHoldRelease"},"LightScaleCompensation":{"properties":{"range":{"type":"boolean","title":"Range","default":true},"intensity":{"anyOf":[{"type":"string","enum":["perceptual","inverse-square"]},{"type":"null"}],"title":"Intensity"},"exponent":{"type":"number","maximum":4.0,"minimum":0.0,"title":"Exponent","default":0.45},"maxMultiplier":{"type":"number","maximum":16.0,"minimum":1.0,"title":"Maxmultiplier","default":2.0}},"type":"object","title":"LightScaleCompensation","description":"子灯光随父模型缩放时的补偿策略。"},"MapCloneRequest":{"properties":{"map_id":{"type":"integer","title":"Map Id","description":"Source map ID to clone"}},"type":"object","required":["map_id"],"title":"MapCloneRequest","description":"Admin map-clone request."},"MapConfiguratorConfigResponse":{"properties":{"config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Config"},"revision":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Revision"},"source_revision":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Revision"},"metric_route":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Metric Route"}},"type":"object","title":"MapConfiguratorConfigResponse","description":"Map Configurator 重新编辑时使用的权威配置快照。"},"MapCreate":{"properties":{"name":{"type":"string","maxLength":1024,"minLength":1,"title":"Name"},"desc":{"type":"string","maxLength":1024,"title":"Desc","default":""},"type":{"type":"string","title":"Type","description":"Map type: sfm-fixed, sfm-refine, or lidar (empty before build)","default":""},"input":{"type":"string","title":"Input","description":"Input source: video, 360_video, polycam, kiri, navvis, faro, leica, matterport, hexagon, xgrid, fjd, or chcnav","default":"video"},"project_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Project Id"},"latitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Latitude"},"longitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Longitude"},"altitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Altitude"}},"type":"object","required":["name"],"title":"MapCreate","description":"Create map request."},"MapMoveRequest":{"properties":{"project_id":{"type":"integer","title":"Project Id","description":"Target project ID to move the map to"}},"type":"object","required":["project_id"],"title":"MapMoveRequest","description":"Move-map-to-project request."},"MapResponse":{"properties":{"name":{"type":"string","maxLength":1024,"minLength":1,"title":"Name"},"desc":{"type":"string","maxLength":1024,"title":"Desc","default":""},"type":{"type":"string","title":"Type","description":"Map type: sfm-fixed, sfm-refine, or lidar (empty before build)","default":""},"input":{"type":"string","title":"Input","description":"Input source: video, 360_video, polycam, kiri, navvis, faro, leica, matterport, hexagon, xgrid, fjd, or chcnav","default":"video"},"id":{"type":"integer","title":"Id"},"project_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Project Id"},"image_num":{"type":"integer","title":"Image Num"},"dir":{"type":"string","title":"Dir"},"status":{"type":"string","title":"Status"},"active":{"type":"boolean","title":"Active"},"localization_ver":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Localization Ver"},"pipeline_ver":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pipeline Ver"},"coordinate_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Coordinate Status"},"metric_diagnostic":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Metric Diagnostic"},"tie_summary":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Tie Summary"},"metric_route":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Metric Route"},"active_job":{"anyOf":[{"$ref":"#/components/schemas/ActiveJobInfo"},{"type":"null"}]},"map_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Map Key"},"latitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Latitude"},"longitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Longitude"},"altitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Altitude"},"origin_pose":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Origin Pose"},"bbox":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Bbox"},"render_params":{"anyOf":[{"$ref":"#/components/schemas/RenderParams"},{"type":"null"}]},"creator_id":{"type":"integer","title":"Creator Id"},"owner_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner Id"},"source_map_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Source Map Id"},"availability_state":{"type":"string","title":"Availability State","default":"online"},"first_ready_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"First Ready At"},"hosting_free_until":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Hosting Free Until"},"source_retention_policy":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Retention Policy"},"floor_area":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Floor Area"},"saas_enabled":{"type":"boolean","title":"Saas Enabled","default":false},"analytics_retention_days":{"type":"integer","title":"Analytics Retention Days","default":7},"created":{"type":"string","format":"date-time","title":"Created"},"modified":{"type":"string","format":"date-time","title":"Modified"}},"type":"object","required":["name","id","project_id","image_num","dir","status","active","localization_ver","pipeline_ver","map_key","latitude","longitude","altitude","creator_id","created","modified"],"title":"MapResponse","description":"Map response."},"MapStatus":{"properties":{"map_id":{"type":"integer","title":"Map Id"},"status":{"type":"string","title":"Status"},"progress":{"type":"integer","title":"Progress"},"stage":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stage"},"error_msg":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Msg"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"finished_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Finished At"},"queue_position":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Queue Position"},"active_job":{"anyOf":[{"$ref":"#/components/schemas/ActiveJobInfo"},{"type":"null"}]},"image_num":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Image Num"},"pipeline_ver":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pipeline Ver"},"localization_ver":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Localization Ver"},"map_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Map Key"},"map_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Map Type"},"coordinate_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Coordinate Status"},"metric_route":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Metric Route"},"tie_summary":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Tie Summary"},"metric_diagnostic":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Metric Diagnostic"}},"type":"object","required":["map_id","status","progress","stage","error_msg","created_at","finished_at"],"title":"MapStatus","description":"Map build status response."},"MapTransferRequest":{"properties":{"target_user_id":{"type":"integer","title":"Target User Id","description":"Target user ID to transfer the map to"}},"type":"object","required":["target_user_id"],"title":"MapTransferRequest","description":"Map transfer request."},"MapUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":1024,"minLength":1},{"type":"null"}],"title":"Name"},"desc":{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"Desc"},"input":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Input","description":"Input source: video, 360_video, polycam, kiri, navvis, faro, leica, matterport, hexagon, xgrid, fjd, or chcnav"},"latitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Latitude"},"longitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Longitude"},"altitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Altitude"},"origin_pose":{"anyOf":[{"$ref":"#/components/schemas/OriginPose"},{"type":"null"}]},"clear_origin_pose":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Clear Origin Pose"}},"type":"object","title":"MapUpdate","description":"Update map request."},"OrbitBehavior":{"properties":{"type":{"type":"string","const":"orbit","title":"Type","default":"orbit"},"schemaVersion":{"type":"integer","maximum":10.0,"minimum":1.0,"title":"Schemaversion","default":1},"enabled":{"type":"boolean","title":"Enabled","default":false},"center":{"items":{"type":"number"},"type":"array","maxItems":3,"minItems":3,"title":"Center"},"radius":{"type":"number","maximum":10000.0,"minimum":0.0,"title":"Radius","default":1.0},"angularSpeed":{"type":"number","maximum":100.0,"minimum":-100.0,"title":"Angularspeed","default":0.35},"heightAmplitude":{"type":"number","maximum":10000.0,"minimum":0.0,"title":"Heightamplitude","default":0.0},"heightFrequency":{"type":"number","maximum":100.0,"minimum":0.0,"title":"Heightfrequency","default":2.0},"startAngle":{"type":"number","maximum":100000.0,"minimum":-100000.0,"title":"Startangle","default":0.0},"phase":{"type":"number","maximum":100000.0,"minimum":-100000.0,"title":"Phase","default":0.0},"orientationMode":{"type":"string","enum":["tangent","fixed","center"],"title":"Orientationmode","default":"tangent"},"forwardAxis":{"type":"string","enum":["+Z","-Z","+X","-X"],"title":"Forwardaxis","default":"+Z"},"headingOffsetDeg":{"type":"number","maximum":3600.0,"minimum":-3600.0,"title":"Headingoffsetdeg","default":0.0},"fixedQuaternion":{"items":{"type":"number"},"type":"array","maxItems":4,"minItems":4,"title":"Fixedquaternion"},"faceTangent":{"type":"boolean","title":"Facetangent","default":true},"baseQuaternion":{"items":{"type":"number"},"type":"array","maxItems":4,"minItems":4,"title":"Basequaternion"}},"type":"object","title":"OrbitBehavior","description":"模型级 orbit 行为。字段保持扁平 JSON，便于各客户端直接消费。"},"OriginPose":{"properties":{"position":{"items":{"type":"number"},"type":"array","maxItems":3,"minItems":3,"title":"Position","description":"Position in the SfM frame [x, y, z]"},"quaternion_xyzw":{"items":{"type":"number"},"type":"array","maxItems":4,"minItems":4,"title":"Quaternion Xyzw","description":"Rotation quaternion [x, y, z, w]"}},"type":"object","required":["position","quaternion_xyzw"],"title":"OriginPose","description":"User-defined origin pose (in the SfM coordinate frame)."},"PasswordChange":{"properties":{"current_password":{"type":"string","title":"Current Password","description":"Current password"},"new_password":{"type":"string","maxLength":1024,"minLength":8,"title":"New Password","description":"New password"}},"type":"object","required":["current_password","new_password"],"title":"PasswordChange","description":"Password change request."},"PaymentMode":{"type":"string","enum":["prepaid","invoice","exempt"],"title":"PaymentMode"},"PaymentPage":{"properties":{"items":{"items":{"$ref":"#/components/schemas/PaymentResponse"},"type":"array","title":"Items"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"}},"type":"object","required":["items","next_cursor"],"title":"PaymentPage"},"PaymentRefundResponse":{"properties":{"public_id":{"type":"string","title":"Public Id"},"provider":{"type":"string","title":"Provider"},"merchant_refund_id":{"type":"string","title":"Merchant Refund Id"},"provider_refund_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider Refund Id"},"amount_minor":{"type":"integer","title":"Amount Minor"},"status":{"type":"string","title":"Status"},"reason":{"type":"string","title":"Reason"},"attempt_count":{"type":"integer","title":"Attempt Count"},"last_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Error"},"last_checked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Checked At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["public_id","provider","merchant_refund_id","amount_minor","status","reason","attempt_count","created_at","updated_at"],"title":"PaymentRefundResponse"},"PaymentResponse":{"properties":{"public_id":{"type":"string","title":"Public Id"},"provider":{"type":"string","title":"Provider"},"sku":{"type":"string","title":"Sku"},"currency":{"type":"string","title":"Currency"},"amount_minor":{"type":"integer","title":"Amount Minor"},"automatic_tax":{"type":"boolean","title":"Automatic Tax"},"provider_amount_minor":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Provider Amount Minor"},"tax_amount_minor":{"type":"integer","title":"Tax Amount Minor"},"credit_milli_credit":{"type":"integer","title":"Credit Milli Credit"},"region":{"type":"string","title":"Region"},"status":{"type":"string","title":"Status"},"refunded_amount_minor":{"type":"integer","title":"Refunded Amount Minor"},"disputed_amount_minor":{"type":"integer","title":"Disputed Amount Minor"},"reversed_credit_milli_credit":{"type":"integer","title":"Reversed Credit Milli Credit"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["public_id","provider","sku","currency","amount_minor","automatic_tax","tax_amount_minor","credit_milli_credit","region","status","refunded_amount_minor","disputed_amount_minor","reversed_credit_milli_credit","created_at","updated_at"],"title":"PaymentResponse"},"ProjectCreate":{"properties":{"name":{"type":"string","maxLength":1024,"minLength":1,"title":"Name"},"desc":{"type":"string","maxLength":1024,"title":"Desc","default":""}},"type":"object","required":["name"],"title":"ProjectCreate","description":"Create project request."},"ProjectListResponse":{"properties":{"projects":{"items":{"$ref":"#/components/schemas/ProjectResponse"},"type":"array","title":"Projects"},"total":{"type":"integer","title":"Total"}},"type":"object","required":["projects","total"],"title":"ProjectListResponse","description":"Project list response."},"ProjectResponse":{"properties":{"name":{"type":"string","maxLength":1024,"minLength":1,"title":"Name"},"desc":{"type":"string","maxLength":1024,"title":"Desc","default":""},"id":{"type":"integer","title":"Id"},"user_id":{"type":"integer","title":"User Id"},"created":{"type":"string","format":"date-time","title":"Created"},"building_map_count":{"type":"integer","title":"Building Map Count","default":0},"map_building_count":{"type":"integer","title":"Map Building Count","default":0},"geometry_building_count":{"type":"integer","title":"Geometry Building Count","default":0},"active_work_count":{"type":"integer","title":"Active Work Count","default":0}},"type":"object","required":["name","id","user_id","created"],"title":"ProjectResponse","description":"Project response."},"ProjectUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":1024,"minLength":1},{"type":"null"}],"title":"Name"},"desc":{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"Desc"}},"type":"object","title":"ProjectUpdate","description":"Update project request."},"RecoveryHoldArchiveResponse":{"properties":{"map_id":{"type":"integer","title":"Map Id"},"service_event_id":{"type":"string","title":"Service Event Id"},"storage_state":{"type":"string","title":"Storage State"},"availability_state":{"type":"string","title":"Availability State"},"archive_bytes":{"type":"integer","title":"Archive Bytes"},"effective_at":{"type":"string","format":"date-time","title":"Effective At"},"replayed":{"type":"boolean","title":"Replayed","default":false}},"type":"object","required":["map_id","service_event_id","storage_state","availability_state","archive_bytes","effective_at"],"title":"RecoveryHoldArchiveResponse"},"RecoveryRestoreRequest":{"properties":{"operation_id":{"type":"string","format":"uuid","title":"Operation Id"}},"type":"object","required":["operation_id"],"title":"RecoveryRestoreRequest"},"RenderParams":{"properties":{"width":{"type":"integer","maximum":100000.0,"exclusiveMinimum":0.0,"title":"Width","description":"Rendered pinhole image width (pixels)"},"height":{"type":"integer","maximum":100000.0,"exclusiveMinimum":0.0,"title":"Height","description":"Rendered pinhole image height (pixels)"},"fx":{"type":"number","exclusiveMinimum":0.0,"title":"Fx","description":"Horizontal focal length (pixels)"},"fy":{"type":"number","exclusiveMinimum":0.0,"title":"Fy","description":"Vertical focal length (pixels)"},"cx":{"type":"number","minimum":0.0,"title":"Cx","description":"Principal point x (pixels)"},"cy":{"type":"number","minimum":0.0,"title":"Cy","description":"Principal point y (pixels)"},"camera_model":{"type":"string","minLength":1,"title":"Camera Model","description":"COLMAP camera model: SIMPLE_PINHOLE / PINHOLE / ..."},"hfov_deg":{"anyOf":[{"type":"number","exclusiveMaximum":180.0,"exclusiveMinimum":0.0},{"type":"null"}],"title":"Hfov Deg","description":"Horizontal field of view (degrees)"},"vfov_deg":{"anyOf":[{"type":"number","exclusiveMaximum":180.0,"exclusiveMinimum":0.0},{"type":"null"}],"title":"Vfov Deg","description":"Vertical field of view (degrees)"}},"type":"object","required":["width","height","fx","fy","cx","cy","camera_model"],"title":"RenderParams","description":"Virtual-pinhole intrinsics used during build (rendering panoramas to pinhole views).\n\nClients use this to compute the optimal downscale factor for localization\nqueries (pixel-density matching: keep the query's effective fx close to\nthe map's render fx). pipeline19g/21b share one intrinsics across the\nwhole virtual-camera rig, so a single object suffices.\n\nField constraints (enforced by Pydantic): width/height/fx/fy > 0;\ncx/cy >= 0; FoV in (0, 180). Pathological values (e.g. corrupted metadata\nleaving fx=0 or FoV=180) raise ValidationError at construction time and\nare caught by the service layer, which falls back to the next data source."},"SaasToggleRequest":{"properties":{"enabled":{"type":"boolean","title":"Enabled"},"retention_days":{"anyOf":[{"type":"integer","enum":[1,7,30,90]},{"type":"null"}],"title":"Retention Days"}},"type":"object","required":["enabled"],"title":"SaasToggleRequest"},"SceneItem":{"properties":{"id":{"type":"string","title":"Id"},"type":{"type":"string","title":"Type"},"subType":{"type":"string","title":"Subtype"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"parentId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Parentid"},"position":{"anyOf":[{"items":{"type":"number"},"type":"array","maxItems":3,"minItems":3},{"type":"null"}],"title":"Position"},"quaternion_xyzw":{"anyOf":[{"items":{"type":"number"},"type":"array","maxItems":4,"minItems":4},{"type":"null"}],"title":"Quaternion Xyzw"},"scale":{"anyOf":[{"items":{"type":"number"},"type":"array","maxItems":3,"minItems":3},{"type":"null"}],"title":"Scale"},"color":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Color"},"intensity":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Intensity"},"range":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Range"},"childTransform":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Childtransform"},"lightRig":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lightrig"},"scaleCompensation":{"anyOf":[{"$ref":"#/components/schemas/LightScaleCompensation"},{"type":"null"}]},"material":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Material"}},"type":"object","required":["id","type","subType","name"],"title":"SceneItem","description":"场景对象：几何体、灯光或标签标注。"},"SceneUpdateRequest":{"properties":{"scene":{"items":{"$ref":"#/components/schemas/SceneItem"},"type":"array","title":"Scene"}},"type":"object","required":["scene"],"title":"SceneUpdateRequest","description":"覆盖保存场景对象列表的请求。"},"SourceRetentionPolicy":{"type":"string","enum":["keep_hot","delete_after_grace","archive_after_grace"],"title":"SourceRetentionPolicy"},"StorageOperationAcceptRequest":{"properties":{"operation_id":{"type":"string","format":"uuid","title":"Operation Id"},"keep_archive_copy":{"type":"boolean","title":"Keep Archive Copy","default":false}},"type":"object","required":["operation_id"],"title":"StorageOperationAcceptRequest"},"StorageOperationResponse":{"properties":{"operation_id":{"type":"string","title":"Operation Id"},"map_id":{"type":"integer","title":"Map Id"},"operation_type":{"type":"string","title":"Operation Type"},"state":{"type":"string","title":"State"},"expected_bytes":{"type":"integer","title":"Expected Bytes"},"copied_bytes":{"type":"integer","title":"Copied Bytes"},"verified_bytes":{"type":"integer","title":"Verified Bytes"},"required_replica_count":{"type":"integer","title":"Required Replica Count"},"verified_replica_count":{"type":"integer","title":"Verified Replica Count"},"shadow_only":{"type":"boolean","title":"Shadow Only"},"keep_archive_copy":{"type":"boolean","title":"Keep Archive Copy"},"error_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Code"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"started_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Started At"},"finished_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Finished At"}},"type":"object","required":["operation_id","map_id","operation_type","state","expected_bytes","copied_bytes","verified_bytes","required_replica_count","verified_replica_count","shadow_only","keep_archive_copy","created_at"],"title":"StorageOperationResponse"},"StorageQuoteRequest":{"properties":{"operation_type":{"$ref":"#/components/schemas/ArchiveOperationType"},"operation_id":{"type":"string","format":"uuid","title":"Operation Id"},"keep_archive_copy":{"type":"boolean","title":"Keep Archive Copy","default":false}},"type":"object","required":["operation_type","operation_id"],"title":"StorageQuoteRequest"},"StorageQuoteResponse":{"properties":{"quote_id":{"type":"string","title":"Quote Id"},"map_id":{"type":"integer","title":"Map Id"},"operation_type":{"type":"string","title":"Operation Type"},"logical_bytes":{"type":"integer","title":"Logical Bytes"},"immediate_milli_credit":{"type":"integer","title":"Immediate Milli Credit"},"estimated_hot_30d_milli_credit":{"type":"integer","title":"Estimated Hot 30D Milli Credit"},"estimated_archive_30d_milli_credit":{"type":"integer","title":"Estimated Archive 30D Milli Credit"},"keep_archive_copy":{"type":"boolean","title":"Keep Archive Copy"},"pricing_version":{"type":"string","title":"Pricing Version"},"expires_at":{"type":"string","format":"date-time","title":"Expires At"},"replayed":{"type":"boolean","title":"Replayed","default":false}},"type":"object","required":["quote_id","map_id","operation_type","logical_bytes","immediate_milli_credit","estimated_hot_30d_milli_credit","estimated_archive_30d_milli_credit","keep_archive_copy","pricing_version","expires_at"],"title":"StorageQuoteResponse"},"Token":{"properties":{"access_token":{"type":"string","title":"Access Token"},"token_type":{"type":"string","title":"Token Type","default":"bearer"},"expires_in":{"type":"integer","title":"Expires In"}},"type":"object","required":["access_token","expires_in"],"title":"Token","description":"JWT Token response."},"UserCreate":{"properties":{"name":{"type":"string","maxLength":1024,"minLength":1,"title":"Name","description":"Username"},"email":{"type":"string","maxLength":1024,"format":"email","title":"Email"},"password":{"type":"string","maxLength":1024,"minLength":8,"title":"Password"},"legal_acceptance":{"$ref":"#/components/schemas/LegalAcceptanceCreate"}},"type":"object","required":["name","email","password","legal_acceptance"],"title":"UserCreate","description":"Create user request."},"UserLogin":{"properties":{"email":{"type":"string","format":"email","title":"Email"},"password":{"type":"string","title":"Password"}},"type":"object","required":["email","password"],"title":"UserLogin","description":"User login request."},"UserResponse":{"properties":{"name":{"type":"string","maxLength":1024,"minLength":1,"title":"Name","description":"Username"},"email":{"type":"string","maxLength":1024,"format":"email","title":"Email"},"id":{"type":"integer","title":"Id"},"level":{"type":"integer","title":"Level"},"organization_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Organization Id"},"api_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Api Key"},"locale":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Locale"},"is_admin":{"type":"boolean","title":"Is Admin","default":false},"oauth_provider":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Oauth Provider"},"has_password":{"type":"boolean","title":"Has Password","default":false},"avatar":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Avatar"},"avatar_source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Avatar Source"},"email_verified_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Email Verified At"},"email_verification_available":{"type":"boolean","title":"Email Verification Available","default":false},"created":{"type":"string","format":"date-time","title":"Created"},"modified":{"type":"string","format":"date-time","title":"Modified"}},"type":"object","required":["name","email","id","level","created","modified"],"title":"UserResponse","description":"User response."},"UserUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":1024,"minLength":1},{"type":"null"}],"title":"Name"},"locale":{"anyOf":[{"type":"string","maxLength":16},{"type":"null"}],"title":"Locale"}},"type":"object","title":"UserUpdate","description":"Update user request."},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}},"securitySchemes":{"HTTPBearer":{"type":"http","scheme":"bearer"}}}}