{"openapi":"3.1.0","info":{"title":"AI Estimating Assistant","description":"AI-powered estimating assistant for insurance adjusters and contractors.","version":"0.1.0"},"paths":{"/health/":{"get":{"tags":["health"],"summary":"Health Check","description":"Health check endpoint to verify the API is running.\n\nIncludes build info (git_sha / git_branch / git_dirty) so you can confirm\nwhich exact commit this instance is serving — live or local.","operationId":"health_check_health__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/health/auth":{"get":{"tags":["health"],"summary":"Auth Health","description":"Diagnostic endpoint for Firebase ID token verification.\n\nWithout an Authorization header: reports whether the Firebase Admin SDK\ninitialized and which project it's bound to. Use for uptime monitoring\nof the verification path.\n\nWith `Authorization: Bearer <token>`: also attempts to verify the token\nand reports the decoded uid/email or the specific error. Use this from\nthe frontend (or curl with a real token) to detect token-verification\ndrift — e.g., audience mismatch, expired keys, project ID drift.\n\nReturns:\n    Dict with admin_initialized, project_id, and optionally\n    token_verified/uid/email/error fields.","operationId":"auth_health_health_auth_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Auth Health Health Auth Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/transcribe/":{"post":{"tags":["transcribe"],"summary":"Transcribe audio and return structured scope","description":"Accepts an audio file, transcribes it using Faster-Whisper, and returns the transcript and metadata.\nAllows anonymous access if Authorization header is not present.","operationId":"transcribe_audio_route_api_v1_transcribe__post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_transcribe_audio_route_api_v1_transcribe__post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/chatbot/":{"post":{"tags":["chatbot"],"summary":"Chatbot Endpoint","description":"Enhanced chatbot endpoint with scope generation capabilities.","operationId":"chatbot_endpoint_api_v1_chatbot__post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_chatbot_endpoint_api_v1_chatbot__post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatbotResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/chatbot/generate-scope":{"post":{"tags":["chatbot"],"summary":"Generate Scope Endpoint","description":"Dedicated endpoint for scope generation with full parameter control.","operationId":"generate_scope_endpoint_api_v1_chatbot_generate_scope_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__models__scope__ScopeGenerationRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Generate Scope Endpoint Api V1 Chatbot Generate Scope Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/user/projects/":{"get":{"tags":["projects"],"summary":"Get User Projects","description":"Get all projects for the current user from Supabase.","operationId":"get_user_projects_api_v1_user_projects__get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Project"},"title":"Response Get User Projects Api V1 User Projects  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["projects"],"summary":"Create Project","description":"Create a new project for the current user in Supabase.","operationId":"create_project_api_v1_user_projects__post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Project"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/user/projects/match":{"post":{"tags":["projects"],"summary":"Match Project From Header","description":"Match an estimate's header_metadata against this user's projects.\n\nPowers the post-PDF-parse confirmation dialog on the Completeness page.\nReturns:\n  exact_match: a single project whose claim_number matches (or None)\n  fuzzy_matches: up to 3 owner/street similarity matches above threshold\n\nFailure is non-fatal for the caller — the frontend falls back to plain\nparse-output rendering if this endpoint errors.","operationId":"match_project_from_header_api_v1_user_projects_match_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/user/projects/{project_id}":{"get":{"tags":["projects"],"summary":"Get Project","description":"Get a specific project by ID from Supabase, ensuring user ownership.","operationId":"get_project_api_v1_user_projects__project_id__get","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Project"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["projects"],"summary":"Update Project","description":"Update an existing project in Supabase.","operationId":"update_project_api_v1_user_projects__project_id__put","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Project"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["projects"],"summary":"Delete Project","description":"Delete a project from Supabase, including related notes.","operationId":"delete_project_api_v1_user_projects__project_id__delete","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/user/projects/{project_id}/test-delete":{"get":{"tags":["projects"],"summary":"Test Delete Endpoint","description":"Test endpoint to verify routing and authentication work.","operationId":"test_delete_endpoint_api_v1_user_projects__project_id__test_delete_get","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/user/projects/notes/{project_id}":{"get":{"tags":["notes"],"summary":"Get Project Notes","description":"Get all notes for a specific project from Supabase.","operationId":"get_project_notes_api_v1_user_projects_notes__project_id__get","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["notes"],"summary":"Create Note","description":"Create a new text note for a project in Supabase.","operationId":"create_note_api_v1_user_projects_notes__project_id__post","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NoteCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Note"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/user/projects/notes/{project_id}/voice":{"post":{"tags":["notes"],"summary":"Create Voice Note","description":"Create a new voice note by uploading an audio file and transcribing it.","operationId":"create_voice_note_api_v1_user_projects_notes__project_id__voice_post","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_create_voice_note_api_v1_user_projects_notes__project_id__voice_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/user/projects/notes/{project_id}/photo":{"post":{"tags":["notes"],"summary":"Create Photo Note","description":"Create a new photo note by uploading an image file.","operationId":"create_photo_note_api_v1_user_projects_notes__project_id__photo_post","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_create_photo_note_api_v1_user_projects_notes__project_id__photo_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/user/projects/notes/{project_id}/{note_id}":{"put":{"tags":["notes"],"summary":"Update Note","description":"Update an existing note in Supabase.","operationId":"update_note_api_v1_user_projects_notes__project_id___note_id__put","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"note_id","in":"path","required":true,"schema":{"type":"string","title":"Note Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NoteUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Note"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["notes"],"summary":"Delete Note","description":"Delete a note from Supabase.","operationId":"delete_note_api_v1_user_projects_notes__project_id___note_id__delete","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"note_id","in":"path","required":true,"schema":{"type":"string","title":"Note Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/user/projects/notes/{project_id}/{note_id}/file":{"get":{"tags":["notes"],"summary":"Get Note File","description":"Download a file attached to a note (voice recording or photo).\nHandles both Azure Storage URLs and local file paths.","operationId":"get_note_file_api_v1_user_projects_notes__project_id___note_id__file_get","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"note_id","in":"path","required":true,"schema":{"type":"string","title":"Note Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/user/projects/notes/{project_id}/{note_id}/image":{"get":{"tags":["notes"],"summary":"Get Note Image Public","description":"Public endpoint to serve image files for photo notes without authentication headers.\nSecurity: Validates that the note exists and is a photo type.\nHandles both Azure Storage URLs and local file paths.","operationId":"get_note_image_public_api_v1_user_projects_notes__project_id___note_id__image_get","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"note_id","in":"path","required":true,"schema":{"type":"string","title":"Note Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/user/projects/notes/{project_id}/{note_id}/retry-transcription":{"post":{"tags":["notes"],"summary":"Retry Transcription","description":"Retry transcription for a voice note that has pending transcription.","operationId":"retry_transcription_api_v1_user_projects_notes__project_id___note_id__retry_transcription_post","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"note_id","in":"path","required":true,"schema":{"type":"string","title":"Note Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/user/profile":{"get":{"tags":["users"],"summary":"Get User Profile","description":"Get the current user's profile information.","operationId":"get_user_profile_api_v1_user_profile_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserProfile"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["users"],"summary":"Create User Profile","description":"Create or update the current user's profile.","operationId":"create_user_profile_api_v1_user_profile_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserProfileUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserProfile"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["users"],"summary":"Update User Profile","description":"Update the current user's profile.","operationId":"update_user_profile_api_v1_user_profile_put","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserProfileUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserProfile"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/user/projects/{project_id}/photos/{note_id}/tags":{"post":{"tags":["photo-tags"],"summary":"Create Photo Tag","description":"Create a new tag for a photo.","operationId":"create_photo_tag_api_v1_user_projects__project_id__photos__note_id__tags_post","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"note_id","in":"path","required":true,"schema":{"type":"string","title":"Note Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PhotoTagCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PhotoTag"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["photo-tags"],"summary":"Get Photo Tags","description":"Get all tags for a specific photo.","operationId":"get_photo_tags_api_v1_user_projects__project_id__photos__note_id__tags_get","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"note_id","in":"path","required":true,"schema":{"type":"string","title":"Note Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PhotoTag"},"title":"Response Get Photo Tags Api V1 User Projects  Project Id  Photos  Note Id  Tags Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["photo-tags"],"summary":"Delete All Photo Tags","description":"Delete all tags for a specific photo.","operationId":"delete_all_photo_tags_api_v1_user_projects__project_id__photos__note_id__tags_delete","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"note_id","in":"path","required":true,"schema":{"type":"string","title":"Note Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/user/projects/{project_id}/photos":{"get":{"tags":["photo-tags"],"summary":"Get Photos With Tags","description":"Get all photos in a project with their tags, optionally filtered.","operationId":"get_photos_with_tags_api_v1_user_projects__project_id__photos_get","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"category_ids","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by category IDs","title":"Category Ids"},"description":"Filter by category IDs"},{"name":"room_ids","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by room IDs","title":"Room Ids"},"description":"Filter by room IDs"},{"name":"damage_types","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by damage types","title":"Damage Types"},"description":"Filter by damage types"},{"name":"has_notes","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter photos with/without tag notes","title":"Has Notes"},"description":"Filter photos with/without tag notes"},{"name":"untagged_only","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Show only untagged photos","default":false,"title":"Untagged Only"},"description":"Show only untagged photos"},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PhotoWithTags"},"title":"Response Get Photos With Tags Api V1 User Projects  Project Id  Photos Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/user/projects/{project_id}/photos/tags/{tag_id}":{"put":{"tags":["photo-tags"],"summary":"Update Photo Tag","description":"Update an existing photo tag.","operationId":"update_photo_tag_api_v1_user_projects__project_id__photos_tags__tag_id__put","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"tag_id","in":"path","required":true,"schema":{"type":"string","title":"Tag Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PhotoTagUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PhotoTag"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["photo-tags"],"summary":"Delete Photo Tag","description":"Delete a photo tag.","operationId":"delete_photo_tag_api_v1_user_projects__project_id__photos_tags__tag_id__delete","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"tag_id","in":"path","required":true,"schema":{"type":"string","title":"Tag Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/user/projects/{project_id}/photos/tags/bulk":{"post":{"tags":["photo-tags"],"summary":"Bulk Tag Photos","description":"Apply tags to multiple photos at once.","operationId":"bulk_tag_photos_api_v1_user_projects__project_id__photos_tags_bulk_post","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkTagCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkTagResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/user/projects/{project_id}/photos/tags/statistics":{"get":{"tags":["photo-tags"],"summary":"Get Tag Statistics","description":"Get tag usage statistics for a project.","operationId":"get_tag_statistics_api_v1_user_projects__project_id__photos_tags_statistics_get","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagStatistics"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/esx/generate-from-scope":{"post":{"tags":["esx"],"summary":"Generate From Scope","description":"Generate an importable ESX file from a saved scope.\n\nReturns the raw ESX bytes as ``application/octet-stream``. The full\n``AdapterReport`` is base64-encoded JSON in the ``X-Adapter-Report``\nresponse header — the front-end can decode it and surface\nmanual-entry items / catalog misses next to the download.","operationId":"generate_from_scope_api_v1_esx_generate_from_scope_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateFromScopeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}},"application/octet-stream":{}}},"404":{"description":"Scope or project not found"},"403":{"description":"Caller does not own the project"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/esx/generate-from-scope/json":{"post":{"tags":["esx"],"summary":"Generate From Scope Json","description":"Same as `/generate-from-scope` but returns base64 ESX + report in JSON.\n\nProvided as an alternative when callers can't easily consume octet-stream\n+ a custom header (e.g. some browser fetch wrappers strip non-standard\nresponse headers).","operationId":"generate_from_scope_json_api_v1_esx_generate_from_scope_json_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateFromScopeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateFromScopeJsonResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/esx/generate-from-pdf/json":{"post":{"tags":["esx"],"summary":"Generate From Pdf Json","description":"Faithfully import a carrier PDF estimate and return an importable ESX.\n\nMetered for trial users: enforces a page cap, consumes one credit before the\nwork, and refunds it if the pipeline fails (so a broken PDF never burns the\nuser's only free conversion). Admins/internal users are unmetered.","operationId":"generate_from_pdf_json_api_v1_esx_generate_from_pdf_json_post","parameters":[{"name":"max_items","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Items"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_generate_from_pdf_json_api_v1_esx_generate_from_pdf_json_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateFromScopeJsonResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/esx/generate-from-parse":{"post":{"tags":["esx"],"summary":"Generate From Parse","description":"Export the persisted (displayed) parse to an importable ESX — WYSIWYG.\n\nLoads the ``ParsedEstimate`` the Supplement page stored for this user under\n``body.parse_hash`` (closing the display!=download divergence: the same\nparse the user reviewed is the one exported), converts it to a\n``GeneratedScope`` via :func:`parsed_estimate_to_scope` (preserving the\nMISC/BIDITM faithful-demotion), then reuses the scope-gen ESX path\n(``adapt_scope_for_writer`` → writer + Decision-D code lookup).\n\nTHIS IS THE CHARGED STEP (2026-06-16): the import preflight is free, the\ncost is collected here, priced by line count — estimates ≤ FREE_LINE_THRESHOLD\nare free, larger ones cost CREDITS_PER_CONVERSION_OVER credits. The charge is\nidempotent on the import ref, so re-exporting the same parse never\ndouble-charges; a generation failure refunds. Members are never metered.\nOwnership is enforced by the user-keyed load (404 on someone else's hash).\nThe Sketch add-on is a member feature: role-less users get list-mode exports\nregardless of the request flag.\n\nReturns the same JSON shape as ``/generate-from-pdf/json`` (filename,\nesx_b64, report, scope_preview, run_ref).","operationId":"generate_from_parse_api_v1_esx_generate_from_parse_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateFromParseRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateFromScopeJsonResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/roof/preview":{"post":{"tags":["roof"],"summary":"Roof Preview","description":"Render an uploaded roof report to a 2D plan + totals.\n\nArgs:\n    file: An EagleView (``EAGLEVIEW_EXPORT``) or Hover (``DATA_EXPORT``) roof\n        ``.xml`` report.\n\nReturns:\n    RoofPreviewResponse: The inline plan SVG plus computed roof area, plan\n    extent, edge lengths by type, and the published-totals cross-check.\n\nRaises:\n    HTTPException: 400 for a non-XML upload, 422 for unparseable XML or a file\n    with no roof geometry.","operationId":"roof_preview_api_v1_roof_preview_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_roof_preview_api_v1_roof_preview_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoofPreviewResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/roof/emit":{"post":{"tags":["roof"],"summary":"Roof Emit From Upload","description":"Emit an importable editable ESX from an uploaded EagleView/Hover roof XML.\n\nArgs:\n    file: An EagleView/Hover roof ``.xml`` report.\n    project_name: Optional ESX project name (defaults to the file stem).\n\nReturns:\n    RoofEmitResponse: the base64 ESX + the emitted roof summary + self-check.\n\nRaises:\n    HTTPException: 400 non-XML, 422 unparseable / no roof geometry.","operationId":"roof_emit_from_upload_api_v1_roof_emit_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_roof_emit_from_upload_api_v1_roof_emit_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoofEmitResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/roof/emit-from-description":{"post":{"tags":["roof"],"summary":"Roof Emit From Description","description":"Emit an importable editable ESX from a free-text roof description.\n\nArgs:\n    req: ``{description, project_name?}`` — e.g. \"6/12 gable 40x24\".\n\nReturns:\n    RoofEmitResponse: the base64 ESX + emitted roof summary + self-check.\n\nRaises:\n    HTTPException: 422 when the description has no parseable dimensions.","operationId":"roof_emit_from_description_api_v1_roof_emit_from_description_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoofDescriptionRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoofEmitResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/roof/eagleview-to-esx":{"post":{"tags":["roof"],"summary":"Eagleview To Esx","description":"Parse an EagleView XML roof report and return a native editable ESX.\n\nThe ESX contains a multi-piece gable sketch (one piece per RIDGE edge) and a\npre-populated roofing scope (shingles, drip edge, valley metal, ridge/hip cap)\nkeyed to the EagleView-published measurements.\n\nArgs:\n    file: EagleView ``.xml`` roof report.\n\nReturns:\n    Binary ESX (``application/octet-stream``) with a ``Content-Disposition``\n    attachment header and an ``X-Roof-Import-Report`` JSON header.\n\nRaises:\n    400: When the uploaded file is not ``.xml``.\n    422: When the XML cannot be parsed or contains no ROOF faces.\n    500: When the ESX emitter fails unexpectedly.","operationId":"eagleview_to_esx_api_v1_roof_eagleview_to_esx_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_eagleview_to_esx_api_v1_roof_eagleview_to_esx_post"}}},"required":true},"responses":{"200":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/roof/interview/measurements/parse":{"post":{"tags":["roof"],"summary":"Parse Measurement Report","description":"Parse an uploaded EagleView roof-report XML into ``RoofMeasurements``.\n\nThe parsed measurements are the product; persistence of the source XML\n(B-739, roof-reports bucket) is best-effort — a storage outage must not\nblock the interview, so on failure the response carries the filename and\n``stored=False``.","operationId":"parse_measurement_report_api_v1_roof_interview_measurements_parse_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_parse_measurement_report_api_v1_roof_interview_measurements_parse_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoofMeasurementsParseResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/roof/interview":{"get":{"tags":["roof"],"summary":"Get Interview Definition","description":"The full roof interview definition (renderer walks /preview instead).","operationId":"get_interview_definition_api_v1_roof_interview_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Interview Definition Api V1 Roof Interview Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/roof/interview/preview":{"post":{"tags":["roof"],"summary":"Preview Roof Scope","description":"Run the interview + generator against answers-so-far.\n\nAlways returns the visible question list so the UI can re-render the\nform; ``result`` is null with a structured ``error`` when the selected\nsystem can't generate yet (repair mode, non-asphalt families).","operationId":"preview_roof_scope_api_v1_roof_interview_preview_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoofInterviewPreviewRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoofInterviewPreviewResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/me/bootstrap":{"post":{"tags":["me"],"summary":"Bootstrap","description":"Idempotent first-login setup.\n\nRecords signup metadata, then grants the one-time signup credit INSTANTLY\nto the account balance for every non-disposable user — no email-verification\ngate, no redeemable code. The old flow (verify the email, THEN open a second\nemail and redeem an AT-xxxx code) killed activation: email/password signups\nwho never clicked the Firebase verification link were stranded with zero\ncredits, and even verified users had to copy-paste a code by hand (B-368).\nDisposable emails are still blocked. ``signup_grant`` is idempotent (ref =\nuser_id), so calling it on every bootstrap only ever credits once.","operationId":"bootstrap_api_v1_me_bootstrap_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BootstrapResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/me/redeem-code":{"post":{"tags":["me"],"summary":"Redeem Code Route","description":"Redeem a one-time credit code for the authenticated user.\n\nMaps the atomic DB redeem statuses to HTTP: ok / already_redeemed_self\nare 200 (self-retry is friendly-idempotent), not_found / expired are 404,\na code consumed by ANOTHER account is 409. Repeated failures are\nthrottled (429) — codes are bearer instruments.","operationId":"redeem_code_route_api_v1_me_redeem_code_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RedeemCodeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RedeemCodeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/me/pending-codes":{"get":{"tags":["me"],"summary":"Pending Codes","description":"Unredeemed signup/purchase codes issued to the caller's verified email.\n\nThe in-app recovery path: a buyer who dismissed the success banner (or\nwhose code email bounced / email infra isn't configured) can always see\nand redeem their paid codes here. Feedback-reward codes are EXCLUDED —\nthose are delivered by the founder manually after review.","operationId":"pending_codes_api_v1_me_pending_codes_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PendingCode"},"title":"Response Pending Codes Api V1 Me Pending Codes Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/me/feedback":{"post":{"tags":["me"],"summary":"Submit Feedback","description":"Store feedback and email it (plus a 1-credit reward code) to the founder.\n\nThe reward code goes to FEEDBACK_INBOX — the founder reviews the feedback\nand forwards the code manually, which is the real quality gate. The user\nis told to expect the code by email within 24 hours. Email failures never\nfail the submission (the code is recoverable via /admin/codes).","operationId":"submit_feedback_api_v1_me_feedback_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeedbackRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeedbackResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/me/accept-agreement":{"post":{"tags":["me"],"summary":"Accept Agreement","description":"Record acceptance of the current alpha agreement version (idempotent).","operationId":"accept_agreement_api_v1_me_accept_agreement_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgreementResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/me/credits":{"get":{"tags":["me"],"summary":"Credits","description":"Current balance + recent ledger + agreement status.","operationId":"credits_api_v1_me_credits_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/me/entitlements":{"get":{"tags":["me"],"summary":"Entitlements","description":"The caller's resolved subscription tier + caps/flags.\n\n``enforced`` reflects the default-open master switch so the UI can preview\ncaps without yet hard-blocking when the mechanism ships OFF.","operationId":"entitlements_api_v1_me_entitlements_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntitlementsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/me/usage":{"get":{"tags":["me"],"summary":"Usage","description":"The caller's metered line usage vs. their tier cap (all-time window).","operationId":"usage_api_v1_me_usage_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/billing/packs":{"get":{"tags":["billing"],"summary":"List Packs","description":"Public price list. ``enabled`` is False when Stripe isn't configured on this\nbackend, so the UI can hide the buy flow (graceful degradation on a deploy\nwhose STRIPE_* secrets aren't set yet) instead of showing buttons that 503.","operationId":"list_packs_api_v1_billing_packs_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PacksResponse"}}}}}}},"/api/v1/billing/config":{"get":{"tags":["billing"],"summary":"Billing Config","description":"Everything the pricing page + credits explainer need, from config.\n\nLets the frontend render tiers, packs, the per-conversion credit rules, and\nthe founder promo code WITHOUT hardcoding any number or price id. ``enabled``\nmirrors ``/packs`` (False when Stripe isn't configured here).","operationId":"billing_config_api_v1_billing_config_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingConfigResponse"}}}}}}},"/api/v1/billing/create-checkout-session":{"post":{"tags":["billing"],"summary":"Create Checkout Session","description":"Create a Stripe Checkout Session for a credit pack (catalog-priced).\n\nArgs:\n    body (CheckoutRequest): Carries the chosen ``pack_id``.\n    user (Dict): The authenticated user (Firebase identity).\n\nReturns:\n    CheckoutResponse: The hosted Stripe Checkout URL to redirect to.\n\nRaises:\n    HTTPException: 400 for an unknown pack; 503 if billing is unconfigured.","operationId":"create_checkout_session_api_v1_billing_create_checkout_session_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/billing/session/{session_id}/claim":{"get":{"tags":["billing"],"summary":"Claim Session Code","description":"Hand the buyer their purchase code right on the success page.\n\nVerifies the checkout session with Stripe directly (paid + belongs to the\ncaller), mints the code idempotently on the session id — whichever of\nwebhook/claim runs first wins, the other returns the same code — and\nreturns it so the UI can offer one-click redeem without waiting for the\nbackup email.\n\nRaises:\n    HTTPException: 503 unconfigured; 404 unknown session or a session\n        that belongs to another account (existence not revealed).","operationId":"claim_session_code_api_v1_billing_session__session_id__claim_get","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/billing/create-subscription-session":{"post":{"tags":["billing"],"summary":"Create Subscription Session","description":"Create a Stripe Checkout Session for a recurring subscription.\n\nMaps (tier, interval) → a Stripe Price id from config (defaults = the LIVE\ncatalog, decision-0015). Founder/promo gating is load-bearing:\n\n- annual + founders available → AUTO-APPLY the founder coupon (50% off) via\n  ``discounts`` and NO ``allow_promotion_codes`` (the two are mutually\n  exclusive in Stripe); the buyer sees the discounted price with nothing to\n  type. The 20-spot cap is enforced by ``FOUNDERS_AVAILABLE``, not the coupon.\n- annual + founders NOT available → ``allow_promotion_codes=True`` (standard\n  annual price; any future promo can still be typed), no founder discount.\n- month → keep the public funnel's auto-applied intro coupon via\n  ``discounts`` (when configured); no ``allow_promotion_codes``.\n\nArgs:\n    body (SubscribeRequest): Carries the chosen ``tier`` and ``interval``.\n    user (Dict): The authenticated user.\n\nReturns:\n    CheckoutResponse: The hosted Stripe Checkout URL.\n\nRaises:\n    HTTPException: 400 for an unknown tier; 503 if billing is unconfigured.","operationId":"create_subscription_session_api_v1_billing_create_subscription_session_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscribeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/billing/create-portal-session":{"post":{"tags":["billing"],"summary":"Create Portal Session","description":"Create a Stripe Billing Portal session so the user can manage/cancel.\n\nArgs:\n    body (PortalRequest): Carries the Stripe ``customer_id``.\n    user (Dict): The authenticated user (auth required).\n\nReturns:\n    CheckoutResponse: The hosted billing-portal URL.\n\nRaises:\n    HTTPException: 503 if billing is unconfigured.","operationId":"create_portal_session_api_v1_billing_create_portal_session_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PortalRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/billing/stripe/webhook":{"post":{"tags":["billing"],"summary":"Stripe Webhook","description":"Receive Stripe webhooks; credit the ledger on a completed checkout.\n\nUnauthenticated by necessity (Stripe calls it), so the signature MUST be\nverified. Crediting is idempotent on the Stripe session id (the ledger\n``ref``), so duplicate deliveries never double-credit.\n\nReturns:\n    dict: ``{\"received\": True}`` (200) once handled.\n\nRaises:\n    HTTPException: 400 on a bad/forged signature or unparseable payload;\n        503 if the webhook secret is not configured.","operationId":"stripe_webhook_api_v1_billing_stripe_webhook_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/auth/test-auth":{"get":{"tags":["auth-test"],"summary":"Test Auth","description":"Test authentication token verification.","operationId":"test_auth_api_v1_auth_test_auth_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/calc/crane":{"post":{"tags":["calculators"],"summary":"Calc Crane","description":"C1 Crane Estimator — sized, durationed, dollared, cited.","operationId":"calc_crane_api_v1_calc_crane_post","parameters":[{"name":"regional_adjustment_pct","in":"query","required":false,"schema":{"type":"number","default":0.0,"title":"Regional Adjustment Pct"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CraneInputs"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Calc Crane Api V1 Calc Crane Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/calc/scaffold":{"post":{"tags":["calculators"],"summary":"Calc Scaffold","description":"C2 Scaffold Calculator.","operationId":"calc_scaffold_api_v1_calc_scaffold_post","parameters":[{"name":"regional_adjustment_pct","in":"query","required":false,"schema":{"type":"number","default":0.0,"title":"Regional Adjustment Pct"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScaffoldInputs"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Calc Scaffold Api V1 Calc Scaffold Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/calc/lift":{"post":{"tags":["calculators"],"summary":"Calc Lift","description":"C3 Aerial Lift Selector.","operationId":"calc_lift_api_v1_calc_lift_post","parameters":[{"name":"regional_adjustment_pct","in":"query","required":false,"schema":{"type":"number","default":0.0,"title":"Regional Adjustment Pct"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LiftInputs"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Calc Lift Api V1 Calc Lift Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/calc/water-mitigation":{"post":{"tags":["calculators"],"summary":"Calc Water Mitigation","description":"C4 Water Mitigation Equipment (IICRC S500).","operationId":"calc_water_mitigation_api_v1_calc_water_mitigation_post","parameters":[{"name":"regional_adjustment_pct","in":"query","required":false,"schema":{"type":"number","default":0.0,"title":"Regional Adjustment Pct"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WaterMitInputs"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Calc Water Mitigation Api V1 Calc Water Mitigation Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/calc/drywall-room":{"post":{"tags":["calculators"],"summary":"Calc Drywall Room","description":"C5 Drywall Room.","operationId":"calc_drywall_room_api_v1_calc_drywall_room_post","parameters":[{"name":"regional_adjustment_pct","in":"query","required":false,"schema":{"type":"number","default":0.0,"title":"Regional Adjustment Pct"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DrywallRoomInputs"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Calc Drywall Room Api V1 Calc Drywall Room Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/calc/debris":{"post":{"tags":["calculators"],"summary":"Calc Debris","description":"C6 Debris / Dumpster.","operationId":"calc_debris_api_v1_calc_debris_post","parameters":[{"name":"regional_adjustment_pct","in":"query","required":false,"schema":{"type":"number","default":0.0,"title":"Regional Adjustment Pct"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DebrisInputs"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Calc Debris Api V1 Calc Debris Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/calc/drying-power":{"post":{"tags":["calculators"],"summary":"Calc Drying Power","description":"C7 Drying Power — can the panel run this drying setup, or temp power?\n\nAccepts an explicit equipment list or a water-mitigation package to carry\nequipment from (the panel integration point in the water-mit tool output).","operationId":"calc_drying_power_api_v1_calc_drying_power_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DryingPowerRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Calc Drying Power Api V1 Calc Drying Power Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/calc/scenario/{calculator}/graph":{"get":{"tags":["calculators"],"summary":"Get Graph","description":"The question graph the frontend walks generically.","operationId":"get_graph_api_v1_calc_scenario__calculator__graph_get","parameters":[{"name":"calculator","in":"path","required":true,"schema":{"type":"string","title":"Calculator"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Graph Api V1 Calc Scenario  Calculator  Graph Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/calc/scenario/{calculator}":{"post":{"tags":["calculators"],"summary":"Run Scenario","description":"Interview answers -> derived engineering inputs -> calculator package.\n\nDispatches by calculator name (B-666); the crane path is byte-compatible\nwith the prior dedicated `/crane` route (same URL, same response shape).","operationId":"run_scenario_api_v1_calc_scenario__calculator__post","parameters":[{"name":"calculator","in":"path","required":true,"schema":{"type":"string","title":"Calculator"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScenarioRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Run Scenario Api V1 Calc Scenario  Calculator  Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/calc/scenario/{calculator}/parse":{"post":{"tags":["calculators"],"summary":"Parse Job Text","description":"Free-text intake (S8.4): parse only, never compute, never guess.\n\nB-722-parse: gated behind FREE_TEXT_PARSE_ENABLED (default OFF) until\nthe founder verifies the evidence_span determinism fix live — while\noff, 503s the same way a parse failure does, so the client falls back\nto the guided interview.","operationId":"parse_job_text_api_v1_calc_scenario__calculator__parse_post","parameters":[{"name":"calculator","in":"path","required":true,"schema":{"type":"string","title":"Calculator"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParseRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Parse Job Text Api V1 Calc Scenario  Calculator  Parse Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/ping":{"get":{"tags":["partner-api"],"summary":"Authenticated health check","description":"Confirms your X-API-Key is valid and reports which environment (live/test) it maps to. Use this as the first call in any new integration.","operationId":"ping_v1_ping_get","parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Key is valid.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Ping V1 Ping Get"},"example":{"status":"ok","partner":"Acme Adjusting","environment":"test"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"example":{"error":{"code":"invalid_api_key","message":"API key is invalid or revoked.","request_id":"b3f1c2..."}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/conversions":{"post":{"tags":["partner-api"],"summary":"Start an async PDF -> ESX conversion","description":"Uploads an estimate PDF and enqueues an asynchronous conversion job. Poll GET /v1/conversions/{job_id} (or register a webhook) until the job reaches 'succeeded' or 'failed'. See the integration guide (docs/integration-guide.md) for the full walkthrough.","operationId":"create_conversion_v1_conversions_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency-Key"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_create_conversion_v1_conversions_post"}}}},"responses":{"202":{"description":"Job accepted and queued.","content":{"application/json":{"schema":{},"example":{"job_id":"b3f1c2...","status":"queued"}}}},"400":{"description":"invalid_file_type | unsupported_price_list | unsupported_output_format | feature_not_enabled | empty_file"},"413":{"description":"file_too_large"},"429":{"description":"too_many_active_jobs | daily_limit_exceeded"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/conversions/{job_id}":{"get":{"tags":["partner-api"],"summary":"Get conversion job status / result","description":"Returns a job belonging to the calling partner only (404 otherwise, never distinguishing 'not yours' from 'does not exist'). On success, includes a fresh time-limited esx_url. On failure, an error envelope.","operationId":"get_conversion_v1_conversions__job_id__get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"queued | processing | succeeded | failed","content":{"application/json":{"schema":{},"example":{"job_id":"b3f1c2...","status":"succeeded","created_at":"2026-07-09T12:00:00Z","summary":{"room_count":14,"line_item_count":132,"total_rcv":48213.44,"warnings":[]},"esx_url":"https://.../job.esx?sig=...","esx_expired":false}}}},"404":{"description":"not_found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/intelligent-scope/process-unified":{"post":{"tags":["intelligent-scope","Intelligent Scope"],"summary":"Process unified payload for AI scope generation","description":"Accepts a unified payload with notes, photos, and context to generate structured scope with AI suggestions.","operationId":"process_unified_payload_api_v1_intelligent_scope_process_unified_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnifiedPayload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StructuredScopeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/intelligent-scope/generate":{"post":{"tags":["intelligent-scope","Intelligent Scope"],"summary":"Generate a detailed scope from field notes","description":"Processes field notes through the multi-agent pipeline to generate a detailed, compliant scope.","operationId":"generate_scope_api_v1_intelligent_scope_generate_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__api__routes__intelligent_scope__ScopeGenerationRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__api__routes__intelligent_scope__ScopeGenerationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/intelligent-scope/validate/scope":{"post":{"tags":["intelligent-scope","Intelligent Scope"],"summary":"Validate a scope for accuracy","description":"Runs a provided scope through the Accuracy Validator to check for hallucinations and inconsistencies.","operationId":"validate_scope_api_v1_intelligent_scope_validate_scope_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeValidationRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/intelligent-scope/profiles/me":{"get":{"tags":["intelligent-scope","Intelligent Scope"],"summary":"Get current user's preferences","description":"Fetches the preferences for the currently authenticated user.\n\nReturns the default preference set for users who have never saved any, so\nthe Settings page always has a usable object rather than a 404.","operationId":"get_my_preferences_api_v1_intelligent_scope_profiles_me_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserPreferences-Output"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/intelligent-scope/profiles/me/scope-config":{"put":{"tags":["intelligent-scope","Intelligent Scope"],"summary":"Update user's scope configuration","description":"Updates the scope structure configuration for the currently authenticated user.","operationId":"update_my_scope_config_api_v1_intelligent_scope_profiles_me_scope_config_put","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeConfig-Input"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserPreferences-Output"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/intelligent-scope/profiles/me/generation":{"put":{"tags":["intelligent-scope","Intelligent Scope"],"summary":"Update user's scope-generation defaults","description":"Updates the generation defaults (damage type, jurisdiction, helpful mode,\nCat-3 default) applied to new scope-generation runs.","operationId":"update_my_generation_prefs_api_v1_intelligent_scope_profiles_me_generation_put","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerationPreferences"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserPreferences-Output"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/intelligent-scope/profiles/categories":{"get":{"tags":["intelligent-scope","Intelligent Scope"],"summary":"List all category profiles","description":"Lists all available category profiles (e.g., carriers, contractors).","operationId":"list_categories_api_v1_intelligent_scope_profiles_categories_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CategoryProfile"},"title":"Response List Categories Api V1 Intelligent Scope Profiles Categories Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/intelligent-scope/profiles/carriers":{"get":{"tags":["intelligent-scope","Intelligent Scope"],"summary":"List all carrier rulesets","description":"Lists all available insurance carrier rulesets.","operationId":"list_carrier_rulesets_api_v1_intelligent_scope_profiles_carriers_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CarrierRuleset"},"title":"Response List Carrier Rulesets Api V1 Intelligent Scope Profiles Carriers Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/intelligent-scope/xactimate/codes/search":{"get":{"tags":["intelligent-scope","Intelligent Scope"],"summary":"Search for Xactimate codes","description":"Searches the Xactimate code database by query and optional category.","operationId":"search_xactimate_codes_api_v1_intelligent_scope_xactimate_codes_search_get","parameters":[{"name":"query","in":"query","required":true,"schema":{"type":"string","title":"Query"}},{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":10,"title":"Limit"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CodeSearchResult"},"title":"Response Search Xactimate Codes Api V1 Intelligent Scope Xactimate Codes Search Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/intelligent-scope/xactimate/codes/import-csv":{"post":{"tags":["intelligent-scope","Intelligent Scope"],"summary":"Import Xactimate codes from a CSV file","description":"Bulk-imports Xactimate codes from a CSV file. Admin-only endpoint.","operationId":"import_xactimate_codes_from_csv_api_v1_intelligent_scope_xactimate_codes_import_csv_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_import_xactimate_codes_from_csv_api_v1_intelligent_scope_xactimate_codes_import_csv_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CSVCodesImportResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/intelligent-scope/xactimate/rules":{"get":{"tags":["intelligent-scope","Intelligent Scope"],"summary":"List all Xactimate rules","description":"Retrieves all active Xactimate business logic rules.","operationId":"list_xactimate_rules_api_v1_intelligent_scope_xactimate_rules_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/XactimateRule"},"title":"Response List Xactimate Rules Api V1 Intelligent Scope Xactimate Rules Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/intelligent-scope/training/ingest/pdf":{"post":{"tags":["intelligent-scope","Intelligent Scope"],"summary":"Ingest a sample scope from a PDF file","description":"Uploads a sample insurance scope in PDF format to be ingested as training data.","operationId":"ingest_pdf_scope_api_v1_intelligent_scope_training_ingest_pdf_post","parameters":[{"name":"source_reference","in":"query","required":false,"schema":{"type":"string","default":"uploaded_pdf","title":"Source Reference"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_ingest_pdf_scope_api_v1_intelligent_scope_training_ingest_pdf_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/intelligent-scope/training/stats":{"get":{"tags":["intelligent-scope","Intelligent Scope"],"summary":"Get training data statistics","description":"Retrieves statistics about the current state of the training data.","operationId":"get_training_data_stats_api_v1_intelligent_scope_training_stats_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrainingDataStats"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/knowledge/sources":{"get":{"tags":["knowledge","rag"],"summary":"List Knowledge Sources","description":"List all knowledge sources with statistics.","operationId":"list_knowledge_sources_api_v1_knowledge_sources_get","parameters":[{"name":"active_only","in":"query","required":false,"schema":{"type":"boolean","description":"Only return active sources","default":false,"title":"Active Only"},"description":"Only return active sources"},{"name":"trade_category","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by trade category","title":"Trade Category"},"description":"Filter by trade category"},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SourceResponse"},"title":"Response List Knowledge Sources Api V1 Knowledge Sources Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["knowledge","rag"],"summary":"Create Knowledge Source","description":"Create a new knowledge source.","operationId":"create_knowledge_source_api_v1_knowledge_sources_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceCreateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string","format":"uuid"},"title":"Response Create Knowledge Source Api V1 Knowledge Sources Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/knowledge/sources/{source_id}/disable":{"post":{"tags":["knowledge","rag"],"summary":"Disable Knowledge Source","description":"Disable a knowledge source (stops it from appearing in search results).","operationId":"disable_knowledge_source_api_v1_knowledge_sources__source_id__disable_post","parameters":[{"name":"source_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Source Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/knowledge/sources/{source_id}/enable":{"post":{"tags":["knowledge","rag"],"summary":"Enable Knowledge Source","description":"Re-enable a knowledge source.","operationId":"enable_knowledge_source_api_v1_knowledge_sources__source_id__enable_post","parameters":[{"name":"source_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Source Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/knowledge/crawl-targets":{"get":{"tags":["knowledge","rag"],"summary":"Get Crawl Targets","description":"Get available predefined crawl targets.","operationId":"get_crawl_targets_api_v1_knowledge_crawl_targets_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/knowledge/sources/{source_id}/crawl":{"post":{"tags":["knowledge","rag"],"summary":"Start Crawl","description":"Start crawling a knowledge source.","operationId":"start_crawl_api_v1_knowledge_sources__source_id__crawl_post","parameters":[{"name":"source_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Source Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrawlRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/knowledge/search":{"post":{"tags":["knowledge","rag"],"summary":"Search Knowledge","description":"Search the knowledge base with semantic similarity.","operationId":"search_knowledge_api_v1_knowledge_search_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/knowledge/search-preview":{"get":{"tags":["knowledge","rag"],"summary":"Search Preview","description":"Preview search results for quality testing.","operationId":"search_preview_api_v1_knowledge_search_preview_get","parameters":[{"name":"query","in":"query","required":true,"schema":{"type":"string","description":"Test search query","title":"Query"},"description":"Test search query"},{"name":"trade_category","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by trade category","title":"Trade Category"},"description":"Filter by trade category"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":20,"minimum":1,"default":5,"title":"Limit"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/knowledge/chunks/{chunk_id}":{"put":{"tags":["knowledge","rag"],"summary":"Update Knowledge Chunk","description":"Update expert verification and confidence for a knowledge chunk.","operationId":"update_knowledge_chunk_api_v1_knowledge_chunks__chunk_id__put","parameters":[{"name":"chunk_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Chunk Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChunkUpdateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["knowledge","rag"],"summary":"Delete Knowledge Chunk","description":"Delete a knowledge chunk from the database.","operationId":"delete_knowledge_chunk_api_v1_knowledge_chunks__chunk_id__delete","parameters":[{"name":"chunk_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Chunk Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/knowledge/statistics":{"get":{"tags":["knowledge","rag"],"summary":"Get Knowledge Statistics","description":"Get comprehensive statistics about the knowledge base.","operationId":"get_knowledge_statistics_api_v1_knowledge_statistics_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatisticsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/knowledge/maintenance/cleanup-logs":{"post":{"tags":["knowledge","rag"],"summary":"Cleanup Search Logs","description":"Clean up old search logs for maintenance.","operationId":"cleanup_search_logs_api_v1_knowledge_maintenance_cleanup_logs_post","parameters":[{"name":"days_to_keep","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"description":"Number of days to keep search logs","default":30,"title":"Days To Keep"},"description":"Number of days to keep search logs"},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/analysis/stats":{"get":{"tags":["analysis"],"summary":"Get Stats","description":"Get corpus statistics from the analysis engine.\n\nReturns:\n    Summary statistics about the loaded analysis data.","operationId":"get_stats_api_v1_analysis_stats_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/analysis/codes/top":{"get":{"tags":["analysis"],"summary":"Get Top Codes","description":"Get the most frequently used Xactimate codes.\n\nArgs:\n    n: Number of codes to return (default 50, max 500).\n\nReturns:\n    Top codes sorted by occurrence count.","operationId":"get_top_codes_api_v1_analysis_codes_top_get","parameters":[{"name":"n","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"description":"Number of top codes to return","default":50,"title":"N"},"description":"Number of top codes to return"},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TopCodesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/analysis/codes/{xact_code}":{"get":{"tags":["analysis"],"summary":"Get Code Profile","description":"Look up a specific Xactimate code profile.\n\nArgs:\n    xact_code: The code to look up (e.g., 'PNT SP2'). URL-encode spaces as %20.\n\nReturns:\n    The code's learned profile.\n\nRaises:\n    HTTPException: 404 if code is not found.","operationId":"get_code_profile_api_v1_analysis_codes__xact_code__get","parameters":[{"name":"xact_code","in":"path","required":true,"schema":{"type":"string","title":"Xact Code"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeProfileResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/analysis/companions/{xact_code}":{"get":{"tags":["analysis"],"summary":"Get Companions","description":"Find always-write companion items for a given code.\n\nArgs:\n    xact_code: The trigger code (e.g., 'DRY 5/8-'). URL-encode spaces as %20.\n    min_confidence: Minimum P(companion|trigger) threshold.\n\nReturns:\n    Companion rules sorted by confidence.","operationId":"get_companions_api_v1_analysis_companions__xact_code__get","parameters":[{"name":"xact_code","in":"path","required":true,"schema":{"type":"string","title":"Xact Code"}},{"name":"min_confidence","in":"query","required":false,"schema":{"type":"number","maximum":1.0,"minimum":0.0,"description":"Minimum confidence threshold","default":0.5,"title":"Min Confidence"},"description":"Minimum confidence threshold"},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanionsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/analysis/room-template/{room_type}":{"get":{"tags":["analysis"],"summary":"Get Room Template","description":"Get the learned scope template for a room type.\n\nArgs:\n    room_type: Canonical room type (kitchen, bedroom, roof, etc.).\n    damage_type: Optional damage type filter.\n\nReturns:\n    The room template with typical line items.\n\nRaises:\n    HTTPException: 404 if no template found for this room type.","operationId":"get_room_template_api_v1_analysis_room_template__room_type__get","parameters":[{"name":"room_type","in":"path","required":true,"schema":{"type":"string","title":"Room Type"}},{"name":"damage_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Damage type filter (hurricane, flood, hail, etc.)","title":"Damage Type"},"description":"Damage type filter (hurricane, flood, hail, etc.)"},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoomTemplateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/analysis/suggest/{room_type}":{"get":{"tags":["analysis"],"summary":"Suggest Scope","description":"Suggest scope items for a room based on learned patterns.\n\nArgs:\n    room_type: Canonical room type.\n    damage_type: Optional damage type filter.\n    min_frequency: Minimum frequency to include (0.3 = 30% of rooms).\n\nReturns:\n    Suggested items with companions, sorted by frequency.","operationId":"suggest_scope_api_v1_analysis_suggest__room_type__get","parameters":[{"name":"room_type","in":"path","required":true,"schema":{"type":"string","title":"Room Type"}},{"name":"damage_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Damage type filter","title":"Damage Type"},"description":"Damage type filter"},{"name":"min_frequency","in":"query","required":false,"schema":{"type":"number","maximum":1.0,"minimum":0.0,"description":"Minimum item frequency threshold","default":0.3,"title":"Min Frequency"},"description":"Minimum item frequency threshold"},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuggestResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/analysis/room-types":{"get":{"tags":["analysis"],"summary":"List Room Types","description":"List available room types with template counts.\n\nReturns:\n    All room types that have learned templates.","operationId":"list_room_types_api_v1_analysis_room_types_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoomTypesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/scope/generate":{"post":{"tags":["scope-generation"],"summary":"Generate Scope","description":"Generate a scope from field notes via the unified scope engine.\n\nRoutes through scope_engine.pipeline.generate with existing_scope=None\n(fresh generation). The rules engine fires on the extracted facts; every\ncode is verified against the canonical catalog. Items the rules don't cover\nare surfaced as UNVERIFIED warnings rather than silently dropped (RULE-001).","operationId":"generate_scope_api_v1_scope_generate_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__api__routes__scope__ScopeGenerationRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__api__routes__scope__ScopeGenerationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/scope/generate/stream":{"post":{"tags":["scope-generation"],"summary":"Generate Scope Stream","description":"Stream scope generation as Server-Sent Events via the unified engine.\n\nEmits stage events during key pipeline steps, then a complete event with\nthe same payload as /generate. Now uses scope_engine.pipeline (old\norchestrator retired).","operationId":"generate_scope_stream_api_v1_scope_generate_stream_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__api__routes__scope__ScopeGenerationRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/scope/from-transcription":{"post":{"tags":["scope-generation"],"summary":"Scope From Transcription","description":"Generate a scope from audio transcription.\n\nCombines any provided field notes with audio transcription text.\nThe transcription is typically produced by the existing\nFaster-Whisper transcription service.","operationId":"scope_from_transcription_api_v1_scope_from_transcription_post","parameters":[{"name":"field_notes","in":"query","required":false,"schema":{"type":"string","default":"","title":"Field Notes"}},{"name":"audio_transcription","in":"query","required":false,"schema":{"type":"string","default":"","title":"Audio Transcription"}},{"name":"property_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Property Type"}},{"name":"damage_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Damage Type"}},{"name":"jurisdiction","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jurisdiction"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__api__routes__scope__ScopeGenerationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/scope/generate-room":{"post":{"tags":["scope-generation"],"summary":"Generate Room Scope","description":"Generate scope for a single room from a damage description.\n\nBuilds a PipelineRequest from the room-level fields and runs\nthe full agent pipeline. If helpful_mode is True, also returns\nchecklist prompts for elements not mentioned in the description.\n\nArgs:\n    request: Per-room scope generation request.\n\nReturns:\n    RoomScopeDetailResponse with room scope, prompts, and metadata.","operationId":"generate_room_scope_api_v1_scope_generate_room_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoomScopeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoomScopeDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/scope/checklist/{room_type}":{"get":{"tags":["scope-generation"],"summary":"Get Checklist","description":"Get the full room-adaptive checklist for a room type.\n\nArgs:\n    room_type: Canonical room type (e.g., 'kitchen', 'bathroom').\n\nReturns:\n    Dict with 'elements' list. Falls back to 'other' if unknown.","operationId":"get_checklist_api_v1_scope_checklist__room_type__get","parameters":[{"name":"room_type","in":"path","required":true,"schema":{"type":"string","title":"Room Type"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/scope/checklist-prompts":{"post":{"tags":["scope-generation"],"summary":"Get Checklist Prompts","description":"Get unmentioned checklist elements for a room description.\n\nFilters the room checklist to return only elements whose keywords\nwere NOT found in the description text.\n\nArgs:\n    request: Room type and description text.\n\nReturns:\n    List of unmentioned element dicts.","operationId":"get_checklist_prompts_api_v1_scope_checklist_prompts_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChecklistPromptRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/scope/supplement":{"post":{"tags":["scope-generation"],"summary":"Supplement Scope","description":"Supplement an existing scope with additional field notes.\n\nLoads the saved scope identified by scope_id, runs the unified scope engine\nwith the new notes, and returns ONLY the delta — line items that are missing\nfrom the existing scope given what the rules engine says should be present.\n\nThis and POST /generate both route through scope_engine.pipeline.generate.\nThe equivalence invariant: supplement(existing=empty) == fresh generate.","operationId":"supplement_scope_api_v1_scope_supplement_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplementRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__api__routes__scope__ScopeGenerationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/dictionary/lookup/{cat}/{sel}":{"get":{"tags":["dictionary"],"summary":"Lookup Code","description":"Return all codes matching a Cat+Sel pair.\n\nArgs:\n    cat: Category code (e.g., \"DRY\").\n    sel: Selector code (e.g., \"1/2\"). May contain slashes.\n\nReturns:\n    dict: codes list and count.","operationId":"lookup_code_api_v1_dictionary_lookup__cat___sel__get","parameters":[{"name":"cat","in":"path","required":true,"schema":{"type":"string","description":"Category code","title":"Cat"},"description":"Category code"},{"name":"sel","in":"path","required":true,"schema":{"type":"string","description":"Selector code (may contain slashes)","title":"Sel"},"description":"Selector code (may contain slashes)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/dictionary/validate":{"get":{"tags":["dictionary"],"summary":"Validate Code","description":"Validate a code against the canonical dictionary.\n\nArgs:\n    cat: Category code.\n    sel: Selector code.\n    activity: Optional activity text.\n\nReturns:\n    dict: Validation result with valid, match_type, and details.","operationId":"validate_code_api_v1_dictionary_validate_get","parameters":[{"name":"cat","in":"query","required":true,"schema":{"type":"string","description":"Category code","title":"Cat"},"description":"Category code"},{"name":"sel","in":"query","required":true,"schema":{"type":"string","description":"Selector code","title":"Sel"},"description":"Selector code"},{"name":"activity","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Activity text","title":"Activity"},"description":"Activity text"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/dictionary/search":{"get":{"tags":["dictionary"],"summary":"Search Descriptions","description":"Search code descriptions by substring.\n\nArgs:\n    q: Search query string (minimum 2 characters).\n\nReturns:\n    dict: results list and count.","operationId":"search_descriptions_api_v1_dictionary_search_get","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":2,"description":"Search query (min 2 chars)","title":"Q"},"description":"Search query (min 2 chars)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/dictionary/categories":{"get":{"tags":["dictionary"],"summary":"Get Categories","description":"Return list of categories with counts.\n\nReturns:\n    dict: categories list with cat, group_code, group_description, count.","operationId":"get_categories_api_v1_dictionary_categories_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/dictionary/selectors/{cat}":{"get":{"tags":["dictionary"],"summary":"List Selectors","description":"List every selector in a category with its description, unit, and actions.\n\nPowers the Review cascade picker's SEL dropdown (B-511): after the user\npicks a CAT, show the selectors under it, each with the human description,\nthe default unit (e.g. SF/LF), and the action symbols the item supports.\n\nArgs:\n    cat: Category code (e.g. \"DRY\", \"RFG\").\n\nReturns:\n    dict: ``{cat, selectors: [{sel, dsc, unit, actions}], count}``.","operationId":"list_selectors_api_v1_dictionary_selectors__cat__get","parameters":[{"name":"cat","in":"path","required":true,"schema":{"type":"string","description":"Category code, e.g. DRY","title":"Cat"},"description":"Category code, e.g. DRY"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/dictionary/actions/{cat}/{sel}":{"get":{"tags":["dictionary"],"summary":"List Actions","description":"List the action codes a given (cat, sel) item supports, with labels.\n\nPowers the cascade picker's ACTION dropdown (B-511): after CAT + SEL, show\nthe valid actions for THAT item (e.g. Replace/Remove/R&R), each a symbol +\nhuman label. Authoritative — derived from the item's ``supported_actions``.\n\nArgs:\n    cat: Category code.\n    sel: Selector code (may contain slashes).\n\nReturns:\n    dict: ``{cat, sel, actions: [{symbol, label}], count}``.","operationId":"list_actions_api_v1_dictionary_actions__cat___sel__get","parameters":[{"name":"cat","in":"path","required":true,"schema":{"type":"string","description":"Category code","title":"Cat"},"description":"Category code"},{"name":"sel","in":"path","required":true,"schema":{"type":"string","description":"Selector code (may contain slashes)","title":"Sel"},"description":"Selector code (may contain slashes)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/dictionary/stats":{"get":{"tags":["dictionary"],"summary":"Get Stats","description":"Return dictionary statistics.\n\nReturns:\n    dict: total_codes, loaded status, categories_count.","operationId":"get_stats_api_v1_dictionary_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/admin/upload":{"post":{"tags":["admin"],"summary":"Upload Files","description":"Accept multiple estimate files for batch processing.\n\nValidates file count, sizes, and extensions. Stages files to disk\nand kicks off background processing. Returns a batch_id for polling.\n\nArgs:\n    files: List of uploaded files (PDF, XLSX, XLS).\n    background_tasks: FastAPI background task scheduler.\n\nReturns:\n    UploadResponse with batch_id and accepted file count.\n\nRaises:\n    HTTPException 400: Invalid file type, count, or size.","operationId":"upload_files_api_v1_admin_upload_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_files_api_v1_admin_upload_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/upload/status/{batch_id}":{"get":{"tags":["admin"],"summary":"Get Upload Status","description":"Poll batch processing status by batch ID.\n\nArgs:\n    batch_id: UUID string from the upload response.\n\nReturns:\n    Full BatchStatus with per-file results and stats diff.\n\nRaises:\n    HTTPException 404: If batch_id is not found.","operationId":"get_upload_status_api_v1_admin_upload_status__batch_id__get","parameters":[{"name":"batch_id","in":"path","required":true,"schema":{"type":"string","title":"Batch Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchStatus"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/rules/":{"get":{"tags":["rules"],"summary":"List Rules","description":"List active rules with optional filters.\n\nArgs:\n    category: Optional category filter (flood, roofing, etc.).\n    damage_type: Optional damage type filter.\n\nReturns:\n    List of active rules.","operationId":"list_rules_api_v1_rules__get","parameters":[{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by rule category","title":"Category"},"description":"Filter by rule category"},{"name":"damage_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by damage type","title":"Damage Type"},"description":"Filter by damage type"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RuleListItem"},"title":"Response List Rules Api V1 Rules  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/rules/citations":{"get":{"tags":["rules"],"summary":"Get Citations","description":"Get all citations from active rules, grouped by source type.\n\nReturns:\n    Citations grouped by source type.","operationId":"get_citations_api_v1_rules_citations_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CitationsResponse"}}}}}}},"/api/v1/rules/general-conditions":{"get":{"tags":["rules"],"summary":"Get General Conditions","description":"Get general conditions suggestions based on project characteristics.\n\nArgs:\n    scope_item_count: Total number of scope items.\n    room_count: Number of rooms.\n    damage_type: Primary damage type.\n    is_commercial: Whether this is a commercial property.\n    has_multi_story: Whether the property is multi-story.\n    total_area_sf: Optional total affected area.\n\nReturns:\n    Suggested general conditions with typical ranges.","operationId":"get_general_conditions_api_v1_rules_general_conditions_get","parameters":[{"name":"scope_item_count","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Total scope items","default":0,"title":"Scope Item Count"},"description":"Total scope items"},{"name":"room_count","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Number of rooms","default":0,"title":"Room Count"},"description":"Number of rooms"},{"name":"damage_type","in":"query","required":false,"schema":{"type":"string","description":"Primary damage type","default":"general","title":"Damage Type"},"description":"Primary damage type"},{"name":"is_commercial","in":"query","required":false,"schema":{"type":"boolean","description":"Commercial property","default":false,"title":"Is Commercial"},"description":"Commercial property"},{"name":"has_multi_story","in":"query","required":false,"schema":{"type":"boolean","description":"Multi-story property","default":false,"title":"Has Multi Story"},"description":"Multi-story property"},{"name":"total_area_sf","in":"query","required":false,"schema":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}],"description":"Total area in SF","title":"Total Area Sf"},"description":"Total area in SF"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeneralConditionsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/rules/building-codes/{code_edition}/{section}":{"get":{"tags":["rules"],"summary":"Get Building Code","description":"Look up a building code section from the cache.\n\nArgs:\n    code_edition: Code edition (e.g., '2024 IRC').\n    section: Section number (e.g., 'R905.1.1').\n    jurisdiction: Optional jurisdiction filter.\n\nReturns:\n    Cached building code entry.\n\nRaises:\n    HTTPException: 404 if code section not found.","operationId":"get_building_code_api_v1_rules_building_codes__code_edition___section__get","parameters":[{"name":"code_edition","in":"path","required":true,"schema":{"type":"string","title":"Code Edition"}},{"name":"section","in":"path","required":true,"schema":{"type":"string","title":"Section"}},{"name":"jurisdiction","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Jurisdiction code","title":"Jurisdiction"},"description":"Jurisdiction code"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BuildingCodeEntry"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/rules/stats":{"get":{"tags":["rules"],"summary":"Get Stats","description":"Get rules system statistics.\n\nReturns:\n    Counts of rules, categories, sources, general conditions, and building codes.","operationId":"get_stats_api_v1_rules_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RulesStatsResponse"}}}}}}},"/api/v1/rules/evaluate":{"post":{"tags":["rules"],"summary":"Evaluate Rules","description":"Evaluate rules against a set of facts (for testing/debugging).\n\nArgs:\n    body: Facts dict, optional category filter, and max evaluation depth.\n\nReturns:\n    EvaluationResult with fired rules, citations, scope items, flags, suggestions.","operationId":"evaluate_rules_api_v1_rules_evaluate_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvaluateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvaluateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/rules/{rule_id}":{"get":{"tags":["rules"],"summary":"Get Rule","description":"Get full rule detail by ID.\n\nArgs:\n    rule_id: Rule UUID or name.\n\nReturns:\n    Full rule including conditions and actions.\n\nRaises:\n    HTTPException: 404 if rule not found.","operationId":"get_rule_api_v1_rules__rule_id__get","parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"type":"string","title":"Rule Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RuleDetail"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["rules"],"summary":"Update Rule","description":"Apply a partial update to a rule (PRP-004).\n\nRoles: editor, expert, super_admin. Other roles get 403.\n\nFlow:\n    1. Fetch current rule (404 if missing).\n    2. Build merged dict; validate against Pydantic Rule model (422 on fail).\n    3. Snapshot pre-update state into rule_versions.\n    4. Update rules row, bump version, invalidate cache.\n    5. Return updated detail.","operationId":"update_rule_api_v1_rules__rule_id__put","parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"type":"string","title":"Rule Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RuleUpdateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RuleDetail"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/rules/from_natural_language":{"post":{"tags":["rules","rule-authoring"],"summary":"From Natural Language","description":"Translate a plain-English description into a structured rule.\n\nDoes not persist. The caller (admin UI) reviews the rendered rule and\nsubmits a separate /save_with_render request once approved.\n\nArgs:\n    body: Translation request body.\n\nReturns:\n    FromNaturalLanguageResponse with the generated rule, plain-English\n    render, confidence, ambiguities, and warnings.\n\nRaises:\n    HTTPException 422: when the LLM output can't be coerced into a valid\n        rule, or when it references unverified Xactimate codes.","operationId":"from_natural_language_api_v1_rules_from_natural_language_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FromNaturalLanguageRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FromNaturalLanguageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/rules/save_with_render":{"post":{"tags":["rules","rule-authoring"],"summary":"Save With Render","description":"Persist a rule plus its cached plain-English render.\n\nUses the existing RulesRepository.upsert_rule path so we go through the\nsame validation and cache-invalidation logic the seed script uses.\n\nArgs:\n    body: Save request with the rule dict and its cached render.\n\nReturns:\n    SaveWithRenderResponse with the rule id and name.\n\nRaises:\n    HTTPException 400: when the rule dict is missing required fields.\n    HTTPException 500: on a database error.","operationId":"save_with_render_api_v1_rules_save_with_render_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveWithRenderRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveWithRenderResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/rules/{rule_id}/explain":{"post":{"tags":["rules","rule-authoring"],"summary":"Explain","description":"Return the plain-English explanation of a stored rule.\n\nCaches the result in the `plain_english_render` column. The first call for\na given rule hits the LLM; subsequent calls return the cached value\nuntil the rule changes or `force_refresh=true` is passed.\n\nArgs:\n    rule_id: Rule id or name.\n    force_refresh: When True, ignore the cached render and re-generate.\n\nReturns:\n    ExplainResponse with the plain-English text and a `from_cache` flag.","operationId":"explain_api_v1_rules__rule_id__explain_post","parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"type":"string","title":"Rule Id"}},{"name":"force_refresh","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Force Refresh"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExplainResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/rule-reviews/categories":{"get":{"tags":["rule-reviews"],"summary":"List Categories","description":"Return every rule category with per-reviewer progress for the caller.","operationId":"list_categories_api_v1_rule_reviews_categories_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CategoryProgress"},"title":"Response List Categories Api V1 Rule Reviews Categories Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/rule-reviews/rules":{"get":{"tags":["rule-reviews"],"summary":"List Rules For Review","description":"Return rules for a reviewer to process.\n\nDiscipline-matching rules surface first (is_discipline_match=True).\nAlready-reviewed rules carry the reviewer's prior decision so the\nUI can show their answer and allow changes.","operationId":"list_rules_for_review_api_v1_rule_reviews_rules_get","parameters":[{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by category","title":"Category"},"description":"Filter by category"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":100,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RuleForReview"},"title":"Response List Rules For Review Api V1 Rule Reviews Rules Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/rule-reviews/{rule_id}":{"post":{"tags":["rule-reviews"],"summary":"Submit Review","description":"Submit or update a reviewer's decision on one rule.","operationId":"submit_review_api_v1_rule_reviews__rule_id__post","parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"type":"string","title":"Rule Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmitReviewRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmitReviewResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/rule-reviews/progress":{"get":{"tags":["rule-reviews"],"summary":"Get Progress","description":"Return the calling reviewer's overall progress across all categories.","operationId":"get_progress_api_v1_rule_reviews_progress_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProgressSummary"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/rule-reviews/admin/consensus":{"get":{"tags":["rule-reviews"],"summary":"Admin Consensus","description":"Return consensus/discrepancy summary for every reviewed rule.","operationId":"admin_consensus_api_v1_rule_reviews_admin_consensus_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ConsensusSummary"},"title":"Response Admin Consensus Api V1 Rule Reviews Admin Consensus Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/rule-reviews/admin/discussions/{rule_id}/resolve":{"post":{"tags":["rule-reviews"],"summary":"Admin Resolve Discussion","description":"Resolve a discrepancy discussion and optionally update the rule's status/severity.","operationId":"admin_resolve_discussion_api_v1_rule_reviews_admin_discussions__rule_id__resolve_post","parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"type":"string","title":"Rule Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResolveDiscrepancyRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Resolve Discussion Api V1 Rule Reviews Admin Discussions  Rule Id  Resolve Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/rule-reviews/admin/ledger":{"get":{"tags":["rule-reviews"],"summary":"Admin Ledger","description":"Per-reviewer contribution counts for equity/accountability tracking.","operationId":"admin_ledger_api_v1_rule_reviews_admin_ledger_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/app__api__routes__rule_reviews__LedgerEntry"},"title":"Response Admin Ledger Api V1 Rule Reviews Admin Ledger Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/rule-reviews/admin/invite":{"post":{"tags":["rule-reviews"],"summary":"Admin Invite Reviewer","description":"Provision the reviewer role + discipline tags for an email address.\n\nLooks up the user by email in the users table (must already have logged\nin at least once so Firebase has created the row), grants `reviewer` role,\nand sets their discipline tags.","operationId":"admin_invite_reviewer_api_v1_rule_reviews_admin_invite_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteReviewerRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Admin Invite Reviewer Api V1 Rule Reviews Admin Invite Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/rule-suggestions/":{"get":{"tags":["rule-suggestions"],"summary":"List Suggestions","description":"Return a page of suggestions for the review queue.\n\nOrdered by confidence desc, then support desc, so the highest-signal\nmined rules surface first.","operationId":"list_suggestions_api_v1_rule_suggestions__get","parameters":[{"name":"source_corpus","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by mining source","title":"Source Corpus"},"description":"Filter by mining source"},{"name":"min_confidence","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Minimum confidence","title":"Min Confidence"},"description":"Minimum confidence"},{"name":"rule_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by rule_type","title":"Rule Type"},"description":"Filter by rule_type"},{"name":"severity","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by severity","title":"Severity"},"description":"Filter by severity"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Substring match on name/description","title":"Search"},"description":"Substring match on name/description"},{"name":"status","in":"query","required":false,"schema":{"type":"string","description":"Filter by status","default":"proposed","title":"Status"},"description":"Filter by status"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":100,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuggestionListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/rule-suggestions":{"get":{"tags":["rule-suggestions"],"summary":"List Suggestions","description":"Return a page of suggestions for the review queue.\n\nOrdered by confidence desc, then support desc, so the highest-signal\nmined rules surface first.","operationId":"list_suggestions_api_v1_rule_suggestions_get","parameters":[{"name":"source_corpus","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by mining source","title":"Source Corpus"},"description":"Filter by mining source"},{"name":"min_confidence","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Minimum confidence","title":"Min Confidence"},"description":"Minimum confidence"},{"name":"rule_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by rule_type","title":"Rule Type"},"description":"Filter by rule_type"},{"name":"severity","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by severity","title":"Severity"},"description":"Filter by severity"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Substring match on name/description","title":"Search"},"description":"Substring match on name/description"},{"name":"status","in":"query","required":false,"schema":{"type":"string","description":"Filter by status","default":"proposed","title":"Status"},"description":"Filter by status"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":100,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuggestionListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/rule-suggestions/stats":{"get":{"tags":["rule-suggestions"],"summary":"Suggestion Stats","description":"Tally proposed suggestions by source, severity, and rule_type.","operationId":"suggestion_stats_api_v1_rule_suggestions_stats_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuggestionStats"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/rule-suggestions/bulk":{"post":{"tags":["rule-suggestions"],"summary":"Bulk Action","description":"Apply approve / reject / set_level across a set of suggestion ids.\n\nEach id is updated independently via RulesRepository.update_rule (which\nsnapshots to rule_versions, bumps version, and invalidates the cache).\nIds that no longer exist are skipped; only successfully-updated ids are\nreturned.","operationId":"bulk_action_api_v1_rule_suggestions_bulk_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkActionRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkActionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/rule-suggestions/collapse-to-family":{"post":{"tags":["rule-suggestions"],"summary":"Collapse To Family","description":"Collapse mined companion pairs into one P1 family-rule proposal.\n\nThe originals are NOT deleted or approved — they become provenance rows on\nthe proposal, which lands as status='proposed' for founder review.","operationId":"collapse_to_family_api_v1_rule_suggestions_collapse_to_family_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollapseRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollapseResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/completeness/analyze":{"post":{"tags":["completeness"],"summary":"Analyze Estimate","description":"Upload a PDF or Excel estimate for completeness analysis.\n\nAccepts a file upload with optional parameters for claim type,\naggressiveness level, and jurisdiction. Parses the file, runs\ngap analysis, and returns a CompletenessReport.\n\nArgs:\n    file: PDF (.pdf) or Excel (.xlsx) estimate file.\n    claim_type: Override claim type (None = auto-detect).\n    aggressiveness: Suggestion depth - conservative/moderate/aggressive.\n    jurisdiction: ZIP code for building code lookup.\n\nReturns:\n    CompletenessReport JSON with rooms, suggestions, and warnings.\n\nRaises:\n    HTTPException: 400 for unsupported format, 422 for parse failure,\n        500 for analysis failure.","operationId":"analyze_estimate_api_v1_completeness_analyze_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_analyze_estimate_api_v1_completeness_analyze_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/completeness/parse-async":{"post":{"tags":["completeness"],"summary":"Parse Estimate Async","description":"Enqueue an import and return immediately (B-440 — non-blocking).\n\nHashes the upload, creates a processing import_jobs row, fires a background\ntask to parse+persist, and returns the job id. The client polls\n``GET /api/v1/jobs/{job_id}`` until ``status == \"ready\"``, at which point\nthe jobs route returns the full /parse response shape. Import is free; the\ncharge still happens at export. Mirrors the validation of the synchronous\n``/parse``.\n\nArgs:\n    file: PDF (.pdf) or Excel (.xlsx) estimate file.\n    access: Injected trial/member access object (enforces import gate).\n\nReturns:\n    202 response with ``{job_id, parse_hash, status}`` where status is\n    ``\"queued\"`` (default durable-queue path, B-458), ``\"processing\"``\n    (legacy in-container fallback, IMPORT_USE_QUEUE=False), or ``\"ready\"``\n    (B-291 manual-override short-circuit).\n\nRaises:\n    HTTPException: 400 bad file; 413 over page cap (free tier); 500 on\n        job-row creation failure. No credit is consumed here.","operationId":"parse_estimate_async_api_v1_completeness_parse_async_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_parse_estimate_async_api_v1_completeness_parse_async_post"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/completeness/preflight":{"post":{"tags":["completeness"],"summary":"Preflight Estimate","description":"Cheap, FREE pre-scan of an upload — powers the confirm dialog (B-457).\n\nRuns ONLY cheap checks: scanned-vs-vector detection, page count, header\nmetadata (text parser for vector PDFs; ONE page-1 vision call for scanned),\nan approximate line-item count, the export cost projection, and a project\nmatch against the user's existing projects. Consumes NO credit and persists\nNOTHING. The page cap still guards metered users against huge files.\n\nReturns:\n    dict: is_scanned, page_count, sketch_available, header_metadata,\n        estimated_line_count, credits_required, free_line_threshold,\n        project_match{exact, fuzzy}.\n\nRaises:\n    HTTPException: 400 bad/unknown file; 413 over page cap (metered);\n        422 unreadable PDF. No credit is ever consumed.","operationId":"preflight_estimate_api_v1_completeness_preflight_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_preflight_estimate_api_v1_completeness_preflight_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/completeness/parse":{"post":{"tags":["completeness"],"summary":"Parse Estimate","description":"Parse an estimate file WITHOUT running completeness analysis.\n\nPowers the \"verify parse first\" flow on the Supplement page. Returns\nthe structured ParsedEstimate (with provenance set on every line item)\nplus a parse_hash the client can later pass to /analyze-cached so the\nbackend does not re-parse on the analyze step.\n\nTHIS IS A FREE PREFLIGHT (2026-06-16): parsing never consumes a credit. It\nreturns the line count plus the credit cost the EXPORT step will charge\n(``credits_required``), so the client can confirm before processing. The\nactual charge happens in ``POST /esx/generate-from-parse``, priced by line\ncount (estimates ≤ FREE_LINE_THRESHOLD are free). A page cap still applies to\nrole-less users so a free preflight can't be abused on huge PDFs. Members\n(any role) are never metered.\n\nArgs:\n    file: PDF (.pdf) or Excel (.xlsx) estimate file.\n\nReturns:\n    {\n      \"parse_hash\": str,\n      \"estimate\": ParsedEstimate (JSON-mode dump),\n      \"match_stats\": {matched, unmatched, total},\n      \"line_count\": int,\n      \"credits_required\": int,   # what the export will charge (0 = free)\n      \"free_line_threshold\": int,\n    }\n\nRaises:\n    HTTPException: 400 bad file; 413 over page cap (free tier); 422 parse\n        failure (beta apology + free manual processing); 500 persist\n        failure. No credit is consumed on this endpoint.","operationId":"parse_estimate_api_v1_completeness_parse_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_parse_estimate_api_v1_completeness_parse_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/completeness/analyze-cached":{"post":{"tags":["completeness"],"summary":"Analyze Cached","description":"Run completeness analysis on an already-parsed estimate.\n\nMember-only (\"Scope Enhancement\" is locked for pay-per-conversion\naccounts). The client passes a parse_hash returned from POST /parse. The\nserver loads the cached ParsedEstimate and runs the analyzer — no\nre-upload, no re-parse.\n\nArgs:\n    payload: JSON body with keys:\n        parse_hash (str, required): hash returned by /parse\n        claim_type (str, optional): override claim type\n        aggressiveness (str, optional, default \"moderate\")\n        jurisdiction (str, optional)\n\nReturns:\n    CompletenessReport JSON.\n\nRaises:\n    HTTPException: 400 missing hash, 404 cache miss, 500 analyzer failure.","operationId":"analyze_cached_api_v1_completeness_analyze_cached_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/completeness/parse/{parse_hash}/line-item":{"patch":{"tags":["completeness"],"summary":"Override Line Item","description":"Manually assign a CAT SEL to a line item in a cached parse.\n\nUsed by the verify-parse override UX: an estimator clicks an UNMAPPED\nrow, searches the canonical dictionary, picks a code, and the row is\nupdated in-place with provenance = MANUAL. Requires that the caller OWNS\na durable parse row for the hash — the disk cache is global-by-hash, and\nwithout the ownership check any caller could re-stamp someone else's\nparse onto their own account.\n\nArgs:\n    parse_hash: hash returned by POST /parse.\n    payload: JSON body with keys:\n        room_index (int, required): index into ParsedEstimate.rooms\n        line_item_index (int, required): index into room.line_items\n        cat (str, required): new category (e.g., \"RFG\")\n        sel (str, required): new selector (e.g., \"MR\")\n\nReturns:\n    {parse_hash, estimate, match_stats} — same shape as POST /parse.\n\nRaises:\n    HTTPException: 400 bad payload, 404 cache miss / out-of-range index /\n        a hash the caller doesn't own.","operationId":"override_line_item_api_v1_completeness_parse__parse_hash__line_item_patch","parameters":[{"name":"parse_hash","in":"path","required":true,"schema":{"type":"string","title":"Parse Hash"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/completeness/parse/{parse_hash}/line-items":{"patch":{"tags":["completeness"],"summary":"Override Line Items Bulk","description":"Apply ONE ``(cat, sel)`` to MANY line items in a cached parse at once.\n\nThe review screen bundles identical unmapped lines (a custom line that\nrepeats dozens of times across a large estimate, B-486) so the estimator\nsearches once and assigns the code to every instance. This applies the same\noverride to a list of (room_index, line_item_index) targets and re-persists\nthe parse a SINGLE time — far cheaper than one request per duplicate.\n\nArgs:\n    parse_hash: hash returned by POST /parse.\n    payload: JSON body with keys:\n        targets (list[dict], required): each ``{room_index, line_item_index}``\n        cat (str, required): new category for every target\n        sel (str, required): new selector for every target\n        replace_description (bool, optional): when True, overwrite each\n            line's description with the catalog standard wording. Defaults\n            False (verbatim PDF descriptions retained).\n        action (str, optional): the chosen action symbol (B-511) applied to\n            every target; \"\" clears a prior override.\n\nReturns:\n    {parse_hash, estimate, match_stats, updated} — ``updated`` is the count\n    of lines changed.\n\nRaises:\n    HTTPException: 400 bad payload, 404 cache miss / out-of-range index /\n        a hash the caller doesn't own.","operationId":"override_line_items_bulk_api_v1_completeness_parse__parse_hash__line_items_patch","parameters":[{"name":"parse_hash","in":"path","required":true,"schema":{"type":"string","title":"Parse Hash"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/completeness/dismiss/{suggestion_id}":{"post":{"tags":["completeness"],"summary":"Dismiss Suggestion","description":"Dismiss a suggestion by ID.\n\nSince reports are stateless (not persisted), this endpoint\nreturns a simple acknowledgment. The frontend tracks dismiss\nstate locally. Exists for future persistence support.\n\nArgs:\n    suggestion_id: UUID of the suggestion to dismiss.\n\nReturns:\n    Dict with status and suggestion_id.","operationId":"dismiss_suggestion_api_v1_completeness_dismiss__suggestion_id__post","parameters":[{"name":"suggestion_id","in":"path","required":true,"schema":{"type":"string","title":"Suggestion Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/enhance/parse/{parse_hash}":{"get":{"tags":["enhance","enhance"],"summary":"Get Enhance Session","description":"Hydrate/resume: persisted narratives, context, latest run, applied ids.\n\nArgs:\n    parse_hash (str): Content hash of the import.\n\nReturns:\n    dict: {session|null, latest_run|null, applied_proposal_ids[]}.","operationId":"get_enhance_session_api_v1_enhance_parse__parse_hash__get","parameters":[{"name":"parse_hash","in":"path","required":true,"schema":{"type":"string","title":"Parse Hash"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/enhance/parse/{parse_hash}/session":{"put":{"tags":["enhance","enhance"],"summary":"Put Enhance Session","description":"Autosave the narratives + loss context. Free.\n\nRoom keys in ``narratives.rooms`` must be parsed RoomGroup display names —\nthe user never types a room name — so an unknown key is a client bug and is\nrejected with the offending keys in the 400 detail.\n\nArgs:\n    parse_hash (str): Content hash of the import.\n    payload (dict): {narratives: EnhanceNarratives-shaped, context: LossContext-shaped}.\n\nReturns:\n    dict: {ok: true, updated_at}.","operationId":"put_enhance_session_api_v1_enhance_parse__parse_hash__session_put","parameters":[{"name":"parse_hash","in":"path","required":true,"schema":{"type":"string","title":"Parse Hash"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/enhance/parse/{parse_hash}/run":{"post":{"tags":["enhance","enhance"],"summary":"Run Enhance","description":"Run the enhance engine → EnhanceRun (persisted).\n\n``mode=\"deterministic\"`` (slice 1) is free — no LLM, no metering.\n``mode=\"full\"`` (slice 2) interprets the persisted narratives with one LLM\ncall; it requires ``ENHANCE_LLM_ENABLED`` and charges 1 credit for metered\n(role-less) users, idempotent on ``enhance:{hash[:16]}:{run_id}`` so a re-run\nwith the same ``run_id`` is free. A degraded run (interpreter unavailable) and\nany raised exception both refund.\n\nArgs:\n    parse_hash (str): Content hash of the import.\n    payload (dict): {mode: \"deterministic\"|\"full\", run_id?: str}.\n\nReturns:\n    dict: The serialized EnhanceRun.","operationId":"run_enhance_api_v1_enhance_parse__parse_hash__run_post","parameters":[{"name":"parse_hash","in":"path","required":true,"schema":{"type":"string","title":"Parse Hash"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/enhance/parse/{parse_hash}/apply":{"post":{"tags":["enhance","enhance"],"summary":"Apply Enhance","description":"Apply approved ADD proposals into the persisted parse. Free in slice 1.\n\nArgs:\n    parse_hash (str): Content hash of the import.\n    payload (dict): {resolutions: [ApplyResolution, ...]}.\n\nReturns:\n    dict: {parse_hash, estimate, match_stats, applied[], rejected[], skipped[]}.","operationId":"apply_enhance_api_v1_enhance_parse__parse_hash__apply_post","parameters":[{"name":"parse_hash","in":"path","required":true,"schema":{"type":"string","title":"Parse Hash"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/enhance/parse/{parse_hash}/revert":{"post":{"tags":["enhance","enhance"],"summary":"Revert Enhance","description":"Undo previously-applied Enhance changes by proposal id. Free.\n\nOnly touches lines carrying our enhance prefix — a faithful parse line is\nnever removed. An ``ADDED`` line is removed (slice-1 behavior); an\n``ENHANCED`` (MODIFY-swapped) line is restored from its ``original_value``\nsnapshot and the snapshot cleared. A matching ``ENHANCED`` line with no\nsnapshot is left as-is and reported in ``skipped``.\n\nArgs:\n    parse_hash (str): Content hash of the import.\n    payload (dict): {proposal_ids: [str, ...]}.\n\nReturns:\n    dict: {parse_hash, estimate, match_stats, reverted[], skipped[]}.","operationId":"revert_enhance_api_v1_enhance_parse__parse_hash__revert_post","parameters":[{"name":"parse_hash","in":"path","required":true,"schema":{"type":"string","title":"Parse Hash"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/user/projects/{project_id}/scopes":{"post":{"tags":["scopes"],"summary":"Save Scope","description":"Save a generated scope to a project.\n\nArgs:\n    project_id: The project to attach the scope to.\n    body: Contains scope_data (full JSON) and optional source badge.\n    user: Authenticated user from JWT.\n\nReturns:\n    ScopeSaveResponse: The saved scope with ID and timestamps.","operationId":"save_scope_api_v1_user_projects__project_id__scopes_post","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeSaveRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeSaveResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["scopes"],"summary":"List Scopes","description":"List all scopes for a project, ordered by created_at descending.\n\nArgs:\n    project_id: The project whose scopes to list.\n    user: Authenticated user from JWT.\n\nReturns:\n    List[ScopeListItem]: Scopes ordered newest-first.","operationId":"list_scopes_api_v1_user_projects__project_id__scopes_get","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ScopeListItem"},"title":"Response List Scopes Api V1 User Projects  Project Id  Scopes Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/user/projects/{project_id}/scopes/{scope_id}/rule-trace":{"get":{"tags":["scopes"],"summary":"Get Scope Rule Trace","description":"Return all rule-firing trace events for a single scope (PRP-003).\n\nJoins current rule status from `rules` so the UI can mark trace\nentries whose underlying rule has since been retired/superseded.\nReturns `pre_phase3: true` when the scope was generated before this\nfeature shipped, so the UI can render the right empty state instead\nof a confusing \"0 rules fired\" message.","operationId":"get_scope_rule_trace_api_v1_user_projects__project_id__scopes__scope_id__rule_trace_get","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"scope_id","in":"path","required":true,"schema":{"type":"string","title":"Scope Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RuleTraceResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/user/projects/{project_id}/scope-draft":{"get":{"tags":["scopes"],"summary":"Get Scope Draft","description":"Get the caller's saved Scope Builder form draft for a project.\n\nArgs:\n    project_id: The project whose draft to retrieve.\n    user: Authenticated user from JWT.\n\nReturns:\n    ScopeDraftResponse: The stored draft payload + updated_at.\n\nRaises:\n    HTTPException: 404 if no draft exists for this project+user.","operationId":"get_scope_draft_api_v1_user_projects__project_id__scope_draft_get","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeDraftResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["scopes"],"summary":"Put Scope Draft","description":"Upsert the caller's Scope Builder form draft for a project.\n\nSaving a draft is free (no AI generation) — this is the \"save without\ngenerate\" path for the Scope Builder form (B-258).\n\nArgs:\n    project_id: The project to attach the draft to.\n    body: Contains the versioned draft JSON (client-defined shape).\n    user: Authenticated user from JWT.\n\nReturns:\n    ScopeDraftResponse: The stored draft + new updated_at.","operationId":"put_scope_draft_api_v1_user_projects__project_id__scope_draft_put","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeDraftPutRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeDraftResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/user/projects/{project_id}/scopes/latest":{"get":{"tags":["scopes"],"summary":"Get Latest Scope","description":"Get the most recent scope for a project.\n\nArgs:\n    project_id: The project whose latest scope to retrieve.\n    user: Authenticated user from JWT.\n\nReturns:\n    ScopeListItem: The most recently created scope.\n\nRaises:\n    HTTPException: 404 if no scopes exist for the project.","operationId":"get_latest_scope_api_v1_user_projects__project_id__scopes_latest_get","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeListItem"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/me":{"get":{"tags":["admin"],"summary":"Me","description":"Return the caller's role set. Used by the frontend to decide whether\nto show the Admin link in the sidebar — does NOT 403 if the caller\nisn't an admin (it just returns an empty role list).","operationId":"me_api_v1_admin_me_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/usage/daily":{"get":{"tags":["admin"],"summary":"Usage Daily","description":"Daily cost totals last N days, broken down per model.\n\nReturns:\n    {\n      days: [\n        {date: \"2026-05-23\", total_usd: 1.234,\n         by_model: {\"gpt-4o\": 0.85, \"claude-sonnet-4-5-20250929\": 0.30, ...},\n         by_provider: {\"openai\": 0.85, \"anthropic\": 0.30, ...}\n        },\n        ...\n      ],\n      total_usd: 12.34,\n    }","operationId":"usage_daily_api_v1_admin_usage_daily_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"default":30,"title":"Days"}},{"name":"user_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter to a single user","title":"User Id"},"description":"Filter to a single user"},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/usage/hourly":{"get":{"tags":["admin"],"summary":"Usage Hourly","description":"Hourly cost totals for a single day, broken down per model.\n\nDefaults to \"today\" (UTC) so the developer can answer\n\"am I burning $1/hour with heavy testing right now?\".","operationId":"usage_hourly_api_v1_admin_usage_hourly_get","parameters":[{"name":"date","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"UTC date YYYY-MM-DD, defaults to today","title":"Date"},"description":"UTC date YYYY-MM-DD, defaults to today"},{"name":"user_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/usage/by-endpoint":{"get":{"tags":["admin"],"summary":"Usage By Endpoint","description":"Per-endpoint avg + p95 cost per *request* (sum of LLM calls per\nrequest_id), so 'What does one /completeness/analyze cost?' has a\ntruthful answer even when one analyze call fans out into 4 LLM calls.","operationId":"usage_by_endpoint_api_v1_admin_usage_by_endpoint_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"default":30,"title":"Days"}},{"name":"user_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter to a single user","title":"User Id"},"description":"Filter to a single user"},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/users":{"get":{"tags":["admin"],"summary":"List Users","description":"User roster with spend + project counts.\n\nJoins users → projects (count) → api_usage (sum over `days`).\nDone in three queries + an in-memory join so we don't depend on\nSupabase RPC or a postgres view.","operationId":"list_users_api_v1_admin_users_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"description":"Spend window in days","default":30,"title":"Days"},"description":"Spend window in days"},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/users/{user_id}/roles":{"get":{"tags":["admin"],"summary":"Get Target User Roles","operationId":"get_target_user_roles_api_v1_admin_users__user_id__roles_get","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["admin"],"summary":"Set User Roles","description":"Replace the user's role set with `payload['roles']`.\n\nAuthorization rules:\n  * Only super_admin can grant or revoke 'super_admin' or 'admin'.\n  * Other roles can be managed by any admin.","operationId":"set_user_roles_api_v1_admin_users__user_id__roles_post","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/users/{user_id}/estimates":{"get":{"tags":["admin"],"summary":"Get User Estimates","description":"One row per estimate for this user (counts + outcome), never payload.","operationId":"get_user_estimates_api_v1_admin_users__user_id__estimates_get","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/estimates/{public_ref}/detail":{"get":{"tags":["admin"],"summary":"Get Estimate Detail","description":"Drill-down for one estimate: unmatched items, diagnostics, error.","operationId":"get_estimate_detail_api_v1_admin_estimates__public_ref__detail_get","parameters":[{"name":"public_ref","in":"path","required":true,"schema":{"type":"string","title":"Public Ref"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/users/{user_id}/logins":{"get":{"tags":["admin"],"summary":"Get User Logins","description":"Login count + last login + per-ip breakdown for a user.","operationId":"get_user_logins_api_v1_admin_users__user_id__logins_get","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/users/{user_id}/deactivate":{"post":{"tags":["admin"],"summary":"Deactivate User","description":"Flip is_active to FALSE. Only super_admin can deactivate users\n(it's a destructive action in spirit even though it's soft).","operationId":"deactivate_user_api_v1_admin_users__user_id__deactivate_post","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/users/{user_id}/activate":{"post":{"tags":["admin"],"summary":"Activate User","operationId":"activate_user_api_v1_admin_users__user_id__activate_post","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/users/{user_id}/account":{"get":{"tags":["admin"],"summary":"Get User Account","description":"Account detail for the admin user card: activation status, signup\nforensics, subscription (if any), credit balance, and a short ledger tail.\nEvery field degrades gracefully when its table/column isn't populated.","operationId":"get_user_account_api_v1_admin_users__user_id__account_get","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/users/{user_id}":{"delete":{"tags":["admin"],"summary":"Delete User","description":"Permanently delete a user and all their data. Super-admin only.\n\nHard delete (the founder's choice for clearing junk/test accounts). Most\nchild rows cascade or SET NULL via FK; the few NO-ACTION foreign keys\n(projects' notes / pipeline_execution_logs, redemption_codes.redeemed_by)\nare cleared first so the delete doesn't fail. Projects are keyed by the\nuuid5 derivative of the user id, not the raw id.","operationId":"delete_user_api_v1_admin_users__user_id__delete","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/roles":{"get":{"tags":["admin"],"summary":"Get Roles","description":"Full role catalog for the UI's assignment checkboxes.","operationId":"get_roles_api_v1_admin_roles_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/pricing":{"get":{"tags":["admin"],"summary":"Get Pricing","description":"Per-model price map. Used by the pricing simulator + as a reference\nin the cost panel (\"you're being billed at $X/Mtok for this model\").","operationId":"get_pricing_api_v1_admin_pricing_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/usage/by-user":{"get":{"tags":["admin"],"summary":"Usage By User","description":"Top N users by cost in the [start, end] window.\n\nReturns:\n    {\n      users: [\n        {user_id, email, name, total_cost_usd, request_count,\n         last_request_at, daily_sparkline: [floats per day]}, ...\n      ],\n      window: {start, end, days},\n      total_users: N,\n      total_cost_usd: $$$\n    }","operationId":"usage_by_user_api_v1_admin_usage_by_user_get","parameters":[{"name":"start","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"ISO start (defaults to 30 days ago)","title":"Start"},"description":"ISO start (defaults to 30 days ago)"},{"name":"end","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"ISO end (defaults to now)","title":"End"},"description":"ISO end (defaults to now)"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Top-N users by cost","default":10,"title":"Limit"},"description":"Top-N users by cost"},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/usage/by-user/{user_id}":{"get":{"tags":["admin"],"summary":"Usage By User Detail","description":"Detailed usage for a single user.\n\nReturns:\n    {\n      user: {id, email, name},\n      window: {...},\n      total_cost_usd,\n      total_requests,\n      by_day: [{date, total_usd, by_model}],\n      by_endpoint: [{endpoint, request_count, total_usd, avg_usd}],\n      by_model: [{model, total_usd, input_tokens, output_tokens}],\n      recent_calls: [up to 20 most recent rows]\n    }","operationId":"usage_by_user_detail_api_v1_admin_usage_by_user__user_id__get","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}},{"name":"start","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Start"}},{"name":"end","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"End"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/thresholds":{"get":{"tags":["admin"],"summary":"List Thresholds","description":"All configured usage thresholds.","operationId":"list_thresholds_api_v1_admin_thresholds_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["admin"],"summary":"Create Threshold","description":"Create a new threshold.\n\nBody: {scope, user_id?, metric, threshold_value, action, enabled?}","operationId":"create_threshold_api_v1_admin_thresholds_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/thresholds/{threshold_id}":{"patch":{"tags":["admin"],"summary":"Update Threshold","description":"Update mutable fields on a threshold (value, action, enabled).","operationId":"update_threshold_api_v1_admin_thresholds__threshold_id__patch","parameters":[{"name":"threshold_id","in":"path","required":true,"schema":{"type":"string","title":"Threshold Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["admin"],"summary":"Delete Threshold","operationId":"delete_threshold_api_v1_admin_thresholds__threshold_id__delete","parameters":[{"name":"threshold_id","in":"path","required":true,"schema":{"type":"string","title":"Threshold Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/thresholds/evaluate":{"post":{"tags":["admin"],"summary":"Evaluate Thresholds Now","description":"Run one evaluation pass synchronously. Used by the 'Evaluate now'\nbutton in the admin UI for testing and for cron-style invocations\nwhen the in-process loop isn't running.","operationId":"evaluate_thresholds_now_api_v1_admin_thresholds_evaluate_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/alerts":{"get":{"tags":["admin"],"summary":"List Alerts","description":"List recent alerts.\n\nFilters:\n  - acknowledged=false → only unacknowledged (default for header view)\n  - acknowledged=true  → only acknowledged (history view)\n  - omit                → both","operationId":"list_alerts_api_v1_admin_alerts_get","parameters":[{"name":"acknowledged","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Acknowledged"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":50,"title":"Limit"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/alerts/{alert_id}/acknowledge":{"post":{"tags":["admin"],"summary":"Acknowledge Alert","description":"Mark an alert acknowledged. If it was a soft/hard block, the user\nis unblocked once *all* their unacknowledged block alerts are cleared.","operationId":"acknowledge_alert_api_v1_admin_alerts__alert_id__acknowledge_post","parameters":[{"name":"alert_id","in":"path","required":true,"schema":{"type":"string","title":"Alert Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/users/{user_id}/unblock":{"post":{"tags":["admin"],"summary":"Unblock User","description":"Clear ALL unacknowledged block alerts for a user. One-click rescue\nwhen a soft/hard block is firing legitimately but admin has decided\nto override.","operationId":"unblock_user_api_v1_admin_users__user_id__unblock_post","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/blocked-users":{"get":{"tags":["admin"],"summary":"List Blocked Users","description":"List users currently blocked (have an unacknowledged soft/hard block).","operationId":"list_blocked_users_api_v1_admin_blocked_users_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/partners":{"get":{"tags":["admin"],"summary":"List Partners","description":"All partners, newest first, each with a sanitized ``keys`` array.\n\nNever returns a key hash or a full key — only prefix/env/status/last-used.","operationId":"list_partners_api_v1_admin_partners_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["admin"],"summary":"Create Partner","description":"Create a partner from ``{name, contact_email}``.","operationId":"create_partner_api_v1_admin_partners_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/partners/{partner_id}/status":{"post":{"tags":["admin"],"summary":"Set Partner Status","description":"Suspend or reactivate a partner. Suspended → all their keys fail auth.","operationId":"set_partner_status_api_v1_admin_partners__partner_id__status_post","parameters":[{"name":"partner_id","in":"path","required":true,"schema":{"type":"string","title":"Partner Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/partners/{partner_id}/webhook":{"post":{"tags":["admin"],"summary":"Set Partner Webhook","description":"Set or clear a partner's webhook.\n\nBody ``{url}`` sets the URL. ``{url: null}`` clears both url and secret.\n``{generate_secret: true}`` mints a new signing secret and returns it in the\nresponse EXACTLY ONCE (``webhook_secret``); it is never returned again.","operationId":"set_partner_webhook_api_v1_admin_partners__partner_id__webhook_post","parameters":[{"name":"partner_id","in":"path","required":true,"schema":{"type":"string","title":"Partner Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/partners/{partner_id}/keys":{"post":{"tags":["admin"],"summary":"Create Partner Key","description":"Create a test or live API key. ``full_key`` is returned EXACTLY ONCE.","operationId":"create_partner_key_api_v1_admin_partners__partner_id__keys_post","parameters":[{"name":"partner_id","in":"path","required":true,"schema":{"type":"string","title":"Partner Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/partners/keys/revoke":{"post":{"tags":["admin"],"summary":"Revoke Partner Key","description":"Revoke all active keys matching a display prefix.","operationId":"revoke_partner_key_api_v1_admin_partners_keys_revoke_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/triage/summary":{"get":{"tags":["admin","triage"],"summary":"Triage Summary","description":"Funnel counts for the Triage dashboard header.","operationId":"triage_summary_api_v1_admin_triage_summary_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/triage/rules":{"get":{"tags":["admin","triage"],"summary":"List Triage Rules","description":"Judged proposed rules, sorted VALID_CONDITIONAL first then confidence desc.","operationId":"list_triage_rules_api_v1_admin_triage_rules_get","parameters":[{"name":"verdict","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter to one verdict","title":"Verdict"},"description":"Filter to one verdict"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":100,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Triage Rules Api V1 Admin Triage Rules Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/triage/{rule_id}/decision":{"post":{"tags":["admin","triage"],"summary":"Triage Decision","description":"Approve or reject a triaged rule.\n\nApprove makes the rule FIRE (status='active' + is_active=True) immediately — an\nexplicit per-rule founder action. VALID_CONDITIONAL rules carry a guard (\"add X\nunless Y present\") which the companion pass now enforces at runtime (B-619,\napp.services.scope_engine.companions.apply_db_companions), so they activate like\nany other rule — no longer held. Reject retires the rule and ensures it can't fire.","operationId":"triage_decision_api_v1_admin_triage__rule_id__decision_post","parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"type":"string","title":"Rule Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Triage Decision Api V1 Admin Triage  Rule Id  Decision Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/rules/chat":{"post":{"tags":["admin","rules","chat"],"summary":"Rule Chat","description":"Interpret a NL message, ground it to catalog codes, and answer over the corpus.","operationId":"rule_chat_api_v1_admin_rules_chat_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Rule Chat Api V1 Admin Rules Chat Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/rules/chat/save":{"post":{"tags":["admin","rules","chat"],"summary":"Save Drafted Rule","description":"Persist a chat-drafted rule — forced to status='proposed', is_active=False.\n\nThe rule enters the same triage/approval gate as mined rules; approving it in\n/admin/triage is what makes it fire (guarded, B-619).","operationId":"save_drafted_rule_api_v1_admin_rules_chat_save_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Save Drafted Rule Api V1 Admin Rules Chat Save Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/codes":{"post":{"tags":["admin-codes"],"summary":"Mint Codes","description":"Mint ``count`` admin codes worth ``credits`` each.\n\nWhen ``email_to`` is given the codes are also emailed to that address\n(one email per code). Codes are returned in the response regardless, so\na failed send never loses them.","operationId":"mint_codes_api_v1_admin_codes_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MintCodesRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MintCodesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["admin-codes"],"summary":"List Codes Route","description":"List redemption codes, newest first, with optional filters.","operationId":"list_codes_route_api_v1_admin_codes_get","parameters":[{"name":"source","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"}},{"name":"redeemed","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Redeemed"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"default":100,"title":"Limit"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CodeOut"},"title":"Response List Codes Route Api V1 Admin Codes Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/email-log":{"get":{"tags":["admin-codes"],"summary":"Email Log Route","description":"Recent email send attempts (filter ``status=failed`` for problems).","operationId":"email_log_route_api_v1_admin_email_log_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"default":100,"title":"Limit"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EmailLogEntry"},"title":"Response Email Log Route Api V1 Admin Email Log Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/estimates/{public_ref}":{"get":{"tags":["admin-codes"],"summary":"Estimate Lookup Route","description":"\"What happened on estimate X\" — the non-PII event timeline for a ref.\n\nPaste an ``EST-...`` ref to see created/parsed/exported/failed events with\nline counts, statuses, error classes, and credits charged. No claim/insured/\naddress data is stored, so this is safe to read for support.","operationId":"estimate_lookup_route_api_v1_admin_estimates__public_ref__get","parameters":[{"name":"public_ref","in":"path","required":true,"schema":{"type":"string","title":"Public Ref"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EstimateLookupResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/users/{user_id}/entitlements":{"post":{"tags":["admin-codes"],"summary":"Grant User Entitlement","description":"Grant a capability (e.g. sketch / scope_gen) to a specific user.\n\nThis is the \"I turned it on for them\" switch: a per-user grant that the\nentitlement resolver ORs in, independent of the user's plan.","operationId":"grant_user_entitlement_api_v1_admin_users__user_id__entitlements_post","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GrantEntitlementRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["admin-codes"],"summary":"List User Entitlements","description":"List a user's per-user capability grants.","operationId":"list_user_entitlements_api_v1_admin_users__user_id__entitlements_get","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/users/{user_id}/entitlements/{feature}":{"delete":{"tags":["admin-codes"],"summary":"Revoke User Entitlement","description":"Revoke a previously-granted capability from a user.","operationId":"revoke_user_entitlement_api_v1_admin_users__user_id__entitlements__feature__delete","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}},{"name":"feature","in":"path","required":true,"schema":{"type":"string","title":"Feature"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/users/{user_id}/credits":{"get":{"tags":["admin-codes"],"summary":"Get User Credits","description":"Show a user's current credit balance, recent ledger, and any admin codes\nthey have outstanding (issued but not yet redeemed).","operationId":"get_user_credits_api_v1_admin_users__user_id__credits_get","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserCreditsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["admin-codes"],"summary":"Add User Credits","description":"Grant credits to a specific user, directly or via a redeemable code.\n\n``direct`` (default): apply the credits to the balance immediately via\n``apply_credit`` (reason ``admin_grant``). This works regardless of email\nverification — the fix for \"I granted credits but they still see 0\".\n\n``code``: mint a one-time admin code and email it. The code is returned in\nthe response too, so a failed/blocked email never loses the grant.","operationId":"add_user_credits_api_v1_admin_users__user_id__credits_post","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddCreditsRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddCreditsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/feedback":{"get":{"tags":["admin-support"],"summary":"List Feedback","description":"List submitted feedback, newest first. Filter by ``status`` (e.g.\n``pending``) to triage what still needs a reward decision.","operationId":"list_feedback_api_v1_admin_feedback_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"default":100,"title":"Limit"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/FeedbackItem"},"title":"Response List Feedback Api V1 Admin Feedback Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/feedback/{feedback_id}/review":{"post":{"tags":["admin-support"],"summary":"Review Feedback","description":"Reward or dismiss a feedback item.\n\n``reward`` grants ``credits`` directly to the submitter's balance (reason\n``feedback_manual``) and marks the item ``rewarded_manual``. ``dismiss``\nmarks it ``reviewed_no_reward``. Idempotent reward: re-reviewing a row that\nis already rewarded does not double-grant.","operationId":"review_feedback_api_v1_admin_feedback__feedback_id__review_post","parameters":[{"name":"feedback_id","in":"path","required":true,"schema":{"type":"integer","title":"Feedback Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewFeedbackRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewFeedbackResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/users/{user_id}/email":{"post":{"tags":["admin-support"],"summary":"Email User","description":"Send a one-off email to a user (support / outreach).\n\nReturns ``email_enabled=False`` when no email provider is configured, so the\ncaller can tell \"no address on file\" apart from \"email is turned off\".","operationId":"email_user_api_v1_admin_users__user_id__email_post","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailUserRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailUserResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/imports/":{"get":{"tags":["imports"],"summary":"List Imports","description":"List the caller's stored imports, newest first.\n\nArgs:\n    project_id: Optional filter to one project's imports.\n\nReturns:\n    List[ImportSummary]: parse_hash, filename, project link, created_at.","operationId":"list_imports_api_v1_imports__get","parameters":[{"name":"project_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ImportSummary"},"title":"Response List Imports Api V1 Imports  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/imports/{parse_hash}":{"get":{"tags":["imports"],"summary":"Get Import","description":"Re-hydrate a stored import in the exact POST /completeness/parse shape.\n\nFree: the charge happened at import time. The Supplement page uses this to\nre-open an import from the dashboard (?import=<hash>) with the same tree,\ndiagnostics, and header metadata it showed originally.\n\nRaises:\n    HTTPException: 404 when the caller has no stored import for the hash.","operationId":"get_import_api_v1_imports__parse_hash__get","parameters":[{"name":"parse_hash","in":"path","required":true,"schema":{"type":"string","title":"Parse Hash"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["imports"],"summary":"Delete Import","description":"Permanently delete one of the caller's stored imports.\n\nRemoves the durable ``parsed_estimates`` row so the import stops appearing\non the dashboard, in the project's imported-estimates list, and in the\nSupplement page's \"open an existing supplement\" picker. Idempotent: a hash\nthe caller doesn't own returns 404 (never touches another user's row).\n\nRaises:\n    HTTPException: 404 when the caller has no stored import for the hash.","operationId":"delete_import_api_v1_imports__parse_hash__delete","parameters":[{"name":"parse_hash","in":"path","required":true,"schema":{"type":"string","title":"Parse Hash"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/imports/{parse_hash}/source-pdf":{"get":{"tags":["imports"],"summary":"Get Import Source Pdf","description":"Stream back the original uploaded source PDF for a stored import (B-600).\n\nThe web Supplement page's \"View in source PDF\" viewer needs the original\nbytes; on a reopened/background import the browser no longer holds the\nuploaded File, so it fetches the retained blob here. Owner-scoped exactly\nlike GET /imports/{hash}: the parsed_estimates row must belong to the\ncaller before any storage lookup happens.\n\nRaises:\n    HTTPException: 404 when the caller has no stored import for the hash,\n        or when no source blob was retained (legacy imports).","operationId":"get_import_source_pdf_api_v1_imports__parse_hash__source_pdf_get","parameters":[{"name":"parse_hash","in":"path","required":true,"schema":{"type":"string","title":"Parse Hash"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/imports/{parse_hash}/link-project":{"post":{"tags":["imports"],"summary":"Link Project","description":"Persist the import↔project association (ownership checked both sides).\n\nThe Supplement page calls this when the user picks/creates a project in\nthe post-parse dialog, making the link durable (it used to live only in a\nURL param).\n\nRaises:\n    HTTPException: 404 unowned import; 403 a project that isn't the\n        caller's; 404 unknown project.","operationId":"link_project_api_v1_imports__parse_hash__link_project_post","parameters":[{"name":"parse_hash","in":"path","required":true,"schema":{"type":"string","title":"Parse Hash"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkProjectRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/jobs/{job_id}":{"get":{"tags":["import-jobs"],"summary":"Get Import Job","description":"Return the status of an import job; include the parse result when ready.\n\nClients poll this endpoint after POSTing to /completeness/parse-async.\nWhen ``status == \"ready\"`` the ``result`` key contains the full parse\nresponse shape (same as POST /completeness/parse) so the Supplement page\ncan render without a second upload.  The response includes\n``credits_required``, ``line_count``, and ``free_line_threshold`` so the\nmetering confirm-before-export dialog works identically to the sync path\n(I1 — these fields were previously missing, causing metered users to see\n\"Free\" before export).\n\nArgs:\n    job_id (str): Import job id returned by parse-async.\n    access (TrialAccess): Auth + metering context from ``require_import_access``.\n        Owner-scopes the job lookup so one user cannot read another user's job.\n\nReturns:\n    Dict with keys:\n        - ``job_id`` (str)\n        - ``status`` (str): ``\"processing\"`` | ``\"ready\"`` | ``\"failed\"``\n        - ``parse_hash`` (str)\n        - ``filename`` (str)\n        - ``error`` (str, only when failed)\n        - ``result`` (dict, only when ready): full /parse response shape\n\nRaises:\n    HTTPException: 404 when the job does not exist or belongs to another user.","operationId":"get_import_job_api_v1_jobs__job_id__get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Import Job Api V1 Jobs  Job Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/comparisons":{"post":{"tags":["comparisons"],"summary":"Create From Estimates","description":"Create a durable comparison from two already-imported estimates.","operationId":"create_from_estimates_api_v1_comparisons_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateFromEstimatesRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComparisonCreateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["comparisons"],"summary":"List All","description":"List the user's saved comparisons, newest first.","operationId":"list_all_api_v1_comparisons_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ComparisonListEntry"},"title":"Response List All Api V1 Comparisons Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/comparisons/upload":{"post":{"tags":["comparisons"],"summary":"Create From Uploads","description":"Create a durable comparison from two uploaded ESX/PDF files.","operationId":"create_from_uploads_api_v1_comparisons_upload_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_create_from_uploads_api_v1_comparisons_upload_post"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComparisonCreateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/comparisons/jobs/upload":{"post":{"tags":["comparisons"],"summary":"Create Job From Uploads","description":"Start an async comparison from two uploads; returns a job id to poll.\n\nThe heavy per-line matching runs in the background so the request returns\nimmediately (no gateway timeout / \"network error\" on large PDFs). Poll\n``GET /comparisons/jobs/{job_id}`` for per-phase progress + the result id.","operationId":"create_job_from_uploads_api_v1_comparisons_jobs_upload_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_create_job_from_uploads_api_v1_comparisons_jobs_upload_post"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/comparisons/jobs/{job_id}":{"get":{"tags":["comparisons"],"summary":"Get Job Status","description":"Poll a comparison job's per-phase progress + terminal result.","operationId":"get_job_status_api_v1_comparisons_jobs__job_id__get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComparisonJobStatus"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/comparisons/{comparison_id}":{"get":{"tags":["comparisons"],"summary":"Get One","description":"Return one comparison with its derived report.","operationId":"get_one_api_v1_comparisons__comparison_id__get","parameters":[{"name":"comparison_id","in":"path","required":true,"schema":{"type":"string","title":"Comparison Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComparisonDetail"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["comparisons"],"summary":"Delete One","description":"Delete one of the user's saved comparisons (B-686).\n\nOwner-scoped like the other comparison routes; returns 204 on success and\n404 if the comparison doesn't exist or isn't the caller's.","operationId":"delete_one_api_v1_comparisons__comparison_id__delete","parameters":[{"name":"comparison_id","in":"path","required":true,"schema":{"type":"string","title":"Comparison Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/comparisons/{comparison_id}/narrative":{"post":{"tags":["comparisons"],"summary":"Generate Narrative","description":"Generate the neutral, grounded prose narrative for a comparison (on demand).\n\nRuns the LLM prose layer over the deterministic themes only when explicitly\nrequested (a button), so there is no cost on normal report views. Returns a\n``NarrativeProse`` (overview + per-theme sections + disclaimer).","operationId":"generate_narrative_api_v1_comparisons__comparison_id__narrative_post","parameters":[{"name":"comparison_id","in":"path","required":true,"schema":{"type":"string","title":"Comparison Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/comparisons/{comparison_id}/decisions":{"patch":{"tags":["comparisons"],"summary":"Patch Decisions","description":"Overwrite the reconciliation decisions, re-derive, and persist.\n\nThe frozen snapshots are the source of truth — only the decisions layer and\nthe derived-report cache change, so the report updates without ever\nre-parsing the source files.","operationId":"patch_decisions_api_v1_comparisons__comparison_id__decisions_patch","parameters":[{"name":"comparison_id","in":"path","required":true,"schema":{"type":"string","title":"Comparison Id"}},{"name":"authorization","in":"header","required":false,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DecisionsPatchRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComparisonDetail"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/favicon.ico":{"get":{"summary":"Favicon","description":"Serve favicon to avoid 404 errors.","operationId":"favicon_favicon_ico_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api":{"get":{"summary":"Api Info","description":"API information endpoint.","operationId":"api_info_api_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/_debug/routers":{"get":{"summary":"Debug Routers","description":"List which optional routers loaded and capture import tracebacks.","operationId":"debug_routers__debug_routers_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"ActionCode":{"type":"string","enum":["&","+","-","R","L","M"],"title":"ActionCode","description":"Action codes for Xactimate line items."},"AdapterReport":{"properties":{"manual_entry_required":{"items":{"$ref":"#/components/schemas/ManualEntryItem"},"type":"array","title":"Manual Entry Required"},"codes_not_in_catalog":{"items":{"$ref":"#/components/schemas/CatalogMissItem"},"type":"array","title":"Codes Not In Catalog"},"warnings":{"items":{"type":"string"},"type":"array","title":"Warnings"},"default_box_rooms":{"items":{"type":"string"},"type":"array","title":"Default Box Rooms"},"dropped_skipped_count":{"type":"integer","title":"Dropped Skipped Count","default":0}},"type":"object","title":"AdapterReport","description":"What the adapter saw — surfaced verbatim in the API response.\n\nThe route is expected to forward this object so the UI can decide what\nto surface inline next to each line item."},"AddCreditsRequest":{"properties":{"credits":{"type":"integer","maximum":1000.0,"exclusiveMinimum":0.0,"title":"Credits"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"},"mode":{"type":"string","title":"Mode","description":"direct | code","default":"direct"}},"type":"object","required":["credits"],"title":"AddCreditsRequest","description":"Manually grant credits to a user.\n\n``mode='direct'`` (default) applies the credits straight to the balance via\nthe ledger — instant, works for unverified users, and is the right tool for\nfounder-initiated support grants. ``mode='code'`` mints a one-time code and\nemails it (the user redeems it and sees the before->after increment), which\nis better when you want the recipient to opt in."},"AddCreditsResponse":{"properties":{"user_id":{"type":"string","title":"User Id"},"mode":{"type":"string","title":"Mode"},"code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code"},"credits":{"type":"integer","title":"Credits"},"issued_to_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Issued To Email"},"emailed":{"type":"boolean","title":"Emailed"},"balance":{"type":"integer","title":"Balance"}},"type":"object","required":["user_id","mode","credits","emailed","balance"],"title":"AddCreditsResponse"},"AgreementResponse":{"properties":{"version":{"type":"string","title":"Version"},"accepted":{"type":"boolean","title":"Accepted"}},"type":"object","required":["version","accepted"],"title":"AgreementResponse"},"BatchStatus":{"properties":{"batch_id":{"type":"string","title":"Batch Id"},"total_files":{"type":"integer","title":"Total Files"},"processed":{"type":"integer","title":"Processed"},"failed":{"type":"integer","title":"Failed"},"succeeded":{"type":"integer","title":"Succeeded"},"files":{"items":{"$ref":"#/components/schemas/FileResult"},"type":"array","title":"Files"},"status":{"type":"string","title":"Status"},"stats_before":{"anyOf":[{"additionalProperties":{"type":"integer"},"type":"object"},{"type":"null"}],"title":"Stats Before"},"stats_after":{"anyOf":[{"additionalProperties":{"type":"integer"},"type":"object"},{"type":"null"}],"title":"Stats After"},"stats_diff":{"anyOf":[{"additionalProperties":{"type":"integer"},"type":"object"},{"type":"null"}],"title":"Stats Diff"}},"type":"object","required":["batch_id","total_files","processed","failed","succeeded","files","status"],"title":"BatchStatus","description":"Overall batch processing status with per-file tracking."},"BillingConfigResponse":{"properties":{"enabled":{"type":"boolean","title":"Enabled"},"credits":{"$ref":"#/components/schemas/CreditsConfigOut"},"tiers":{"items":{"$ref":"#/components/schemas/TierOut"},"type":"array","title":"Tiers"},"packs":{"items":{"$ref":"#/components/schemas/PackOut"},"type":"array","title":"Packs"},"founder_promo_code":{"type":"string","title":"Founder Promo Code"},"founder":{"$ref":"#/components/schemas/FounderConfigOut"}},"type":"object","required":["enabled","credits","tiers","packs","founder_promo_code","founder"],"title":"BillingConfigResponse"},"Body_analyze_estimate_api_v1_completeness_analyze_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"},"claim_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Claim Type"},"aggressiveness":{"type":"string","title":"Aggressiveness","default":"moderate"},"jurisdiction":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jurisdiction"}},"type":"object","required":["file"],"title":"Body_analyze_estimate_api_v1_completeness_analyze_post"},"Body_chatbot_endpoint_api_v1_chatbot__post":{"properties":{"question":{"type":"string","title":"Question"},"project_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Id"},"project_address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Address"},"image":{"type":"string","format":"binary","title":"Image"}},"type":"object","required":["question"],"title":"Body_chatbot_endpoint_api_v1_chatbot__post"},"Body_create_conversion_v1_conversions_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"},"price_list":{"type":"string","title":"Price List"},"output_formats":{"items":{"type":"string"},"type":"array","title":"Output Formats","default":["esx"]},"callback_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Callback Url"}},"type":"object","required":["file","price_list"],"title":"Body_create_conversion_v1_conversions_post"},"Body_create_from_uploads_api_v1_comparisons_upload_post":{"properties":{"baseline_file":{"type":"string","format":"binary","title":"Baseline File"},"comparison_file":{"type":"string","format":"binary","title":"Comparison File"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"project_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Id"}},"type":"object","required":["baseline_file","comparison_file"],"title":"Body_create_from_uploads_api_v1_comparisons_upload_post"},"Body_create_job_from_uploads_api_v1_comparisons_jobs_upload_post":{"properties":{"baseline_file":{"type":"string","format":"binary","title":"Baseline File"},"comparison_file":{"type":"string","format":"binary","title":"Comparison File"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"project_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Id"}},"type":"object","required":["baseline_file","comparison_file"],"title":"Body_create_job_from_uploads_api_v1_comparisons_jobs_upload_post"},"Body_create_photo_note_api_v1_user_projects_notes__project_id__photo_post":{"properties":{"title":{"type":"string","title":"Title"},"file":{"type":"string","format":"binary","title":"File"},"room_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Room Id"},"room_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Room Type"}},"type":"object","required":["title","file"],"title":"Body_create_photo_note_api_v1_user_projects_notes__project_id__photo_post"},"Body_create_voice_note_api_v1_user_projects_notes__project_id__voice_post":{"properties":{"title":{"type":"string","title":"Title"},"file":{"type":"string","format":"binary","title":"File"},"room_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Room Id"},"room_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Room Type"}},"type":"object","required":["title","file"],"title":"Body_create_voice_note_api_v1_user_projects_notes__project_id__voice_post"},"Body_eagleview_to_esx_api_v1_roof_eagleview_to_esx_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","required":["file"],"title":"Body_eagleview_to_esx_api_v1_roof_eagleview_to_esx_post"},"Body_generate_from_pdf_json_api_v1_esx_generate_from_pdf_json_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","required":["file"],"title":"Body_generate_from_pdf_json_api_v1_esx_generate_from_pdf_json_post"},"Body_import_xactimate_codes_from_csv_api_v1_intelligent_scope_xactimate_codes_import_csv_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","required":["file"],"title":"Body_import_xactimate_codes_from_csv_api_v1_intelligent_scope_xactimate_codes_import_csv_post"},"Body_ingest_pdf_scope_api_v1_intelligent_scope_training_ingest_pdf_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","required":["file"],"title":"Body_ingest_pdf_scope_api_v1_intelligent_scope_training_ingest_pdf_post"},"Body_parse_estimate_api_v1_completeness_parse_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","required":["file"],"title":"Body_parse_estimate_api_v1_completeness_parse_post"},"Body_parse_estimate_async_api_v1_completeness_parse_async_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"},"project_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Id"},"enable_sketch":{"type":"boolean","title":"Enable Sketch","default":false}},"type":"object","required":["file"],"title":"Body_parse_estimate_async_api_v1_completeness_parse_async_post"},"Body_parse_measurement_report_api_v1_roof_interview_measurements_parse_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","required":["file"],"title":"Body_parse_measurement_report_api_v1_roof_interview_measurements_parse_post"},"Body_preflight_estimate_api_v1_completeness_preflight_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","required":["file"],"title":"Body_preflight_estimate_api_v1_completeness_preflight_post"},"Body_roof_emit_from_upload_api_v1_roof_emit_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"},"project_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Name"}},"type":"object","required":["file"],"title":"Body_roof_emit_from_upload_api_v1_roof_emit_post"},"Body_roof_preview_api_v1_roof_preview_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","required":["file"],"title":"Body_roof_preview_api_v1_roof_preview_post"},"Body_transcribe_audio_route_api_v1_transcribe__post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","required":["file"],"title":"Body_transcribe_audio_route_api_v1_transcribe__post"},"Body_upload_files_api_v1_admin_upload_post":{"properties":{"files":{"items":{"type":"string","format":"binary"},"type":"array","title":"Files"}},"type":"object","required":["files"],"title":"Body_upload_files_api_v1_admin_upload_post"},"BootstrapResponse":{"properties":{"balance":{"type":"integer","title":"Balance"},"granted":{"type":"boolean","title":"Granted"},"email_verified":{"type":"boolean","title":"Email Verified"},"agreement_accepted":{"type":"boolean","title":"Agreement Accepted"},"disposable_blocked":{"type":"boolean","title":"Disposable Blocked"},"signup_code_sent":{"type":"boolean","title":"Signup Code Sent","default":false},"signup_code_pending":{"type":"boolean","title":"Signup Code Pending","default":false}},"type":"object","required":["balance","granted","email_verified","agreement_accepted","disposable_blocked"],"title":"BootstrapResponse"},"BuildingCodeEntry":{"properties":{"code_edition":{"type":"string","title":"Code Edition"},"section":{"type":"string","title":"Section"},"title":{"type":"string","title":"Title"},"content":{"type":"string","title":"Content"},"summary":{"type":"string","title":"Summary"},"jurisdiction":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jurisdiction"},"verified":{"type":"boolean","title":"Verified","default":false}},"type":"object","required":["code_edition","section","title","content","summary"],"title":"BuildingCodeEntry","description":"A cached building code entry."},"BulkActionRequest":{"properties":{"ids":{"items":{"type":"string"},"type":"array","title":"Ids"},"action":{"type":"string","enum":["approve","reject","set_level"],"title":"Action"},"severity":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Severity"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"}},"type":"object","required":["ids","action"],"title":"BulkActionRequest","description":"Bulk operation over a set of suggestion ids."},"BulkActionResponse":{"properties":{"updated":{"type":"integer","title":"Updated"},"ids":{"items":{"type":"string"},"type":"array","title":"Ids"}},"type":"object","required":["updated","ids"],"title":"BulkActionResponse"},"BulkTagCreate":{"properties":{"note_ids":{"items":{"type":"string"},"type":"array","title":"Note Ids","description":"List of photo note IDs to tag"},"tags":{"items":{"$ref":"#/components/schemas/PhotoTagBase"},"type":"array","title":"Tags","description":"List of tags to apply to all photos"}},"type":"object","required":["note_ids","tags"],"title":"BulkTagCreate","description":"Model for bulk tagging multiple photos."},"BulkTagResponse":{"properties":{"success_count":{"type":"integer","title":"Success Count","description":"Number of photos successfully tagged"},"error_count":{"type":"integer","title":"Error Count","description":"Number of photos that failed to be tagged"},"errors":{"items":{"type":"string"},"type":"array","title":"Errors","description":"List of error messages"}},"type":"object","required":["success_count","error_count"],"title":"BulkTagResponse","description":"Response model for bulk tagging operations."},"CSVCodesImportResult":{"properties":{"total":{"type":"integer","title":"Total"},"imported":{"type":"integer","title":"Imported"},"skipped":{"type":"integer","title":"Skipped"},"errors":{"items":{"type":"string"},"type":"array","title":"Errors"}},"type":"object","required":["total","imported","skipped","errors"],"title":"CSVCodesImportResult","description":"Result of importing Xactimate codes from CSV."},"CanonicalItem":{"properties":{"cat":{"type":"string","title":"Cat"},"sel":{"type":"string","title":"Sel"},"activity":{"type":"string","title":"Activity"},"description":{"type":"string","title":"Description","default":""},"room":{"type":"string","title":"Room","default":""},"group_path":{"items":{"type":"string"},"type":"array","title":"Group Path"},"qty":{"type":"number","title":"Qty","default":0.0},"unit":{"type":"string","title":"Unit","default":""},"qty_variable":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Qty Variable"},"labor_hours":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Labor Hours"},"unit_price":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Unit Price"},"is_custom_or_bid":{"type":"boolean","title":"Is Custom Or Bid","default":false},"source_ref":{"type":"string","title":"Source Ref","default":""},"display_description":{"type":"string","title":"Display Description","description":"Description with the ESX ``{V}`` placeholder resolved (B-631).","readOnly":true},"action_label":{"type":"string","title":"Action Label","description":"Human action wording for the activity glyph (B-635).","readOnly":true}},"type":"object","required":["cat","sel","activity","display_description","action_label"],"title":"CanonicalItem","description":"One line item, normalized from either a parsed PDF or a read ESX."},"CarrierRuleset":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"carrier_name":{"type":"string","title":"Carrier Name"},"scope_config":{"$ref":"#/components/schemas/ScopeConfig-Output"},"required_line_items":{"additionalProperties":{"items":{"type":"string"},"type":"array"},"type":"object","title":"Required Line Items","default":{}},"prohibited_line_items":{"items":{"type":"string"},"type":"array","title":"Prohibited Line Items","default":[]},"code_requirements":{"additionalProperties":{"additionalProperties":true,"type":"object"},"type":"object","title":"Code Requirements","default":{}},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"is_active":{"type":"boolean","title":"Is Active","default":true}},"type":"object","required":["carrier_name","scope_config"],"title":"CarrierRuleset","description":"Ruleset for a specific insurance carrier."},"CatalogMissItem":{"properties":{"cat":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cat"},"sel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sel"},"d_g":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"D G"},"xactimate_code":{"type":"string","title":"Xactimate Code"},"description":{"type":"string","title":"Description"},"room_name":{"type":"string","title":"Room Name"},"scope_index":{"type":"integer","title":"Scope Index"}},"type":"object","required":["xactimate_code","description","room_name","scope_index"],"title":"CatalogMissItem","description":"A line item that carried a code but the code is not in plx_items.\n\nPer Decision D, these ARE emitted into the ESX with whatever scope-\nprovided fields exist (cat / sel / dsc / un). Flagged here so the UI\ncan show \"unverified — confirm against your local Xactimate catalog\"."},"CategoryProfile":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"type":{"$ref":"#/components/schemas/CategoryType"},"scope_config":{"$ref":"#/components/schemas/ScopeConfig-Output"},"parent_category_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Parent Category Id"},"rules":{"additionalProperties":true,"type":"object","title":"Rules","default":{}},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"is_active":{"type":"boolean","title":"Is Active","default":true}},"type":"object","required":["name","type","scope_config"],"title":"CategoryProfile","description":"Profile for a category (carrier, contractor, adjuster)."},"CategoryProgress":{"properties":{"category":{"type":"string","title":"Category"},"total_rules":{"type":"integer","title":"Total Rules"},"reviewed_count":{"type":"integer","title":"Reviewed Count"},"pct_complete":{"type":"number","title":"Pct Complete"}},"type":"object","required":["category","total_rules","reviewed_count","pct_complete"],"title":"CategoryProgress"},"CategoryType":{"type":"string","enum":["unaffiliated","carrier","contractor","adjuster","custom"],"title":"CategoryType","description":"Types of user categories."},"ChatRequest":{"properties":{"message":{"type":"string","maxLength":2000,"minLength":2,"title":"Message"}},"type":"object","required":["message"],"title":"ChatRequest"},"ChatbotResponse":{"properties":{"answer":{"type":"string","title":"Answer"},"scope_generated":{"type":"boolean","title":"Scope Generated","default":false},"scope_data":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Scope Data"}},"type":"object","required":["answer"],"title":"ChatbotResponse"},"ChecklistPromptRequest":{"properties":{"room_type":{"type":"string","title":"Room Type","description":"Canonical room type"},"description":{"type":"string","title":"Description","description":"Room damage description text"}},"type":"object","required":["room_type","description"],"title":"ChecklistPromptRequest","description":"Request body for checklist prompts filtering."},"CheckoutRequest":{"properties":{"pack_id":{"type":"string","title":"Pack Id"}},"type":"object","required":["pack_id"],"title":"CheckoutRequest"},"CheckoutResponse":{"properties":{"url":{"type":"string","title":"Url"}},"type":"object","required":["url"],"title":"CheckoutResponse"},"ChunkUpdateRequest":{"properties":{"expert_verified":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Expert Verified"},"confidence_score":{"anyOf":[{"type":"number","maximum":1.0,"minimum":0.0},{"type":"null"}],"title":"Confidence Score"}},"type":"object","title":"ChunkUpdateRequest"},"Circuit":{"properties":{"amps":{"type":"integer","enum":[15,20,30],"title":"Amps","default":20},"count":{"type":"integer","minimum":1.0,"title":"Count","default":1}},"type":"object","title":"Circuit","description":"One available branch circuit the drying setup may use."},"CitationResponse":{"properties":{"source_type":{"type":"string","title":"Source Type"},"reference":{"type":"string","title":"Reference"},"summary":{"type":"string","title":"Summary"},"jurisdiction":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jurisdiction"}},"type":"object","required":["source_type","reference","summary"],"title":"CitationResponse","description":"Citation attached to a rule."},"CitationsResponse":{"properties":{"citations":{"items":{"$ref":"#/components/schemas/RuleCitationItem"},"type":"array","title":"Citations"},"total":{"type":"integer","title":"Total"},"by_source_type":{"additionalProperties":{"type":"integer"},"type":"object","title":"By Source Type"}},"type":"object","required":["citations","total"],"title":"CitationsResponse","description":"Grouped citations response."},"ClaimResponse":{"properties":{"status":{"type":"string","title":"Status"},"code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code"},"credits":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Credits"},"redeemed":{"type":"boolean","title":"Redeemed","default":false}},"type":"object","required":["status"],"title":"ClaimResponse","description":"Result of claiming the credit code for a checkout session."},"CodeOut":{"properties":{"code":{"type":"string","title":"Code"},"credits":{"type":"integer","title":"Credits"},"source":{"type":"string","title":"Source"},"ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ref"},"issued_to_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Issued To Email"},"redeemed_by":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Redeemed By"},"redeemed_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Redeemed At"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At"}},"type":"object","required":["code","credits","source"],"title":"CodeOut"},"CodeProfileResponse":{"properties":{"xactimate_code":{"type":"string","title":"Xactimate Code"},"category":{"type":"string","title":"Category"},"selector":{"type":"string","title":"Selector"},"primary_description":{"type":"string","title":"Primary Description"},"primary_unit":{"type":"string","title":"Primary Unit"},"primary_activity":{"type":"string","title":"Primary Activity"},"occurrence_count":{"type":"integer","title":"Occurrence Count"},"estimate_count":{"type":"integer","title":"Estimate Count"},"avg_quantity":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Avg Quantity"},"is_custom":{"type":"boolean","title":"Is Custom","default":false},"descriptions":{"additionalProperties":{"type":"integer"},"type":"object","title":"Descriptions"},"units":{"additionalProperties":{"type":"integer"},"type":"object","title":"Units"},"activities":{"additionalProperties":{"type":"integer"},"type":"object","title":"Activities"}},"type":"object","required":["xactimate_code","category","selector","primary_description","primary_unit","primary_activity","occurrence_count","estimate_count"],"title":"CodeProfileResponse","description":"Response for a single code profile lookup."},"CodeRequirementResponse":{"properties":{"code_reference":{"type":"string","title":"Code Reference"},"description":{"type":"string","title":"Description"},"severity":{"type":"string","title":"Severity"},"source":{"type":"string","title":"Source"}},"type":"object","required":["code_reference","description","severity","source"],"title":"CodeRequirementResponse","description":"A building code requirement."},"CodeSearchResult":{"properties":{"code":{"$ref":"#/components/schemas/app__services__xactimate_code_manager__XactimateCode"},"relevance":{"type":"number","title":"Relevance"},"matched_field":{"type":"string","title":"Matched Field"}},"type":"object","required":["code","relevance","matched_field"],"title":"CodeSearchResult","description":"Result of searching for Xactimate codes."},"CollapseRequest":{"properties":{"ids":{"items":{"type":"string"},"type":"array","minItems":2,"title":"Ids"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"concern":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Concern"}},"type":"object","required":["ids"],"title":"CollapseRequest","description":"N mined per-code pair ids -> 1 family-rule proposal (originals kept,\nlinked as provenance)."},"CollapseResponse":{"properties":{"rule_id":{"type":"string","title":"Rule Id"},"name":{"type":"string","title":"Name"},"concern":{"type":"string","title":"Concern"},"family":{"type":"string","title":"Family"},"collapsed":{"type":"integer","title":"Collapsed"},"pairs":{"items":{"type":"string"},"type":"array","title":"Pairs"}},"type":"object","required":["rule_id","name","concern","family","collapsed","pairs"],"title":"CollapseResponse"},"CompanionResponse":{"properties":{"trigger_code":{"type":"string","title":"Trigger Code"},"companion_code":{"type":"string","title":"Companion Code"},"companion_description":{"type":"string","title":"Companion Description"},"confidence":{"type":"number","title":"Confidence"},"support":{"type":"integer","title":"Support"}},"type":"object","required":["trigger_code","companion_code","companion_description","confidence","support"],"title":"CompanionResponse","description":"A single companion rule."},"CompanionsResponse":{"properties":{"xactimate_code":{"type":"string","title":"Xactimate Code"},"companions":{"items":{"$ref":"#/components/schemas/CompanionResponse"},"type":"array","title":"Companions"},"count":{"type":"integer","title":"Count"}},"type":"object","required":["xactimate_code","companions","count"],"title":"CompanionsResponse","description":"Response for companion lookup."},"ComparisonCreateResponse":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"report":{"$ref":"#/components/schemas/ComparisonReport"}},"type":"object","required":["id","name","report"],"title":"ComparisonCreateResponse"},"ComparisonDetail":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"project_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Id"},"baseline_source_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Baseline Source Ref"},"comparison_source_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comparison Source Ref"},"decisions":{"additionalProperties":true,"type":"object","title":"Decisions","default":{}},"report":{"$ref":"#/components/schemas/ComparisonReport"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At"},"updated_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Updated At"}},"type":"object","required":["id","name","report"],"title":"ComparisonDetail"},"ComparisonJobStatus":{"properties":{"job_id":{"type":"string","title":"Job Id"},"status":{"type":"string","title":"Status"},"phase":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phase"},"phase_label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phase Label"},"phase_index":{"type":"integer","title":"Phase Index","default":0},"phase_total":{"type":"integer","title":"Phase Total","default":2},"current":{"type":"integer","title":"Current","default":0},"total":{"type":"integer","title":"Total","default":0},"comparison_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comparison Id"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"type":"object","required":["job_id","status"],"title":"ComparisonJobStatus"},"ComparisonListEntry":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"project_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Id"},"baseline_source_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Baseline Source Ref"},"comparison_source_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comparison Source Ref"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At"},"updated_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Updated At"}},"type":"object","required":["id","name"],"title":"ComparisonListEntry"},"ComparisonReport":{"properties":{"baseline_filename":{"type":"string","title":"Baseline Filename"},"comparison_filename":{"type":"string","title":"Comparison Filename"},"baseline_format":{"type":"string","title":"Baseline Format"},"comparison_format":{"type":"string","title":"Comparison Format"},"baseline_price_list":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Baseline Price List"},"comparison_price_list":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comparison Price List"},"whole":{"items":{"$ref":"#/components/schemas/DiffEntry"},"type":"array","title":"Whole"},"agreed":{"items":{"$ref":"#/components/schemas/DiffEntry"},"type":"array","title":"Agreed"},"different":{"items":{"$ref":"#/components/schemas/DiffEntry"},"type":"array","title":"Different"},"room_sections":{"items":{"$ref":"#/components/schemas/RoomSection"},"type":"array","title":"Room Sections"},"themes":{"items":{"$ref":"#/components/schemas/Theme"},"type":"array","title":"Themes"},"suggested_equivalences":{"items":{"$ref":"#/components/schemas/EquivalenceSuggestion"},"type":"array","title":"Suggested Equivalences"},"summary":{"$ref":"#/components/schemas/ReportSummary"},"counts":{"$ref":"#/components/schemas/Counts"},"measurement_groups":{"items":{"$ref":"#/components/schemas/MeasurementGroup"},"type":"array","title":"Measurement Groups"},"warnings":{"items":{"type":"string"},"type":"array","title":"Warnings"},"derive_version":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Derive Version"}},"type":"object","required":["baseline_filename","comparison_filename","baseline_format","comparison_format"],"title":"ComparisonReport","description":"Presentation-ready comparison. Feeds three output modes:\n\n* by-room view          → ``room_sections`` (each room's full A|B scope).\n* whole-estimate view   → ``whole`` (baseline/estimate-A order, each tagged).\n* split-sections view    → ``agreed`` + ``different``."},"ConsensusSummary":{"properties":{"rule_id":{"type":"string","title":"Rule Id"},"rule_name":{"type":"string","title":"Rule Name"},"category":{"type":"string","title":"Category"},"agree_count":{"type":"integer","title":"Agree Count"},"agree_optional_count":{"type":"integer","title":"Agree Optional Count"},"agree_carrier_count":{"type":"integer","title":"Agree Carrier Count"},"contest_count":{"type":"integer","title":"Contest Count"},"needs_discussion_count":{"type":"integer","title":"Needs Discussion Count"},"total_reviews":{"type":"integer","title":"Total Reviews"},"has_discrepancy":{"type":"boolean","title":"Has Discrepancy"},"discussion_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Discussion Status"}},"type":"object","required":["rule_id","rule_name","category","agree_count","agree_optional_count","agree_carrier_count","contest_count","needs_discussion_count","total_reviews","has_discrepancy"],"title":"ConsensusSummary"},"Counts":{"properties":{"baseline_items":{"type":"integer","title":"Baseline Items","default":0},"comparison_items":{"type":"integer","title":"Comparison Items","default":0},"same":{"type":"integer","title":"Same","default":0},"qty_delta":{"type":"integer","title":"Qty Delta","default":0},"variant":{"type":"integer","title":"Variant","default":0},"swap_candidate":{"type":"integer","title":"Swap Candidate","default":0},"custom_price_delta":{"type":"integer","title":"Custom Price Delta","default":0},"added":{"type":"integer","title":"Added","default":0},"removed":{"type":"integer","title":"Removed","default":0},"unmapped":{"type":"integer","title":"Unmapped","default":0},"equivalent":{"type":"integer","title":"Equivalent","default":0}},"type":"object","title":"Counts"},"CraneInputs":{"properties":{"pick_weight_lb":{"type":"number","exclusiveMinimum":0.0,"title":"Pick Weight Lb"},"pick_radius_ft":{"type":"number","exclusiveMinimum":0.0,"title":"Pick Radius Ft"},"tip_height_ft":{"type":"number","exclusiveMinimum":0.0,"title":"Tip Height Ft"},"pick_count":{"type":"integer","minimum":1.0,"title":"Pick Count"},"setup_surface":{"type":"string","enum":["street","lot","soil"],"title":"Setup Surface"},"power_lines_within_20ft":{"type":"boolean","title":"Power Lines Within 20Ft","default":false},"occupied_building":{"type":"boolean","title":"Occupied Building","default":false},"picks_per_day_override":{"anyOf":[{"type":"number","exclusiveMinimum":0.0},{"type":"null"}],"title":"Picks Per Day Override"}},"type":"object","required":["pick_weight_lb","pick_radius_ft","tip_height_ft","pick_count","setup_surface"],"title":"CraneInputs","description":"C1 Crane Estimator inputs."},"CrawlRequest":{"properties":{"target_key":{"type":"string","title":"Target Key","description":"Predefined crawl target key"},"max_pages":{"anyOf":[{"type":"integer","maximum":1000.0,"minimum":1.0},{"type":"null"}],"title":"Max Pages"}},"type":"object","required":["target_key"],"title":"CrawlRequest"},"CreateFromEstimatesRequest":{"properties":{"baseline_parse_hash":{"type":"string","title":"Baseline Parse Hash"},"comparison_parse_hash":{"type":"string","title":"Comparison Parse Hash"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"project_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Id"}},"type":"object","required":["baseline_parse_hash","comparison_parse_hash"],"title":"CreateFromEstimatesRequest","description":"Create a comparison from two estimates the user already imported."},"CreditsConfigOut":{"properties":{"free_line_threshold":{"type":"integer","title":"Free Line Threshold"},"per_conversion":{"type":"integer","title":"Per Conversion"},"per_conversion_over":{"type":"integer","title":"Per Conversion Over"},"sketch_multiplier":{"type":"integer","title":"Sketch Multiplier"},"trial_signup_credits":{"type":"integer","title":"Trial Signup Credits"}},"type":"object","required":["free_line_threshold","per_conversion","per_conversion_over","sketch_multiplier","trial_signup_credits"],"title":"CreditsConfigOut"},"CreditsResponse":{"properties":{"balance":{"type":"integer","title":"Balance"},"agreement_version":{"type":"string","title":"Agreement Version"},"agreement_accepted":{"type":"boolean","title":"Agreement Accepted"},"ledger":{"items":{"$ref":"#/components/schemas/app__api__routes__me__LedgerEntry"},"type":"array","title":"Ledger"}},"type":"object","required":["balance","agreement_version","agreement_accepted","ledger"],"title":"CreditsResponse"},"DebrisInputs":{"properties":{"roofing_squares":{"type":"number","minimum":0.0,"title":"Roofing Squares","default":0},"roofing_layers":{"type":"integer","minimum":1.0,"title":"Roofing Layers","default":1},"drywall_sf":{"type":"number","minimum":0.0,"title":"Drywall Sf","default":0},"carpet_sy":{"type":"number","minimum":0.0,"title":"Carpet Sy","default":0},"framing_lf":{"type":"number","minimum":0.0,"title":"Framing Lf","default":0},"other_cy":{"type":"number","minimum":0.0,"title":"Other Cy","default":0},"direct_cy":{"anyOf":[{"type":"number","exclusiveMinimum":0.0},{"type":"null"}],"title":"Direct Cy"},"dumpster_size_yd":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Dumpster Size Yd"},"weight_limit_tons_override":{"anyOf":[{"type":"number","minimum":0.5},{"type":"null"}],"title":"Weight Limit Tons Override","description":"Hauler-quoted per-load weight limit in tons. Realistic dumpster loads run 1-8 tons; values below 0.5 ton are almost certainly a units mistake (e.g. lb entered instead of tons)."}},"type":"object","title":"DebrisInputs","description":"C6 inputs. Per-material tear-out quantities or direct CY."},"DecisionsPatchRequest":{"properties":{"decisions":{"additionalProperties":true,"type":"object","title":"Decisions"}},"type":"object","required":["decisions"],"title":"DecisionsPatchRequest"},"DiffEntry":{"properties":{"kind":{"$ref":"#/components/schemas/DiffKind"},"cat":{"type":"string","title":"Cat","default":""},"room":{"type":"string","title":"Room","default":""},"baseline":{"anyOf":[{"$ref":"#/components/schemas/CanonicalItem"},{"type":"null"}]},"comparison":{"anyOf":[{"$ref":"#/components/schemas/CanonicalItem"},{"type":"null"}]},"match_tier":{"anyOf":[{"$ref":"#/components/schemas/MatchTier"},{"type":"null"}]},"polarity":{"$ref":"#/components/schemas/Polarity","default":"UNKNOWN"},"room_moved":{"type":"boolean","title":"Room Moved","default":false},"same_surface":{"type":"boolean","title":"Same Surface","default":false},"qty_delta":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Qty Delta"},"qty_ratio":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Qty Ratio"},"qty_delta_kind":{"anyOf":[{"$ref":"#/components/schemas/QtyDeltaKind"},{"type":"null"}]},"measurement_group_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Measurement Group Id"},"unit_price_delta":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Unit Price Delta"},"variant_axis":{"type":"string","title":"Variant Axis","default":""},"whole_building":{"anyOf":[{"$ref":"#/components/schemas/WholeBuildingBreakout"},{"type":"null"}]},"notes":{"items":{"type":"string"},"type":"array","title":"Notes"},"key":{"type":"string","title":"Key","description":"A stable identity for this entry, targeted by wizard decisions.\n\nSerialized so the reconciliation UI can reference a specific swap/pair\nby the SAME key the reconcile layer matches on — no client-side\nre-derivation to drift out of sync.","readOnly":true}},"type":"object","required":["kind","key"],"title":"DiffEntry","description":"One row of the diff. Carries both source items in full when paired, so a\nreport can render the substitution without re-deriving anything."},"DiffKind":{"type":"string","enum":["SAME","QTY_DELTA","VARIANT","SWAP_CANDIDATE","CUSTOM_PRICE_DELTA","ADDED","REMOVED","UNMAPPED","EQUIVALENT"],"title":"DiffKind","description":"Per-entry classification."},"DryingPowerRequest":{"properties":{"equipment":{"items":{"$ref":"#/components/schemas/EquipmentCount"},"type":"array","title":"Equipment"},"circuits":{"items":{"$ref":"#/components/schemas/Circuit"},"type":"array","title":"Circuits"},"service_size_amps":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Service Size Amps"},"drying_days":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Drying Days"},"commercial":{"type":"boolean","title":"Commercial","default":false},"water_mitigation":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Water Mitigation"}},"type":"object","title":"DryingPowerRequest","description":"C7 request. Equipment may be given directly OR carried from a C4\nwater-mitigation package via ``water_mitigation`` (the panel path — the\nfrontend passes the water-mit result straight in)."},"DrywallRoomInputs":{"properties":{"length_ft":{"type":"number","minimum":1.0,"title":"Length Ft"},"width_ft":{"type":"number","minimum":1.0,"title":"Width Ft"},"height_ft":{"type":"number","minimum":1.0,"title":"Height Ft","default":8.0},"openings":{"items":{"$ref":"#/components/schemas/Opening"},"type":"array","title":"Openings"},"scope":{"type":"string","enum":["walls","ceiling","both"],"title":"Scope","default":"both"},"thickness":{"type":"string","enum":["1/2","5/8"],"title":"Thickness","default":"1/2"},"texture":{"type":"string","enum":["none","light_hand","heavy_hand","machine","machine_knockdown","smooth_skim"],"title":"Texture","default":"machine"},"activity":{"type":"string","enum":["replace","patch"],"title":"Activity","default":"replace"},"patch_count":{"type":"integer","minimum":1.0,"title":"Patch Count","default":1},"paint_coats":{"enum":["none",1,2],"title":"Paint Coats","default":2},"water_damage":{"type":"string","enum":["none","clean","cat3","flood_nfip"],"title":"Water Damage","default":"none"},"flood_cut":{"type":"string","enum":["none","2ft","4ft"],"title":"Flood Cut","default":"none"},"baseboard_action":{"type":"string","enum":["none","detach_reset","remove_replace"],"title":"Baseboard Action","default":"detach_reset"},"baseboard_size":{"type":"string","enum":["2_1/4","3_1/4","5_1/4"],"title":"Baseboard Size","default":"3_1/4"},"floor_protection":{"type":"boolean","title":"Floor Protection","default":true}},"type":"object","required":["length_ft","width_ft"],"title":"DrywallRoomInputs","description":"C5 inputs. Room box, openings, scope, finish, water condition."},"EmailLogEntry":{"properties":{"id":{"type":"integer","title":"Id"},"to_email":{"type":"string","title":"To Email"},"template":{"type":"string","title":"Template"},"ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ref"},"status":{"type":"string","title":"Status"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At"}},"type":"object","required":["id","to_email","template","status"],"title":"EmailLogEntry"},"EmailUserRequest":{"properties":{"subject":{"type":"string","maxLength":200,"minLength":1,"title":"Subject"},"body":{"type":"string","maxLength":5000,"minLength":1,"title":"Body"}},"type":"object","required":["subject","body"],"title":"EmailUserRequest"},"EmailUserResponse":{"properties":{"user_id":{"type":"string","title":"User Id"},"to_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To Email"},"emailed":{"type":"boolean","title":"Emailed"},"email_enabled":{"type":"boolean","title":"Email Enabled"}},"type":"object","required":["user_id","emailed","email_enabled"],"title":"EmailUserResponse"},"EntitlementsResponse":{"properties":{"tier":{"type":"string","title":"Tier"},"can_convert":{"type":"boolean","title":"Can Convert"},"can_generate_scope":{"type":"boolean","title":"Can Generate Scope"},"can_enhance":{"type":"boolean","title":"Can Enhance"},"monthly_line_cap":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Monthly Line Cap"},"enforced":{"type":"boolean","title":"Enforced"}},"type":"object","required":["tier","can_convert","can_generate_scope","can_enhance","monthly_line_cap","enforced"],"title":"EntitlementsResponse"},"EquipmentCount":{"properties":{"unit_type":{"type":"string","enum":["air_mover_axial","air_mover_centrifugal","dehu_lgr_small","dehu_lgr_large","dehu_conventional","air_scrubber","heater_electric"],"title":"Unit Type"},"count":{"type":"integer","minimum":0.0,"title":"Count"}},"type":"object","required":["unit_type","count"],"title":"EquipmentCount","description":"A count of one equipment band on the drying job."},"EquivalenceSuggestion":{"properties":{"from_cat":{"type":"string","title":"From Cat","default":""},"from_sel":{"type":"string","title":"From Sel","default":""},"from_activity":{"type":"string","title":"From Activity","default":""},"from_description":{"type":"string","title":"From Description","default":""},"from_room":{"type":"string","title":"From Room","default":""},"from_key":{"type":"string","title":"From Key","default":""},"to_cat":{"type":"string","title":"To Cat","default":""},"to_sel":{"type":"string","title":"To Sel","default":""},"to_description":{"type":"string","title":"To Description","default":""},"to_activity":{"type":"string","title":"To Activity","default":""},"to_room":{"type":"string","title":"To Room","default":""},"to_key":{"type":"string","title":"To Key","default":""},"similarity":{"type":"number","title":"Similarity","default":0.0},"pair_count":{"type":"integer","title":"Pair Count","default":1}},"type":"object","title":"EquivalenceSuggestion","description":"A proposed 'same work, different code' pair for one-click confirmation."},"EstimateLookupResponse":{"properties":{"public_ref":{"type":"string","title":"Public Ref"},"events":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Events"}},"type":"object","required":["public_ref","events"],"title":"EstimateLookupResponse","description":"Support lookup for a single estimate (non-PII event timeline)."},"EvaluateRequest":{"properties":{"facts":{"additionalProperties":true,"type":"object","title":"Facts"},"category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"},"max_depth":{"type":"integer","title":"Max Depth","default":20}},"type":"object","required":["facts"],"title":"EvaluateRequest","description":"Request body for rule evaluation."},"EvaluateResponse":{"properties":{"fired_rules":{"items":{"type":"string"},"type":"array","title":"Fired Rules"},"citations":{"items":{"$ref":"#/components/schemas/CitationResponse"},"type":"array","title":"Citations"},"scope_items":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Scope Items"},"flags":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Flags"},"suggestions":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Suggestions"},"iterations":{"type":"integer","title":"Iterations","default":0}},"type":"object","title":"EvaluateResponse","description":"Response from rule evaluation."},"ExplainResponse":{"properties":{"plain_english":{"type":"string","title":"Plain English"},"from_cache":{"type":"boolean","title":"From Cache"}},"type":"object","required":["plain_english","from_cache"],"title":"ExplainResponse","description":"Response from /explain."},"Facet":{"properties":{"label":{"type":"string","title":"Label","description":"Facet label from the report, e.g. 'A'"},"area_sf":{"type":"number","minimum":0.0,"title":"Area Sf"},"pitch":{"type":"string","title":"Pitch","description":"Pitch as rise string, e.g. '4/12'"}},"type":"object","required":["label","area_sf","pitch"],"title":"Facet","description":"Per-facet row; optional, required only for facet-selection override."},"FeedbackItem":{"properties":{"id":{"type":"integer","title":"Id"},"user_id":{"type":"string","title":"User Id"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"rating":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rating"},"would_pay":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Would Pay"},"body":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body"},"status":{"type":"string","title":"Status"},"run_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Run Ref"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At"},"reviewed_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reviewed At"}},"type":"object","required":["id","user_id","status"],"title":"FeedbackItem"},"FeedbackRequest":{"properties":{"body":{"type":"string","title":"Body"},"rating":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rating"},"would_pay":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Would Pay"},"run_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Run Ref"}},"type":"object","required":["body"],"title":"FeedbackRequest"},"FeedbackResponse":{"properties":{"status":{"type":"string","title":"Status"}},"type":"object","required":["status"],"title":"FeedbackResponse"},"FileResult":{"properties":{"filename":{"type":"string","title":"Filename"},"status":{"$ref":"#/components/schemas/FileStatus"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"line_items_parsed":{"type":"integer","title":"Line Items Parsed","default":0},"rooms_parsed":{"type":"integer","title":"Rooms Parsed","default":0}},"type":"object","required":["filename","status"],"title":"FileResult","description":"Tracking result for a single uploaded file."},"FileStatus":{"type":"string","enum":["queued","processing","done","failed"],"title":"FileStatus","description":"Processing status for a single file in a batch."},"FounderConfigOut":{"properties":{"available":{"type":"boolean","title":"Available"},"remaining":{"type":"integer","title":"Remaining"},"percent_off":{"type":"integer","title":"Percent Off"},"promo_code":{"type":"string","title":"Promo Code"}},"type":"object","required":["available","remaining","percent_off","promo_code"],"title":"FounderConfigOut","description":"Founder-program state for the pricing page.\n\nAttributes:\n    available (bool): Whether founder spots remain (annual auto-discount on).\n    remaining (int): Display-only \"spots left\" count (no live counter).\n    percent_off (int): The founder discount percentage shown to the user.\n    promo_code (str): The typed FOUNDER50 promo code (back-compat / display)."},"FromNaturalLanguageRequest":{"properties":{"description":{"type":"string","minLength":10,"title":"Description"},"available_categories":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Available Categories"},"existing_similar_rules":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Existing Similar Rules"}},"type":"object","required":["description"],"title":"FromNaturalLanguageRequest","description":"Body for POST /from_natural_language.\n\nArgs:\n    description: Admin-supplied plain-English rule description.\n    available_categories: Optional category whitelist passed to the LLM.\n    existing_similar_rules: Optional list of {id, name, description} dicts\n        to discourage duplicate generation."},"FromNaturalLanguageResponse":{"properties":{"rule":{"additionalProperties":true,"type":"object","title":"Rule"},"plain_english_render":{"type":"string","title":"Plain English Render"},"confidence":{"type":"number","title":"Confidence"},"ambiguities":{"items":{"type":"string"},"type":"array","title":"Ambiguities"},"warnings":{"items":{"type":"string"},"type":"array","title":"Warnings"}},"type":"object","required":["rule","plain_english_render","confidence"],"title":"FromNaturalLanguageResponse","description":"Response from the translator endpoint.\n\nThe rule is NOT persisted — the admin must POST to /save_with_render to\nactually save. This separation keeps the review step explicit."},"GeneralConditionItem":{"properties":{"name":{"type":"string","title":"Name"},"category":{"type":"string","title":"Category"},"unit":{"type":"string","title":"Unit"},"typical_range_min":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Typical Range Min"},"typical_range_max":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Typical Range Max"},"citation":{"$ref":"#/components/schemas/CitationResponse"},"confidence":{"type":"number","title":"Confidence"},"needs_verification":{"type":"boolean","title":"Needs Verification","default":true}},"type":"object","required":["name","category","unit","citation","confidence"],"title":"GeneralConditionItem","description":"A suggested general condition."},"GeneralConditionsResponse":{"properties":{"suggestions":{"items":{"$ref":"#/components/schemas/GeneralConditionItem"},"type":"array","title":"Suggestions"},"count":{"type":"integer","title":"Count"}},"type":"object","required":["suggestions","count"],"title":"GeneralConditionsResponse","description":"Response for general conditions suggestions."},"GenerateFromParseRequest":{"properties":{"parse_hash":{"type":"string","title":"Parse Hash","description":"parse_hash returned by /completeness/parse|analyze."},"project_name_override":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Name Override","description":"When given, used as PROJECT_INFO/@name (after sanitization to [A-Z0-9_-]{1,20}). When absent, derived from the parsed estimate metadata or the authenticated user."},"enable_sketch":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Enable Sketch","description":"Opt in to generating a floor-plan sketch for this export. When True, rooms carrying floor SF + perimeter + height get sketch geometry, so the ESX ships a <SKETCHDOCUMENTS> with ManualUpdateAlgorithm:0 → Xactimate opens it calculated/totaled. None falls back to the ESX_SKETCH_ENABLED env default. Multi-room arrangement is still unsolved, so this is opt-in."},"confirm_credits":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Confirm Credits","description":"The credit cost the client showed the user (the credits_required from /completeness/parse). When provided it MUST equal the server-computed cost or the request is rejected 409 (guards against a stale client under-charging). When omitted, the server charges the computed cost (back-compat for older clients)."},"use_flood_profile":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Use Flood Profile","description":"Opt in/out of the FEMA/NFIP flood coverage profile (B-400). When True the ESX ships policyType=2 with the NFIP flood coverages (Building/Property/ICC/…) so it imports already in the flood profile (no manual 'clone to flood'). When False, the carrier profile is forced. None auto-detects: flood losses default ON. Does NOT change unit prices — the pricing profile/price list are identical between carrier and flood."}},"type":"object","required":["parse_hash"],"title":"GenerateFromParseRequest","description":"Body of POST /api/v1/esx/generate-from-parse.\n\nW1 convergence: export the EXACT parse the Supplement page displayed (the\npersisted ``ParsedEstimate`` keyed by user + parse_hash) instead of\nre-parsing the uploaded file with a different pipeline. This makes the\ndownload WYSIWYG with the display."},"GenerateFromScopeJsonResponse":{"properties":{"filename":{"type":"string","title":"Filename"},"esx_b64":{"type":"string","title":"Esx B64","description":"Base64-encoded ESX bytes."},"report":{"$ref":"#/components/schemas/AdapterReport"},"scope_preview":{"anyOf":[{"$ref":"#/components/schemas/ScopePreview"},{"type":"null"}],"description":"Display-only parsed scope for the trial UI."},"run_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Run Ref","description":"Ledger/feedback reference for a metered run."}},"type":"object","required":["filename","esx_b64","report"],"title":"GenerateFromScopeJsonResponse","description":"Fallback JSON response when the caller can't accept octet-stream."},"GenerateFromScopeRequest":{"properties":{"scope_id":{"type":"string","title":"Scope Id","description":"UUID of the persisted scope to convert."},"enable_sketch":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Enable Sketch","description":"Per-request sketch override. True forces the floor-plan sketch, False forces list-mode folders; None (default) follows the ESX_SKETCH_ENABLED env default (ON)."},"project_name_override":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Name Override","description":"When given, used as the estimate's PROJECT_INFO/@name (after sanitization to [A-Z0-9_-]{1,20}). When absent, the adapter derives the name from the authenticated user."},"use_flood_profile":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Use Flood Profile","description":"Opt in/out of the FEMA/NFIP flood coverage profile (B-400). When True the ESX ships policyType=2 with the NFIP flood coverages (Building/Property/ICC/…) so it imports already in the flood profile (no manual 'clone to flood'). When False, the carrier profile is forced. None auto-detects: flood losses default ON. Does NOT change unit prices — the pricing profile/price list are identical between carrier and flood."}},"type":"object","required":["scope_id"],"title":"GenerateFromScopeRequest","description":"Body of POST /api/v1/esx/generate-from-scope."},"GeneratedScope-Input":{"properties":{"rooms":{"items":{"$ref":"#/components/schemas/RoomScope-Input"},"type":"array","title":"Rooms"},"line_items":{"items":{"$ref":"#/components/schemas/ScopeItem-Input"},"type":"array","title":"Line Items"},"code_requirements":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Code Requirements"},"expert_guidelines":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Expert Guidelines"},"sources_used":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Sources Used"},"confidence_score":{"type":"number","maximum":1.0,"minimum":0.0,"title":"Confidence Score"},"generation_metadata":{"additionalProperties":true,"type":"object","title":"Generation Metadata"}},"type":"object","required":["rooms","line_items","code_requirements","expert_guidelines","sources_used","confidence_score","generation_metadata"],"title":"GeneratedScope","description":"Complete generated scope with metadata."},"GeneratedScope-Output":{"properties":{"rooms":{"items":{"$ref":"#/components/schemas/RoomScope-Output"},"type":"array","title":"Rooms"},"line_items":{"items":{"$ref":"#/components/schemas/app__models__scope__ScopeItem"},"type":"array","title":"Line Items"},"code_requirements":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Code Requirements"},"expert_guidelines":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Expert Guidelines"},"sources_used":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Sources Used"},"confidence_score":{"type":"number","maximum":1.0,"minimum":0.0,"title":"Confidence Score"},"generation_metadata":{"additionalProperties":true,"type":"object","title":"Generation Metadata"}},"type":"object","required":["rooms","line_items","code_requirements","expert_guidelines","sources_used","confidence_score","generation_metadata"],"title":"GeneratedScope","description":"Complete generated scope with metadata."},"GenerationPreferences":{"properties":{"default_damage_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Default Damage Type"},"default_jurisdiction":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Default Jurisdiction"},"helpful_mode":{"type":"boolean","title":"Helpful Mode","default":false},"cat3_default":{"type":"boolean","title":"Cat3 Default","default":false}},"type":"object","title":"GenerationPreferences","description":"Defaults applied to new scope-generation runs (Scope Builder, Chat)."},"GrantEntitlementRequest":{"properties":{"feature":{"type":"string","title":"Feature","description":"sketch | scope_gen | enhance | convert"},"expires_days":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Expires Days","description":"Expire in N days; null = never."}},"type":"object","required":["feature"],"title":"GrantEntitlementRequest","description":"Comp a capability to one user (founder's per-user on switch)."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HeadingConfig":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"order":{"type":"integer","title":"Order"},"enabled":{"type":"boolean","title":"Enabled","default":true},"default_categories":{"items":{"type":"string"},"type":"array","title":"Default Categories","default":[]},"override_level":{"$ref":"#/components/schemas/OverrideLevel","default":10}},"type":"object","required":["id","name","order"],"title":"HeadingConfig","description":"Configuration for a scope heading."},"ImportSummary":{"properties":{"parse_hash":{"type":"string","title":"Parse Hash"},"filename":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filename"},"project_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Id"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At"}},"type":"object","required":["parse_hash"],"title":"ImportSummary","description":"One stored import, without its payload."},"IntervalPriceOut":{"properties":{"price_id":{"type":"string","title":"Price Id"},"amount_cents":{"type":"integer","title":"Amount Cents"}},"type":"object","required":["price_id","amount_cents"],"title":"IntervalPriceOut"},"InviteReviewerRequest":{"properties":{"email":{"type":"string","title":"Email"},"disciplines":{"items":{"type":"string"},"type":"array","title":"Disciplines","description":"One or more of: legal, coverage, trade, estimating"}},"type":"object","required":["email","disciplines"],"title":"InviteReviewerRequest"},"LiftInputs":{"properties":{"working_height_ft":{"type":"number","exclusiveMinimum":0.0,"title":"Working Height Ft"},"horizontal_reach_ft":{"type":"number","minimum":0.0,"title":"Horizontal Reach Ft","default":0},"indoor":{"type":"boolean","title":"Indoor","default":false},"surface":{"type":"string","enum":["slab","firm","rough"],"title":"Surface","default":"firm"},"duration_weeks":{"type":"number","exclusiveMinimum":0.0,"title":"Duration Weeks"}},"type":"object","required":["working_height_ft","duration_weeks"],"title":"LiftInputs","description":"C3 Aerial Lift Selector inputs."},"LinkProjectRequest":{"properties":{"project_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Id"}},"type":"object","title":"LinkProjectRequest","description":"Body of POST /imports/{hash}/link-project. None unlinks."},"ManualEntryItem":{"properties":{"description":{"type":"string","title":"Description"},"room_name":{"type":"string","title":"Room Name"},"original_quantity":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Original Quantity"},"original_unit":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Original Unit"},"scope_index":{"type":"integer","title":"Scope Index","description":"0-based index of the item within its source list (room.items or scope.general_conditions / no_match_items)."},"reason":{"type":"string","title":"Reason","description":"Why the item could not be emitted (e.g. 'no_code', 'unparseable_xactimate_code').","default":""}},"type":"object","required":["description","room_name","scope_index"],"title":"ManualEntryItem","description":"A line item the adapter could not emit because no Xactimate code exists.\n\nPer Q1: these are surfaced in the API response (NOT the ESX XML) so the\nUI can prompt the editor to either pick a code manually or refine the\nsource notes."},"MatchTier":{"type":"string","enum":["EXACT_ROOM","EXACT_ESTIMATE","VARIANT_FAMILY","SWAP"],"title":"MatchTier","description":"Which matcher tier produced a matched/paired entry."},"MeasurementGroup":{"properties":{"id":{"type":"integer","title":"Id"},"ratio":{"type":"number","title":"Ratio"},"pair_count":{"type":"integer","title":"Pair Count"},"member_labels":{"items":{"type":"string"},"type":"array","title":"Member Labels"}},"type":"object","required":["id","ratio","pair_count"],"title":"MeasurementGroup","description":"A cluster of ≥4 QTY_DELTA pairs sharing a ratio ≠ 1.0 — a sketch/\nmeasurement difference rather than a scope difference."},"MeasurementSource":{"type":"string","enum":["eagleview","gaf_quickmeasure","roofr","aerialreports","manual","other"],"title":"MeasurementSource"},"MintCodesRequest":{"properties":{"credits":{"type":"integer","maximum":1000.0,"exclusiveMinimum":0.0,"title":"Credits"},"count":{"type":"integer","maximum":50.0,"exclusiveMinimum":0.0,"title":"Count","default":1},"email_to":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email To"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"}},"type":"object","required":["credits"],"title":"MintCodesRequest","description":"Mint one or more admin codes, optionally emailing them out."},"MintCodesResponse":{"properties":{"codes":{"items":{"type":"string"},"type":"array","title":"Codes"},"emailed":{"type":"boolean","title":"Emailed"}},"type":"object","required":["codes","emailed"],"title":"MintCodesResponse"},"NoMatchItemResponse":{"properties":{"activity_description":{"type":"string","title":"Activity Description","default":""},"surface":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Surface"},"material":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Material"},"condition":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Condition"},"room":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Room"},"reason":{"type":"string","title":"Reason","default":""},"suggested_search":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Suggested Search"},"debug":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Debug"}},"type":"object","title":"NoMatchItemResponse","description":"An activity the retrieval pipeline couldn't resolve to a real code."},"Note":{"properties":{"id":{"type":"string","title":"Id"},"project_id":{"type":"string","title":"Project Id"},"content":{"type":"string","title":"Content"},"type":{"type":"string","title":"Type"},"time":{"type":"string","title":"Time"},"audiouri":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Audiouri"},"duration":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Duration"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At"},"updated_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Updated At"},"room_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Room Id"},"room_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Room Type"},"room_geometry":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Room Geometry"},"room_features":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Room Features"}},"type":"object","required":["id","project_id","content","type","time"],"title":"Note"},"NoteCreate":{"properties":{"content":{"type":"string","title":"Content"},"type":{"type":"string","title":"Type","default":"text"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"content_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content Type"},"room_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Room Id"},"room_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Room Type"},"room_geometry":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Room Geometry"},"room_features":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Room Features"}},"type":"object","required":["content"],"title":"NoteCreate"},"NoteUpdate":{"properties":{"content":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Type"},"time":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Time"},"room_geometry":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Room Geometry"},"room_features":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Room Features"}},"type":"object","title":"NoteUpdate"},"Opening":{"properties":{"width_ft":{"type":"number","exclusiveMinimum":0.0,"title":"Width Ft"},"height_ft":{"type":"number","exclusiveMinimum":0.0,"title":"Height Ft"},"kind":{"type":"string","enum":["door","window"],"title":"Kind","default":"door"},"subtract_from_wall":{"type":"boolean","title":"Subtract From Wall","default":true},"trim_action":{"type":"string","enum":["replace","detach_reset","replace_prehung","none"],"title":"Trim Action","default":"replace"}},"type":"object","required":["width_ft","height_ft"],"title":"Opening","description":"A wall opening (door/window)."},"OracleCheck":{"properties":{"label":{"type":"string","title":"Label"},"computed":{"type":"number","title":"Computed"},"published":{"type":"number","title":"Published"},"pct":{"type":"number","title":"Pct"},"within":{"type":"boolean","title":"Within"}},"type":"object","required":["label","computed","published","pct","within"],"title":"OracleCheck","description":"One computed-vs-published metric comparison."},"OverrideLevel":{"type":"integer","enum":[10,20,30,40],"title":"OverrideLevel","description":"Priority levels for rule overrides."},"PackOut":{"properties":{"id":{"type":"string","title":"Id"},"credits":{"type":"integer","title":"Credits"},"amount_cents":{"type":"integer","title":"Amount Cents"},"label":{"type":"string","title":"Label"}},"type":"object","required":["id","credits","amount_cents","label"],"title":"PackOut"},"PacksResponse":{"properties":{"enabled":{"type":"boolean","title":"Enabled"},"packs":{"items":{"$ref":"#/components/schemas/PackOut"},"type":"array","title":"Packs"}},"type":"object","required":["enabled","packs"],"title":"PacksResponse"},"ParseRequest":{"properties":{"text":{"type":"string","maxLength":8000,"minLength":1,"title":"Text"}},"type":"object","required":["text"],"title":"ParseRequest"},"PendingCode":{"properties":{"code":{"type":"string","title":"Code"},"credits":{"type":"integer","title":"Credits"},"source":{"type":"string","title":"Source"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At"}},"type":"object","required":["code","credits","source"],"title":"PendingCode"},"PhotoMetadata":{"properties":{"url":{"type":"string","title":"Url","description":"URL or path to the photo"},"filename":{"type":"string","title":"Filename","description":"Original filename"},"size_bytes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Size Bytes","description":"File size in bytes"},"content_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content Type","description":"MIME type"},"timestamp":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Timestamp","description":"When photo was taken"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags","description":"Photo tags/categories"},"analysis_results":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Analysis Results","description":"AI analysis results"}},"type":"object","required":["url","filename"],"title":"PhotoMetadata","description":"Metadata for uploaded photos."},"PhotoTag":{"properties":{"category_id":{"type":"string","title":"Category Id","description":"Main category ID (overview, damage, materials, etc.)"},"subcategory_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subcategory Id","description":"Optional subcategory within the main category"},"room_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Room Id","description":"Optional room identifier where photo was taken"},"damage_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Damage Type","description":"Optional damage type classification"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes","description":"Optional free-form text notes about the photo"},"id":{"type":"string","title":"Id","description":"Unique tag identifier"},"note_id":{"type":"string","title":"Note Id","description":"ID of the photo note this tag belongs to"},"created_at":{"type":"string","format":"date-time","title":"Created At","description":"When the tag was created"},"updated_at":{"type":"string","format":"date-time","title":"Updated At","description":"When the tag was last updated"}},"type":"object","required":["category_id","id","note_id","created_at","updated_at"],"title":"PhotoTag","description":"Complete photo tag model with all fields."},"PhotoTagBase":{"properties":{"category_id":{"type":"string","title":"Category Id","description":"Main category ID (overview, damage, materials, etc.)"},"subcategory_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subcategory Id","description":"Optional subcategory within the main category"},"room_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Room Id","description":"Optional room identifier where photo was taken"},"damage_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Damage Type","description":"Optional damage type classification"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes","description":"Optional free-form text notes about the photo"}},"type":"object","required":["category_id"],"title":"PhotoTagBase","description":"Base model for photo tags with shared attributes."},"PhotoTagCreate":{"properties":{"category_id":{"type":"string","title":"Category Id","description":"Main category ID (overview, damage, materials, etc.)"},"subcategory_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subcategory Id","description":"Optional subcategory within the main category"},"room_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Room Id","description":"Optional room identifier where photo was taken"},"damage_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Damage Type","description":"Optional damage type classification"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes","description":"Optional free-form text notes about the photo"}},"type":"object","required":["category_id"],"title":"PhotoTagCreate","description":"Model for creating a new photo tag."},"PhotoTagUpdate":{"properties":{"category_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category Id"},"subcategory_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subcategory Id"},"room_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Room Id"},"damage_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Damage Type"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"}},"type":"object","title":"PhotoTagUpdate","description":"Model for updating an existing photo tag."},"PhotoWithTags":{"properties":{"note_id":{"type":"string","title":"Note Id","description":"Photo note ID"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title","description":"Photo title/filename"},"file_path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"File Path","description":"File path or URL"},"created_at":{"type":"string","format":"date-time","title":"Created At","description":"When the photo was created"},"tags":{"items":{"$ref":"#/components/schemas/PhotoTag"},"type":"array","title":"Tags","description":"Associated tags"}},"type":"object","required":["note_id","created_at"],"title":"PhotoWithTags","description":"Model representing a photo with its associated tags."},"PitchArea":{"properties":{"pitch":{"type":"string","title":"Pitch","description":"Pitch as rise string, e.g. '4/12'; '0/12' allowed"},"area_sf":{"type":"number","minimum":0.0,"title":"Area Sf","description":"Roof area at this pitch, square feet"}},"type":"object","required":["pitch","area_sf"],"title":"PitchArea","description":"One row of the areas-per-pitch table."},"Polarity":{"type":"string","enum":["UPGRADE","DOWNGRADE","UNKNOWN"],"title":"Polarity"},"PortalRequest":{"properties":{"customer_id":{"type":"string","title":"Customer Id"}},"type":"object","required":["customer_id"],"title":"PortalRequest"},"ProgressSummary":{"properties":{"total_rules":{"type":"integer","title":"Total Rules"},"total_reviewed":{"type":"integer","title":"Total Reviewed"},"pct_complete":{"type":"number","title":"Pct Complete"},"categories":{"items":{"$ref":"#/components/schemas/CategoryProgress"},"type":"array","title":"Categories"}},"type":"object","required":["total_rules","total_reviewed","pct_complete","categories"],"title":"ProgressSummary"},"Project":{"properties":{"id":{"type":"string","title":"Id"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"address":{"type":"string","title":"Address"},"street":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Street"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"zip":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Zip"},"owner_name":{"type":"string","title":"Owner Name"},"owner_phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Owner Phone"},"owner_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Owner Email"},"claim_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Claim Number"},"policy_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Policy Number"},"date_of_loss":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date Of Loss"},"date_of_inspection":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date Of Inspection"},"ahj":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ahj"},"latitude":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Latitude"},"longitude":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Longitude"},"damage_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Damage Type"},"claim_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Claim Type"},"loss_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Loss Type"},"policy_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Policy Type"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At"},"created_by":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created By"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"},"project_type":{"type":"string","title":"Project Type","default":"residential"}},"type":"object","required":["id","address","owner_name"],"title":"Project"},"ProjectContext":{"properties":{"project_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Id","description":"Project identifier"},"project_name":{"type":"string","title":"Project Name","description":"Human-readable project name"},"project_type":{"$ref":"#/components/schemas/ProjectType","description":"Type of project/claim"},"property_address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Property Address","description":"Property address"},"claim_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Claim Number","description":"Insurance claim number"},"adjuster_info":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Adjuster Info","description":"Adjuster contact information"},"incident_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Incident Date","description":"Date of incident/damage"},"additional_context":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Additional Context","description":"Additional context or notes"}},"type":"object","required":["project_name","project_type"],"title":"ProjectContext","description":"Context information about the project."},"ProjectCreate":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address"},"street":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Street"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"zip":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Zip"},"owner_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Owner Name"},"owner_phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Owner Phone"},"owner_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Owner Email"},"claim_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Claim Number"},"policy_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Policy Number"},"date_of_loss":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date Of Loss"},"date_of_inspection":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date Of Inspection"},"ahj":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ahj"},"latitude":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Latitude"},"longitude":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Longitude"},"damage_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Damage Type"},"claim_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Claim Type"},"loss_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Loss Type"},"policy_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Policy Type"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"},"project_type":{"type":"string","enum":["residential","commercial"],"title":"Project Type","default":"residential"}},"type":"object","title":"ProjectCreate"},"ProjectType":{"type":"string","enum":["water_damage","fire_damage","storm_damage","mold_remediation","general_repair","other"],"title":"ProjectType","description":"Types of insurance claims/projects."},"ProjectUpdate":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address"},"street":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Street"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"zip":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Zip"},"owner_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Owner Name"},"owner_phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Owner Phone"},"owner_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Owner Email"},"claim_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Claim Number"},"policy_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Policy Number"},"date_of_loss":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date Of Loss"},"date_of_inspection":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date Of Inspection"},"ahj":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ahj"},"latitude":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Latitude"},"longitude":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Longitude"},"damage_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Damage Type"},"claim_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Claim Type"},"loss_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Loss Type"},"policy_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Policy Type"},"project_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Type"}},"type":"object","title":"ProjectUpdate"},"ProvenanceResponse":{"properties":{"source_type":{"type":"string","title":"Source Type"},"reference":{"type":"string","title":"Reference"},"summary":{"type":"string","title":"Summary"},"applicable_text":{"type":"string","title":"Applicable Text","default":""},"confidence":{"type":"number","title":"Confidence","default":1.0},"authority_rank":{"type":"integer","title":"Authority Rank","default":3},"is_first_occurrence":{"type":"boolean","title":"Is First Occurrence","default":true}},"type":"object","required":["source_type","reference","summary"],"title":"ProvenanceResponse","description":"Provenance metadata for a scope line item in API response."},"QtyDeltaKind":{"type":"string","enum":["DISCRETE","MEASUREMENT_GROUP"],"title":"QtyDeltaKind"},"RedeemCodeRequest":{"properties":{"code":{"type":"string","title":"Code"}},"type":"object","required":["code"],"title":"RedeemCodeRequest"},"RedeemCodeResponse":{"properties":{"status":{"type":"string","title":"Status"},"balance":{"type":"integer","title":"Balance"},"credits":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Credits"}},"type":"object","required":["status","balance"],"title":"RedeemCodeResponse"},"ReportSummary":{"properties":{"agreed":{"type":"integer","title":"Agreed","default":0},"contested":{"type":"integer","title":"Contested","default":0},"added":{"type":"integer","title":"Added","default":0},"removed":{"type":"integer","title":"Removed","default":0},"unmapped":{"type":"integer","title":"Unmapped","default":0},"total_items":{"type":"integer","title":"Total Items","default":0},"total_different":{"type":"integer","title":"Total Different","default":0}},"type":"object","title":"ReportSummary","description":"Header tallies for the report (agreed / contested / added / dropped)."},"ResolveDiscrepancyRequest":{"properties":{"resolution":{"type":"string","title":"Resolution"},"new_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"New Status"},"new_severity":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"New Severity"}},"type":"object","required":["resolution"],"title":"ResolveDiscrepancyRequest"},"ReviewFeedbackRequest":{"properties":{"action":{"type":"string","title":"Action","description":"reward | dismiss"},"credits":{"type":"integer","maximum":100.0,"exclusiveMinimum":0.0,"title":"Credits","default":1}},"type":"object","required":["action"],"title":"ReviewFeedbackRequest","description":"Resolve a feedback item: reward it (grant credits) or dismiss it."},"ReviewFeedbackResponse":{"properties":{"id":{"type":"integer","title":"Id"},"status":{"type":"string","title":"Status"},"credits_granted":{"type":"integer","title":"Credits Granted"},"balance":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Balance"}},"type":"object","required":["id","status","credits_granted"],"title":"ReviewFeedbackResponse"},"RoofDescriptionRequest":{"properties":{"description":{"type":"string","title":"Description","description":"Roof description (dimensions required)."},"project_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Name","description":"Optional ESX project name."}},"type":"object","required":["description"],"title":"RoofDescriptionRequest","description":"A free-text roof description, e.g. '6/12 gable 40x24'."},"RoofEmitResponse":{"properties":{"filename":{"type":"string","title":"Filename","description":"Suggested download filename (Decision 0011)."},"project_name":{"type":"string","title":"Project Name"},"esx_base64":{"type":"string","title":"Esx Base64","description":"The .ESX archive, base64-encoded."},"roof_type":{"type":"integer","title":"Roof Type"},"roof_kind":{"type":"string","title":"Roof Kind"},"length_ft":{"type":"number","title":"Length Ft"},"width_ft":{"type":"number","title":"Width Ft"},"pitch":{"type":"number","title":"Pitch"},"self_check_passed":{"type":"boolean","title":"Self Check Passed","description":"True if the emitted geometry re-derives to the spec within 2%."}},"type":"object","required":["filename","project_name","esx_base64","roof_type","roof_kind","length_ft","width_ft","pitch","self_check_passed"],"title":"RoofEmitResponse","description":"An emitted, importable `.ESX` (base64) plus the emitted roof's summary."},"RoofInterviewPreviewError":{"properties":{"code":{"type":"string","title":"Code"},"message":{"type":"string","title":"Message"}},"type":"object","required":["code","message"],"title":"RoofInterviewPreviewError"},"RoofInterviewPreviewRequest":{"properties":{"measurements":{"$ref":"#/components/schemas/RoofMeasurements-Input"},"answers":{"additionalProperties":true,"type":"object","title":"Answers"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"zip_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Zip Code"}},"type":"object","required":["measurements"],"title":"RoofInterviewPreviewRequest","description":"Measurements + answers-so-far from the web interview UI."},"RoofInterviewPreviewResponse":{"properties":{"profile_id":{"type":"string","title":"Profile Id"},"questions":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Questions"},"effective_answers":{"additionalProperties":true,"type":"object","title":"Effective Answers"},"system":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"System"},"result":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Result"},"error":{"anyOf":[{"$ref":"#/components/schemas/RoofInterviewPreviewError"},{"type":"null"}]}},"type":"object","required":["profile_id","questions","effective_answers"],"title":"RoofInterviewPreviewResponse"},"RoofLengths":{"properties":{"ridge_lf":{"type":"number","minimum":0.0,"title":"Ridge Lf","default":0},"hip_lf":{"type":"number","minimum":0.0,"title":"Hip Lf","default":0},"valley_lf":{"type":"number","minimum":0.0,"title":"Valley Lf","default":0},"rake_lf":{"type":"number","minimum":0.0,"title":"Rake Lf","default":0},"eave_lf":{"type":"number","minimum":0.0,"title":"Eave Lf","default":0},"drip_edge_lf":{"type":"number","minimum":0.0,"title":"Drip Edge Lf","default":0},"flashing_lf":{"type":"number","minimum":0.0,"title":"Flashing Lf","default":0},"step_flashing_lf":{"type":"number","minimum":0.0,"title":"Step Flashing Lf","default":0},"parapet_lf":{"type":"number","minimum":0.0,"title":"Parapet Lf","default":0}},"type":"object","title":"RoofLengths","description":"Linear-foot measurements from the report summary. All LFs >= 0."},"RoofMeasurements-Input":{"properties":{"source":{"$ref":"#/components/schemas/MeasurementSource"},"report_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Report Id"},"report_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Report Date"},"property_address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Property Address"},"total_area_sf":{"type":"number","exclusiveMinimum":0.0,"title":"Total Area Sf"},"facet_count":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Facet Count"},"stories":{"type":"integer","minimum":1.0,"title":"Stories","default":1},"predominant_pitch":{"type":"string","title":"Predominant Pitch","description":"Pitch as rise string, e.g. '6/12'"},"areas_by_pitch":{"items":{"$ref":"#/components/schemas/PitchArea"},"type":"array","minItems":1,"title":"Areas By Pitch"},"lengths":{"$ref":"#/components/schemas/RoofLengths"},"facets":{"anyOf":[{"items":{"$ref":"#/components/schemas/Facet"},"type":"array"},{"type":"null"}],"title":"Facets","description":"Optional; required for facet-selection override"},"waste":{"anyOf":[{"$ref":"#/components/schemas/Waste"},{"type":"null"}]},"source_document_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Document Ref","description":"Pointer to the stored source PDF"},"schema_version":{"type":"integer","title":"Schema Version","default":1}},"type":"object","required":["source","total_area_sf","predominant_pitch","areas_by_pitch"],"title":"RoofMeasurements","description":"RoofMeasurements v1 (schema_version=1)."},"RoofMeasurements-Output":{"properties":{"source":{"$ref":"#/components/schemas/MeasurementSource"},"report_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Report Id"},"report_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Report Date"},"property_address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Property Address"},"total_area_sf":{"type":"number","exclusiveMinimum":0.0,"title":"Total Area Sf"},"facet_count":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Facet Count"},"stories":{"type":"integer","minimum":1.0,"title":"Stories","default":1},"predominant_pitch":{"type":"string","title":"Predominant Pitch","description":"Pitch as rise string, e.g. '6/12'"},"areas_by_pitch":{"items":{"$ref":"#/components/schemas/PitchArea"},"type":"array","minItems":1,"title":"Areas By Pitch"},"lengths":{"$ref":"#/components/schemas/RoofLengths"},"facets":{"anyOf":[{"items":{"$ref":"#/components/schemas/Facet"},"type":"array"},{"type":"null"}],"title":"Facets","description":"Optional; required for facet-selection override"},"waste":{"anyOf":[{"$ref":"#/components/schemas/Waste"},{"type":"null"}]},"source_document_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Document Ref","description":"Pointer to the stored source PDF"},"schema_version":{"type":"integer","title":"Schema Version","default":1}},"type":"object","required":["source","total_area_sf","predominant_pitch","areas_by_pitch"],"title":"RoofMeasurements","description":"RoofMeasurements v1 (schema_version=1)."},"RoofMeasurementsParseResponse":{"properties":{"measurements":{"$ref":"#/components/schemas/RoofMeasurements-Output"},"dialect":{"type":"string","title":"Dialect"},"stored":{"type":"boolean","title":"Stored","default":false}},"type":"object","required":["measurements","dialect"],"title":"RoofMeasurementsParseResponse"},"RoofPreviewResponse":{"properties":{"filename":{"type":"string","title":"Filename"},"source_format":{"type":"string","title":"Source Format","description":"\"EagleView\" | \"Hover\" | raw root tag."},"svg":{"type":"string","title":"Svg","description":"Top-down 2D roof plan as an inline SVG string."},"total_roof_area_sf":{"type":"number","title":"Total Roof Area Sf"},"plan_width_ft":{"type":"number","title":"Plan Width Ft"},"plan_height_ft":{"type":"number","title":"Plan Height Ft"},"edge_lengths_ft":{"additionalProperties":{"type":"number"},"type":"object","title":"Edge Lengths Ft","description":"Σ 3D edge length by type (EAVE/RAKE/RIDGE/HIP/VALLEY)."},"has_summary":{"type":"boolean","title":"Has Summary","description":"True if the file published an OVERALL_SUMMARY to cross-check."},"oracle_passed":{"type":"boolean","title":"Oracle Passed","description":"True if every published metric agrees within 2% (full dialect)."},"oracle":{"items":{"$ref":"#/components/schemas/OracleCheck"},"type":"array","title":"Oracle"}},"type":"object","required":["filename","source_format","svg","total_roof_area_sf","plan_width_ft","plan_height_ft","edge_lengths_ft","has_summary","oracle_passed","oracle"],"title":"RoofPreviewResponse","description":"Rendered 2D roof plan + derived/validated totals for on-screen display."},"RoomQty":{"properties":{"room":{"type":"string","title":"Room"},"qty":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Qty"},"unit":{"type":"string","title":"Unit","default":""}},"type":"object","required":["room"],"title":"RoomQty","description":"One per-room placement of a distributed code (B-662 breakout row)."},"RoomScope-Input":{"properties":{"room_name":{"type":"string","title":"Room Name"},"damage_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Damage Type"},"line_items":{"items":{"$ref":"#/components/schemas/ScopeItem-Input"},"type":"array","title":"Line Items"},"special_requirements":{"items":{"type":"string"},"type":"array","title":"Special Requirements","default":[]}},"type":"object","required":["room_name","line_items"],"title":"RoomScope","description":"Scope for a specific room or area."},"RoomScope-Output":{"properties":{"room_name":{"type":"string","title":"Room Name"},"damage_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Damage Type"},"line_items":{"items":{"$ref":"#/components/schemas/app__models__scope__ScopeItem"},"type":"array","title":"Line Items"},"special_requirements":{"items":{"type":"string"},"type":"array","title":"Special Requirements","default":[]}},"type":"object","required":["room_name","line_items"],"title":"RoomScope","description":"Scope for a specific room or area."},"RoomScopeDetailResponse":{"properties":{"room":{"anyOf":[{"$ref":"#/components/schemas/RoomScopeResponse"},{"type":"null"}]},"checklist_prompts":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Checklist Prompts","default":[]},"validation_issues":{"items":{"$ref":"#/components/schemas/ValidationIssueResponse"},"type":"array","title":"Validation Issues","default":[]},"questions":{"items":{"type":"string"},"type":"array","title":"Questions","default":[]},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata","default":{}}},"type":"object","title":"RoomScopeDetailResponse","description":"Response from per-room scope generation."},"RoomScopeItemResponse":{"properties":{"xactimate_code":{"type":"string","title":"Xactimate Code"},"description":{"type":"string","title":"Description"},"activity":{"type":"string","title":"Activity"},"unit":{"type":"string","title":"Unit"},"frequency":{"type":"number","title":"Frequency"},"avg_quantity":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Avg Quantity"},"order_position":{"type":"number","title":"Order Position"}},"type":"object","required":["xactimate_code","description","activity","unit","frequency","order_position"],"title":"RoomScopeItemResponse","description":"A single item in a room template."},"RoomScopeRequest":{"properties":{"room_description":{"type":"string","title":"Room Description","description":"Natural language description of damage in this room"},"room_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Room Type","description":"Canonical room type or free text (system maps to standard)"},"damage_type":{"type":"string","title":"Damage Type","description":"Primary damage type: water, fire, wind, hail, mold, flood, storm"},"claim_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Claim Type","description":"homeowner, flood, commercial"},"jurisdiction":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jurisdiction","description":"ZIP code for building code compliance"},"measurements":{"anyOf":[{"additionalProperties":{"type":"number"},"type":"object"},{"type":"null"}],"title":"Measurements","description":"Optional room measurements: length, width, height in feet"},"cat3_toggle":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Cat3 Toggle","description":"Cat 3 water toggle override. None = auto-infer from damage_type."},"helpful_mode":{"type":"boolean","title":"Helpful Mode","description":"Whether to return checklist prompts for unmentioned elements","default":false},"debug_trace":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Debug Trace","description":"Dev only — when true AND env DEV_SCOPE_DEBUG=1, attach a pipeline-trace `debug` block to every line item / no-match. Silently ignored in prod.","default":false}},"type":"object","required":["room_description","damage_type"],"title":"RoomScopeRequest","description":"Request to generate scope for a single room."},"RoomScopeResponse":{"properties":{"room_name":{"type":"string","title":"Room Name"},"room_type":{"type":"string","title":"Room Type"},"items":{"items":{"$ref":"#/components/schemas/ScopeLineItemResponse"},"type":"array","title":"Items"},"notes":{"items":{"type":"string"},"type":"array","title":"Notes","default":[]},"no_match_items":{"items":{"$ref":"#/components/schemas/NoMatchItemResponse"},"type":"array","title":"No Match Items","default":[]},"measurements":{"additionalProperties":{"type":"number"},"type":"object","title":"Measurements","default":{}},"traced_polygon_inches":{"anyOf":[{"items":{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2},"type":"array"},{"type":"null"}],"title":"Traced Polygon Inches"}},"type":"object","required":["room_name","room_type","items"],"title":"RoomScopeResponse","description":"Scope for a single room.\n\n``measurements`` mirrors ``RoomScope.measurements`` ({length,width,height}\nin decimal feet). The web client persists this DTO verbatim into\n``scopes.scope_data``, and the ESX export re-hydrates ``GeneratedScope``\nfrom it — without this field every room falls back to the 12×12×8\ndefault box at export time."},"RoomSection":{"properties":{"room":{"type":"string","title":"Room"},"key":{"type":"string","title":"Key"},"entries":{"items":{"$ref":"#/components/schemas/DiffEntry"},"type":"array","title":"Entries"},"agreed":{"type":"integer","title":"Agreed","default":0},"different":{"type":"integer","title":"Different","default":0},"a_total":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"A Total"},"b_total":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"B Total"}},"type":"object","required":["room","key"],"title":"RoomSection","description":"One room's full scope, A vs B together — how estimators read (B-630)."},"RoomSectionInput":{"properties":{"room":{"type":"string","title":"Room","description":"Room name or type (e.g. 'Master Bedroom', 'Kitchen')"},"text":{"type":"string","title":"Text","description":"Damage description for this room"},"measurements":{"anyOf":[{"additionalProperties":{"type":"number"},"type":"object"},{"type":"null"}],"title":"Measurements","description":"Structured room dimensions in feet (length/width/height); drives deterministic quantity calculation."},"water_depth_interior_in":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Water Depth Interior In","description":"Interior standing-water depth (inches)"},"water_category":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Water Category","description":"IICRC water category (1/2/3). On an armed flood_nfip claim this is FORCED to 3 server-side (SFIP flood is Cat-3 by definition); the client does not send it."},"water_quality_desc":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Water Quality Desc","description":"Free-form water-quality description (e.g. 'saltwater, silt'); lands in the per-room F9 flood note."},"area_class":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Area Class","description":"NFIP area class: basement | enclosure_below_lef | above_lef | crawlspace | garage_attached"},"geometry":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Geometry","description":"App-captured RoomGeometry jsonb (frontend/storage/schemas.ts): primary {length,width,height} ft, optional second rectangle (L-shape) with offsetX/offsetY, and openings [{type: door|window|opening, width, height, opensInto}]. Drives ESX sketch openings/adjacency and true L-shape quantities."},"features":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Features","description":"App-captured RoomFeature rows (kind: cabinet|countertop|appliance|plumbing_fixture|wet_area + kind-specific fields). Directive: each generates scope activities resolved via the codes service."}},"type":"object","required":["room","text"],"title":"RoomSectionInput","description":"A per-room note section for structured scope generation."},"RoomTemplateResponse":{"properties":{"room_type":{"type":"string","title":"Room Type"},"damage_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Damage Type"},"sample_count":{"type":"integer","title":"Sample Count"},"items":{"items":{"$ref":"#/components/schemas/RoomScopeItemResponse"},"type":"array","title":"Items"},"item_count":{"type":"integer","title":"Item Count"}},"type":"object","required":["room_type","sample_count","items","item_count"],"title":"RoomTemplateResponse","description":"Response for room template lookup."},"RoomTypeInfo":{"properties":{"room_type":{"type":"string","title":"Room Type"},"template_count":{"type":"integer","title":"Template Count"},"damage_types":{"items":{"type":"string"},"type":"array","title":"Damage Types"}},"type":"object","required":["room_type","template_count","damage_types"],"title":"RoomTypeInfo","description":"Info about an available room type."},"RoomTypesResponse":{"properties":{"room_types":{"items":{"$ref":"#/components/schemas/RoomTypeInfo"},"type":"array","title":"Room Types"},"total":{"type":"integer","title":"Total"}},"type":"object","required":["room_types","total"],"title":"RoomTypesResponse","description":"Response for listing available room types."},"RuleCitationItem":{"properties":{"rule_name":{"type":"string","title":"Rule Name"},"source_type":{"type":"string","title":"Source Type"},"reference":{"type":"string","title":"Reference"},"summary":{"type":"string","title":"Summary"},"jurisdiction":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jurisdiction"}},"type":"object","required":["rule_name","source_type","reference","summary"],"title":"RuleCitationItem","description":"A citation entry with its rule name."},"RuleDetail":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"type":"string","title":"Description"},"category":{"type":"string","title":"Category"},"priority":{"type":"integer","title":"Priority"},"conditions":{"additionalProperties":true,"type":"object","title":"Conditions"},"actions":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Actions"},"citation":{"anyOf":[{"$ref":"#/components/schemas/CitationResponse"},{"type":"null"}]},"produces_facts":{"items":{"type":"string"},"type":"array","title":"Produces Facts"},"jurisdictions":{"items":{"type":"string"},"type":"array","title":"Jurisdictions"},"damage_types":{"items":{"type":"string"},"type":"array","title":"Damage Types"},"is_active":{"type":"boolean","title":"Is Active"},"version":{"type":"integer","title":"Version"},"rule_type":{"type":"string","title":"Rule Type","default":"trigger"},"status":{"type":"string","title":"Status","default":"active"},"severity":{"type":"string","title":"Severity","default":"should"},"domains":{"items":{"type":"string"},"type":"array","title":"Domains"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"citations":{"items":{"$ref":"#/components/schemas/CitationResponse"},"type":"array","title":"Citations"},"plain_english_render":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Plain English Render"}},"type":"object","required":["id","name","description","category","priority","is_active","version"],"title":"RuleDetail","description":"Full rule detail including conditions and actions."},"RuleForReview":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"plain_english_render":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Plain English Render"},"description":{"type":"string","title":"Description"},"category":{"type":"string","title":"Category"},"domains":{"items":{"type":"string"},"type":"array","title":"Domains"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"citations":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Citations"},"status":{"type":"string","title":"Status"},"severity":{"type":"string","title":"Severity"},"rule_type":{"type":"string","title":"Rule Type"},"my_decision":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"My Decision"},"my_comment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"My Comment"},"my_contest_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"My Contest Reason"},"is_discipline_match":{"type":"boolean","title":"Is Discipline Match","default":false}},"type":"object","required":["id","name","description","category","status","severity","rule_type"],"title":"RuleForReview","description":"A rule card presented to a reviewer."},"RuleListItem":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"type":"string","title":"Description"},"category":{"type":"string","title":"Category"},"priority":{"type":"integer","title":"Priority"},"citation":{"anyOf":[{"$ref":"#/components/schemas/CitationResponse"},{"type":"null"}]},"is_active":{"type":"boolean","title":"Is Active"},"rule_type":{"type":"string","title":"Rule Type","default":"trigger"},"status":{"type":"string","title":"Status","default":"active"},"severity":{"type":"string","title":"Severity","default":"should"},"domains":{"items":{"type":"string"},"type":"array","title":"Domains"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"citations":{"items":{"$ref":"#/components/schemas/CitationResponse"},"type":"array","title":"Citations"},"plain_english_render":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Plain English Render"}},"type":"object","required":["id","name","description","category","priority","is_active"],"title":"RuleListItem","description":"Summary of a rule for list endpoints.\n\nPhase 0 (PRP-001) adds rule_type, status, severity, domains, tags,\ncitations[] alongside the legacy fields. Frontend can adopt the new\nfields opportunistically; the legacy fields remain populated."},"RulePriority":{"type":"integer","enum":[1,2,3,4],"title":"RulePriority","description":"Priority levels for rule application."},"RuleTraceEntry":{"properties":{"id":{"type":"string","title":"Id"},"rule_id":{"type":"string","title":"Rule Id"},"rule_version":{"type":"integer","title":"Rule Version"},"rule_name":{"type":"string","title":"Rule Name"},"rule_type":{"type":"string","title":"Rule Type"},"rule_severity":{"type":"string","title":"Rule Severity"},"current_rule_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Rule Status"},"evaluation_phase":{"type":"string","title":"Evaluation Phase"},"target_item_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Target Item Id"},"fired_at":{"type":"string","title":"Fired At"},"conditions_matched":{"additionalProperties":true,"type":"object","title":"Conditions Matched","default":{}},"actions_emitted":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Actions Emitted","default":[]},"rationale_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rationale Text"}},"type":"object","required":["id","rule_id","rule_version","rule_name","rule_type","rule_severity","evaluation_phase","fired_at"],"title":"RuleTraceEntry","description":"One persisted rule-firing entry returned by the trace API."},"RuleTraceResponse":{"properties":{"scope_id":{"type":"string","title":"Scope Id"},"project_id":{"type":"string","title":"Project Id"},"generated_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Generated At"},"trace_count":{"type":"integer","title":"Trace Count"},"traces":{"items":{"$ref":"#/components/schemas/RuleTraceEntry"},"type":"array","title":"Traces","default":[]},"pre_phase3":{"type":"boolean","title":"Pre Phase3","default":false}},"type":"object","required":["scope_id","project_id","trace_count"],"title":"RuleTraceResponse","description":"Response shape for GET /scopes/{scope_id}/rule-trace."},"RuleTrigger":{"type":"string","enum":["always","damage_type","jurisdiction","property_type","carrier","manual"],"title":"RuleTrigger","description":"Triggers for when rules should be applied."},"RuleType":{"type":"string","enum":["dependent_item","code_requirement","quantity_calculation","alternative_item","exclusion","inclusion","condition"],"title":"RuleType","description":"Types of Xactimate rules."},"RuleUpdateRequest":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"},"priority":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Priority"},"conditions":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Conditions"},"actions":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Actions"},"citations":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Citations"},"produces_facts":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Produces Facts"},"jurisdictions":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Jurisdictions"},"damage_types":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Damage Types"},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"},"rule_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rule Type"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"},"severity":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Severity"},"domains":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Domains"},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Tags"},"change_summary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Change Summary"}},"type":"object","title":"RuleUpdateRequest","description":"Partial update payload for PUT /rules/{id}.\n\nAll fields are optional — only those present are applied. Server\nvalidates the merged shape against the Rule model before persisting.\n\n`change_summary` is metadata for the audit log; not stored on the rule."},"RulesStatsResponse":{"properties":{"total_rules":{"type":"integer","title":"Total Rules"},"active_rules":{"type":"integer","title":"Active Rules"},"rules_by_category":{"additionalProperties":{"type":"integer"},"type":"object","title":"Rules By Category"},"rules_by_source_type":{"additionalProperties":{"type":"integer"},"type":"object","title":"Rules By Source Type"},"general_conditions_count":{"type":"integer","title":"General Conditions Count"},"building_code_cache_count":{"type":"integer","title":"Building Code Cache Count"}},"type":"object","required":["total_rules","active_rules","general_conditions_count","building_code_cache_count"],"title":"RulesStatsResponse","description":"Rules system statistics."},"SaveWithRenderRequest":{"properties":{"rule":{"additionalProperties":true,"type":"object","title":"Rule"},"plain_english_render":{"type":"string","title":"Plain English Render","default":""}},"type":"object","required":["rule"],"title":"SaveWithRenderRequest","description":"Body for POST /save_with_render."},"SaveWithRenderResponse":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"saved":{"type":"boolean","title":"Saved","default":true}},"type":"object","required":["id","name"],"title":"SaveWithRenderResponse","description":"Response from the save endpoint."},"ScaffoldInputs":{"properties":{"facade_lengths_ft":{"items":{"type":"number"},"type":"array","minItems":1,"title":"Facade Lengths Ft"},"height_ft":{"type":"number","exclusiveMinimum":0.0,"title":"Height Ft"},"working_levels":{"type":"integer","minimum":1.0,"title":"Working Levels"},"duration_weeks":{"type":"number","exclusiveMinimum":0.0,"title":"Duration Weeks"},"config":{"type":"string","enum":["frame","system"],"title":"Config","default":"frame"},"debris_netting":{"type":"boolean","title":"Debris Netting","default":false}},"type":"object","required":["facade_lengths_ft","height_ft","working_levels","duration_weeks"],"title":"ScaffoldInputs","description":"C2 Scaffold Calculator inputs."},"ScenarioRequest":{"properties":{"answers":{"additionalProperties":true,"type":"object","title":"Answers"},"derived_overrides":{"additionalProperties":{"type":"number"},"type":"object","title":"Derived Overrides"}},"type":"object","title":"ScenarioRequest","description":"Interview answers plus any user edits to derived values."},"ScopeCompanion":{"properties":{"code":{"type":"string","title":"Code"},"description":{"type":"string","title":"Description"},"confidence":{"type":"number","title":"Confidence"}},"type":"object","required":["code","description","confidence"],"title":"ScopeCompanion","description":"Companion info embedded in a scope suggestion."},"ScopeConfig-Input":{"properties":{"structure_type":{"$ref":"#/components/schemas/ScopeStructureType","default":"top_down"},"headings":{"items":{"$ref":"#/components/schemas/HeadingConfig"},"type":"array","title":"Headings","default":[]},"override_level":{"$ref":"#/components/schemas/OverrideLevel","default":10},"damage_type_mapping":{"additionalProperties":{"$ref":"#/components/schemas/ScopeStructureType"},"type":"object","title":"Damage Type Mapping"}},"type":"object","title":"ScopeConfig","description":"Configuration for scope structure."},"ScopeConfig-Output":{"properties":{"structure_type":{"$ref":"#/components/schemas/ScopeStructureType","default":"top_down"},"headings":{"items":{"$ref":"#/components/schemas/HeadingConfig"},"type":"array","title":"Headings","default":[]},"override_level":{"$ref":"#/components/schemas/OverrideLevel","default":10},"damage_type_mapping":{"additionalProperties":{"$ref":"#/components/schemas/ScopeStructureType"},"type":"object","title":"Damage Type Mapping"}},"type":"object","title":"ScopeConfig","description":"Configuration for scope structure."},"ScopeDraftPutRequest":{"properties":{"draft":{"additionalProperties":true,"type":"object","title":"Draft"}},"type":"object","required":["draft"],"title":"ScopeDraftPutRequest","description":"Request body for upserting a Scope Builder form draft."},"ScopeDraftResponse":{"properties":{"draft":{"additionalProperties":true,"type":"object","title":"Draft"},"updated_at":{"type":"string","title":"Updated At"}},"type":"object","required":["draft","updated_at"],"title":"ScopeDraftResponse","description":"A stored Scope Builder form draft."},"ScopeItem-Input":{"properties":{"description":{"type":"string","title":"Description"},"category":{"type":"string","title":"Category"},"quantity":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Quantity"},"unit":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Unit"},"code_requirements":{"items":{"type":"string"},"type":"array","title":"Code Requirements","default":[]},"expert_notes":{"items":{"type":"string"},"type":"array","title":"Expert Notes","default":[]},"confidence_score":{"type":"number","maximum":1.0,"minimum":0.0,"title":"Confidence Score"}},"type":"object","required":["description","category","confidence_score"],"title":"ScopeItem","description":"Individual line item in a scope."},"ScopeLineItemResponse":{"properties":{"xactimate_code":{"type":"string","title":"Xactimate Code"},"description":{"type":"string","title":"Description"},"activity":{"type":"string","title":"Activity"},"quantity":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Quantity"},"variable":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Variable"},"surface":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Surface"},"sequence":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Sequence"},"qty_variable":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Qty Variable"},"needs_qty_verification":{"type":"boolean","title":"Needs Qty Verification","default":false},"needs_type_verification":{"type":"boolean","title":"Needs Type Verification","default":false},"type_alternatives":{"items":{"type":"string"},"type":"array","title":"Type Alternatives","default":[]},"unit":{"type":"string","title":"Unit"},"confidence":{"type":"string","title":"Confidence"},"source":{"type":"string","title":"Source"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"},"reasoning":{"type":"string","title":"Reasoning","default":""},"provenance":{"anyOf":[{"$ref":"#/components/schemas/ProvenanceResponse"},{"type":"null"}]},"needs_review":{"type":"boolean","title":"Needs Review","default":false},"review_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Review Reason"},"provenance_tag":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provenance Tag"},"debug":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Debug"},"helpful_annotation":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Helpful Annotation"}},"type":"object","required":["xactimate_code","description","activity","unit","confidence","source"],"title":"ScopeLineItemResponse","description":"A line item in the generated scope."},"ScopeListItem":{"properties":{"id":{"type":"string","title":"Id"},"project_id":{"type":"string","title":"Project Id"},"scope_data":{"additionalProperties":true,"type":"object","title":"Scope Data"},"source":{"type":"string","title":"Source"},"created_at":{"type":"string","title":"Created At"},"updated_at":{"type":"string","title":"Updated At"}},"type":"object","required":["id","project_id","scope_data","source","created_at","updated_at"],"title":"ScopeListItem","description":"A scope entry in a list response."},"ScopePreview":{"properties":{"rooms":{"items":{"$ref":"#/components/schemas/ScopePreviewRoom"},"type":"array","title":"Rooms"},"room_count":{"type":"integer","title":"Room Count","default":0},"item_count":{"type":"integer","title":"Item Count","default":0},"review_count":{"type":"integer","title":"Review Count","default":0}},"type":"object","title":"ScopePreview","description":"Faithful, display-only view of the converted scope for the trial page."},"ScopePreviewItem":{"properties":{"description":{"type":"string","title":"Description"},"quantity":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Quantity"},"unit":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Unit"},"code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code"},"needs_review":{"type":"boolean","title":"Needs Review","default":false},"review_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Review Reason"}},"type":"object","required":["description"],"title":"ScopePreviewItem","description":"One line item as shown to the user — read-only projection."},"ScopePreviewRoom":{"properties":{"name":{"type":"string","title":"Name"},"items":{"items":{"$ref":"#/components/schemas/ScopePreviewItem"},"type":"array","title":"Items"}},"type":"object","required":["name"],"title":"ScopePreviewRoom"},"ScopeSaveRequest":{"properties":{"scope_data":{"additionalProperties":true,"type":"object","title":"Scope Data"},"source":{"type":"string","title":"Source","default":"web"},"rule_trace":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Rule Trace"}},"type":"object","required":["scope_data"],"title":"ScopeSaveRequest","description":"Request body for saving a scope to a project."},"ScopeSaveResponse":{"properties":{"id":{"type":"string","title":"Id"},"project_id":{"type":"string","title":"Project Id"},"scope_data":{"additionalProperties":true,"type":"object","title":"Scope Data"},"source":{"type":"string","title":"Source"},"created_at":{"type":"string","title":"Created At"},"updated_at":{"type":"string","title":"Updated At"}},"type":"object","required":["id","project_id","scope_data","source","created_at","updated_at"],"title":"ScopeSaveResponse","description":"Response after saving a scope."},"ScopeStructureType":{"type":"string","enum":["top_down","bottom_up"],"title":"ScopeStructureType","description":"Types of scope structure organization."},"ScopeSuggestionItem":{"properties":{"xactimate_code":{"type":"string","title":"Xactimate Code"},"description":{"type":"string","title":"Description"},"activity":{"type":"string","title":"Activity"},"unit":{"type":"string","title":"Unit"},"frequency":{"type":"number","title":"Frequency"},"avg_quantity":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Avg Quantity"},"companions":{"items":{"$ref":"#/components/schemas/ScopeCompanion"},"type":"array","title":"Companions"}},"type":"object","required":["xactimate_code","description","activity","unit","frequency"],"title":"ScopeSuggestionItem","description":"A single scope suggestion item."},"ScopeValidationRequest":{"properties":{"scope":{"$ref":"#/components/schemas/GeneratedScope-Input"},"property_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Property Type"},"damage_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Damage Type"},"jurisdiction":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jurisdiction"},"address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address"}},"type":"object","required":["scope"],"title":"ScopeValidationRequest","description":"Request body for validating a scope."},"SearchFilters":{"properties":{"trade_categories":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Trade Categories"},"jurisdictions":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Jurisdictions"},"content_types":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Content Types"},"min_confidence":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Confidence"},"expert_verified_only":{"type":"boolean","title":"Expert Verified Only","default":false},"source_types":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Source Types"}},"type":"object","title":"SearchFilters"},"SearchRequest":{"properties":{"query":{"type":"string","title":"Query","description":"Search query"},"filters":{"anyOf":[{"$ref":"#/components/schemas/SearchFilters"},{"type":"null"}]},"limit":{"type":"integer","maximum":50.0,"minimum":1.0,"title":"Limit","default":10},"similarity_threshold":{"type":"number","maximum":1.0,"minimum":0.0,"title":"Similarity Threshold","default":0.5}},"type":"object","required":["query"],"title":"SearchRequest"},"SearchResponse":{"properties":{"results":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Results"},"total_results":{"type":"integer","title":"Total Results"},"query_time_ms":{"type":"integer","title":"Query Time Ms"},"sources_searched":{"items":{"type":"string"},"type":"array","title":"Sources Searched"}},"type":"object","required":["results","total_results","query_time_ms","sources_searched"],"title":"SearchResponse"},"SourceCreateRequest":{"properties":{"name":{"type":"string","title":"Name","description":"Human-readable name for the source"},"url":{"type":"string","title":"Url","description":"Base URL to crawl"},"source_type":{"type":"string","pattern":"^(building_code|industry_guide|best_practice|expert_knowledge|xactimate_help)$","title":"Source Type","description":"Type of source"},"jurisdiction":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jurisdiction","description":"Jurisdiction (International, State, Local)"},"trade_category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Trade Category","description":"Trade category"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description","description":"Description of the source"}},"type":"object","required":["name","url","source_type"],"title":"SourceCreateRequest"},"SourceResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"url":{"type":"string","title":"Url"},"source_type":{"type":"string","title":"Source Type"},"jurisdiction":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jurisdiction"},"trade_category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Trade Category"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"is_active":{"type":"boolean","title":"Is Active"},"total_chunks":{"type":"integer","title":"Total Chunks"},"verified_chunks":{"type":"integer","title":"Verified Chunks"},"avg_chunk_confidence":{"type":"number","title":"Avg Chunk Confidence"},"last_crawled_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Crawled At"},"crawl_status":{"type":"string","title":"Crawl Status"}},"type":"object","required":["id","name","url","source_type","jurisdiction","trade_category","description","is_active","total_chunks","verified_chunks","avg_chunk_confidence","last_crawled_at","crawl_status"],"title":"SourceResponse"},"StatisticsResponse":{"properties":{"total_sources":{"type":"integer","title":"Total Sources"},"active_sources":{"type":"integer","title":"Active Sources"},"total_chunks":{"type":"integer","title":"Total Chunks"},"verified_chunks":{"type":"integer","title":"Verified Chunks"},"avg_confidence":{"type":"number","title":"Avg Confidence"},"trade_distribution":{"additionalProperties":{"type":"integer"},"type":"object","title":"Trade Distribution"},"recent_searches":{"type":"integer","title":"Recent Searches"},"search_quality":{"additionalProperties":{"type":"number"},"type":"object","title":"Search Quality"}},"type":"object","required":["total_sources","active_sources","total_chunks","verified_chunks","avg_confidence","trade_distribution","recent_searches","search_quality"],"title":"StatisticsResponse"},"StatsResponse":{"properties":{"total_codes":{"type":"integer","title":"Total Codes"},"total_estimates":{"type":"integer","title":"Total Estimates"},"co_occurrences":{"type":"integer","title":"Co Occurrences"},"always_write_rules":{"type":"integer","title":"Always Write Rules"},"quantity_relationships":{"type":"integer","title":"Quantity Relationships"},"room_templates":{"type":"integer","title":"Room Templates"},"data_loaded":{"type":"boolean","title":"Data Loaded"}},"type":"object","required":["total_codes","total_estimates","co_occurrences","always_write_rules","quantity_relationships","room_templates","data_loaded"],"title":"StatsResponse","description":"Response for corpus statistics."},"StructuredScopeResponse":{"properties":{"scope_items":{"items":{"$ref":"#/components/schemas/app__models__unified_payload__ScopeItem"},"type":"array","title":"Scope Items","description":"List of identified scope items"},"potential_gaps":{"items":{"type":"string"},"type":"array","title":"Potential Gaps","description":"Potential missing items"},"followup_questions":{"items":{"type":"string"},"type":"array","title":"Followup Questions","description":"Questions for clarification"},"ai_suggestions":{"items":{"type":"string"},"type":"array","title":"Ai Suggestions","description":"AI recommendations"},"xactimate_codes":{"items":{"$ref":"#/components/schemas/app__models__unified_payload__XactimateCode"},"type":"array","title":"Xactimate Codes","description":"Mapped Xactimate codes"},"processing_time_seconds":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Processing Time Seconds","description":"Time taken to process"},"ai_model_used":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ai Model Used","description":"AI model identifier"},"confidence_score":{"type":"number","title":"Confidence Score","description":"Overall confidence in the scope (0-1)","default":0.8},"processed_at":{"type":"string","format":"date-time","title":"Processed At","description":"Processing timestamp"}},"type":"object","required":["scope_items"],"title":"StructuredScopeResponse","description":"Structured response from AI processing."},"SubmitReviewRequest":{"properties":{"decision":{"type":"string","title":"Decision"},"comment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comment"},"contest_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contest Reason"}},"type":"object","required":["decision"],"title":"SubmitReviewRequest"},"SubmitReviewResponse":{"properties":{"rule_id":{"type":"string","title":"Rule Id"},"decision":{"type":"string","title":"Decision"},"saved":{"type":"boolean","title":"Saved"}},"type":"object","required":["rule_id","decision","saved"],"title":"SubmitReviewResponse"},"SubscribeRequest":{"properties":{"tier":{"type":"string","title":"Tier","default":"A"},"interval":{"type":"string","title":"Interval","default":"month"}},"type":"object","title":"SubscribeRequest","description":"Subscription checkout request.\n\nAttributes:\n    tier (str): One of \"A\", \"B\", \"C\" (10/20/40 credits/mo).\n    interval (str): \"month\" or \"annual\" (\"year\" is accepted as an alias for\n        \"annual\"). Defaults to \"month\" for back-compat with callers that omit\n        it. Annual sessions enable FOUNDER50; monthly keep the intro coupon."},"SuggestResponse":{"properties":{"room_type":{"type":"string","title":"Room Type"},"damage_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Damage Type"},"suggestions":{"items":{"$ref":"#/components/schemas/ScopeSuggestionItem"},"type":"array","title":"Suggestions"},"count":{"type":"integer","title":"Count"}},"type":"object","required":["room_type","suggestions","count"],"title":"SuggestResponse","description":"Response for scope suggestions."},"SuggestionListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/SuggestionRow"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"}},"type":"object","required":["items","total"],"title":"SuggestionListResponse","description":"Paginated list of suggestions plus the total matching count."},"SuggestionRow":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"type":"string","title":"Description"},"rule_type":{"type":"string","title":"Rule Type"},"severity":{"type":"string","title":"Severity"},"status":{"type":"string","title":"Status"},"source_corpus":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Corpus"},"confidence":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Confidence"},"support":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Support"},"authority_tier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authority Tier"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"plain_english_render":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Plain English Render"},"conditions":{"additionalProperties":true,"type":"object","title":"Conditions"},"actions":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Actions"},"citation":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Citation"},"headline":{"type":"string","title":"Headline"}},"type":"object","required":["id","name","description","rule_type","severity","status","headline"],"title":"SuggestionRow","description":"A mined draft rule presented in the review queue."},"SuggestionStats":{"properties":{"total":{"type":"integer","title":"Total"},"by_source":{"additionalProperties":{"type":"integer"},"type":"object","title":"By Source"},"by_severity":{"additionalProperties":{"type":"integer"},"type":"object","title":"By Severity"},"by_rule_type":{"additionalProperties":{"type":"integer"},"type":"object","title":"By Rule Type"}},"type":"object","required":["total"],"title":"SuggestionStats","description":"Aggregate counts over the proposed-suggestion queue."},"SupplementRequest":{"properties":{"scope_id":{"type":"string","title":"Scope Id","description":"UUID of the saved scope to supplement"},"notes":{"type":"string","title":"Notes","description":"Additional field notes (what's new / what you found)"},"damage_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Damage Type"},"jurisdiction":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jurisdiction"},"property_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Property Type"},"cat3_toggle":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Cat3 Toggle"}},"type":"object","required":["scope_id","notes"],"title":"SupplementRequest","description":"Request body for supplementing an existing saved scope with new notes."},"TagStatistics":{"properties":{"total_tags":{"type":"integer","title":"Total Tags","description":"Total number of tags"},"tags_by_category":{"additionalProperties":true,"type":"object","title":"Tags By Category","description":"Tag count grouped by category"},"tags_by_room":{"additionalProperties":true,"type":"object","title":"Tags By Room","description":"Tag count grouped by room"},"tags_by_damage_type":{"additionalProperties":true,"type":"object","title":"Tags By Damage Type","description":"Tag count grouped by damage type"},"most_used_categories":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Most Used Categories","description":"Most frequently used categories"}},"type":"object","required":["total_tags","tags_by_category","tags_by_room","tags_by_damage_type","most_used_categories"],"title":"TagStatistics","description":"Model for tag usage statistics."},"Theme":{"properties":{"kind":{"$ref":"#/components/schemas/ThemeKind"},"title":{"type":"string","title":"Title"},"summary":{"type":"string","title":"Summary"},"direction":{"type":"string","title":"Direction","default":""},"item_count":{"type":"integer","title":"Item Count","default":0},"amount":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Amount"},"evidence":{"items":{"$ref":"#/components/schemas/ThemeEvidence"},"type":"array","title":"Evidence"},"groups":{"items":{"$ref":"#/components/schemas/ThemeGroup"},"type":"array","title":"Groups"}},"type":"object","required":["kind","title","summary"],"title":"Theme","description":"A methodology theme with its grounded supporting evidence."},"ThemeEvidence":{"properties":{"room":{"type":"string","title":"Room","default":""},"code":{"type":"string","title":"Code","default":""},"description":{"type":"string","title":"Description","default":""},"detail":{"type":"string","title":"Detail","default":""},"amount":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Amount"},"a_code":{"type":"string","title":"A Code","default":""},"b_code":{"type":"string","title":"B Code","default":""},"a_description":{"type":"string","title":"A Description","default":""},"b_description":{"type":"string","title":"B Description","default":""},"unit":{"type":"string","title":"Unit","default":""},"a_qty":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"A Qty"},"b_qty":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"B Qty"},"axis":{"type":"string","title":"Axis","default":""}},"type":"object","title":"ThemeEvidence","description":"One line item supporting a theme — real code, room, and the delta fact."},"ThemeGroup":{"properties":{"axis":{"type":"string","title":"Axis","default":""},"a_code":{"type":"string","title":"A Code","default":""},"b_code":{"type":"string","title":"B Code","default":""},"a_description":{"type":"string","title":"A Description","default":""},"b_description":{"type":"string","title":"B Description","default":""},"descriptions_match":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Descriptions Match"},"unit":{"type":"string","title":"Unit","default":""},"room_count":{"type":"integer","title":"Room Count","default":0},"item_count":{"type":"integer","title":"Item Count","default":0},"a_qty_total":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"A Qty Total"},"b_qty_total":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"B Qty Total"},"amount":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Amount"},"pattern":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pattern"},"ratio":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Ratio"},"evidence":{"items":{"$ref":"#/components/schemas/ThemeEvidence"},"type":"array","title":"Evidence"}},"type":"object","title":"ThemeGroup","description":"A theme's evidence rolled up by CODE (B-657): the aggregate + drill-down.\n\nThe founder reads differences by code, not by room — e.g. \"WTR PLASN — 1,240\nSF, $X across 6 rooms\", expandable to the per-room lines. For grade/quality\nand substitution groups both codes + descriptions are carried so a reviewer\ncan see whether the two codes actually mean the same thing (B-658/B-659)."},"ThemeKind":{"type":"string","enum":["WATER_REMEDIATION","HEIGHT_COVERAGE","GRADE_QUALITY","SUBSTITUTION","ADDED_SCOPE","OMITTED_SCOPE","QUANTITY","PRICE_LIST","SKETCH"],"title":"ThemeKind","description":"The methodology buckets a difference set rolls up into."},"TierOut":{"properties":{"tier":{"type":"string","title":"Tier"},"credits_per_month":{"type":"integer","title":"Credits Per Month"},"monthly":{"$ref":"#/components/schemas/IntervalPriceOut"},"annual":{"$ref":"#/components/schemas/IntervalPriceOut"}},"type":"object","required":["tier","credits_per_month","monthly","annual"],"title":"TierOut"},"TopCodesResponse":{"properties":{"codes":{"items":{"$ref":"#/components/schemas/CodeProfileResponse"},"type":"array","title":"Codes"},"total_codes":{"type":"integer","title":"Total Codes"}},"type":"object","required":["codes","total_codes"],"title":"TopCodesResponse","description":"Response for top codes listing."},"TrainingDataSource":{"type":"string","enum":["sample_scope","user_feedback","expert_input","system_generated","external_database"],"title":"TrainingDataSource","description":"Sources of training data."},"TrainingDataStats":{"properties":{"total_examples":{"type":"integer","title":"Total Examples","default":0},"by_type":{"additionalProperties":{"type":"integer"},"propertyNames":{"$ref":"#/components/schemas/TrainingDataType"},"type":"object","title":"By Type"},"by_source":{"additionalProperties":{"type":"integer"},"propertyNames":{"$ref":"#/components/schemas/TrainingDataSource"},"type":"object","title":"By Source"},"avg_quality":{"type":"number","title":"Avg Quality","default":0.0},"validated_percent":{"type":"number","title":"Validated Percent","default":0.0},"abbreviation_count":{"type":"integer","title":"Abbreviation Count","default":0},"xactimate_code_count":{"type":"integer","title":"Xactimate Code Count","default":0},"scope_pattern_count":{"type":"integer","title":"Scope Pattern Count","default":0},"last_updated":{"type":"string","format":"date-time","title":"Last Updated"}},"type":"object","title":"TrainingDataStats","description":"Statistics about the training data."},"TrainingDataType":{"type":"string","enum":["field_notes","scope","abbreviation","xactimate_code","building_code","expert_guideline","room_hierarchy","clarification_question"],"title":"TrainingDataType","description":"Types of training data for the multi-agent system."},"UnifiedPayload":{"properties":{"notes":{"items":{"type":"string"},"type":"array","title":"Notes","description":"Text notes and descriptions"},"photos":{"items":{"$ref":"#/components/schemas/PhotoMetadata"},"type":"array","title":"Photos","description":"Photo metadata"},"project_context":{"$ref":"#/components/schemas/ProjectContext","description":"Project context information"},"user_preferences":{"anyOf":[{"$ref":"#/components/schemas/UserPreferences-Input"},{"type":"null"}],"description":"User processing preferences"}},"type":"object","required":["notes","project_context"],"title":"UnifiedPayload","description":"Unified payload for AI processing requests."},"UnitOfMeasurement":{"type":"string","enum":["EA","SF","LF","SY","SQ","HR","WK","RL","BF","CY","GL","PR","CF","TN","IN","DA","MO","BG","BX","RM"],"title":"UnitOfMeasurement","description":"Units of measurement used in Xactimate."},"UploadResponse":{"properties":{"batch_id":{"type":"string","title":"Batch Id"},"files_accepted":{"type":"integer","title":"Files Accepted"},"status":{"type":"string","title":"Status"}},"type":"object","required":["batch_id","files_accepted","status"],"title":"UploadResponse","description":"Response returned immediately after accepting an upload."},"UsageResponse":{"properties":{"tier":{"type":"string","title":"Tier"},"monthly_line_cap":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Monthly Line Cap"},"lines_used":{"type":"integer","title":"Lines Used"}},"type":"object","required":["tier","monthly_line_cap","lines_used"],"title":"UsageResponse"},"UserCreditsResponse":{"properties":{"user_id":{"type":"string","title":"User Id"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"email_verified_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email Verified At"},"balance":{"type":"integer","title":"Balance"},"recent_ledger":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Recent Ledger"},"pending_codes":{"items":{"$ref":"#/components/schemas/CodeOut"},"type":"array","title":"Pending Codes"}},"type":"object","required":["user_id","balance","recent_ledger","pending_codes"],"title":"UserCreditsResponse","description":"A user's credit standing for the admin panel."},"UserPreferences-Input":{"properties":{"include_xactimate_codes":{"type":"boolean","title":"Include Xactimate Codes","description":"Include Xactimate line item codes","default":true},"detail_level":{"type":"string","title":"Detail Level","description":"Level of detail: basic, medium, detailed","default":"medium"},"preferred_units":{"type":"string","title":"Preferred Units","description":"Measurement units: imperial, metric","default":"imperial"},"include_material_suggestions":{"type":"boolean","title":"Include Material Suggestions","description":"Include material suggestions","default":true},"include_cost_estimates":{"type":"boolean","title":"Include Cost Estimates","description":"Include rough cost estimates","default":false},"custom_instructions":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Custom Instructions","description":"Custom processing instructions"}},"type":"object","title":"UserPreferences","description":"User preferences for AI processing."},"UserPreferences-Output":{"properties":{"scope_config":{"$ref":"#/components/schemas/ScopeConfig-Output"},"generation":{"$ref":"#/components/schemas/GenerationPreferences"},"default_category_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Default Category Id"},"preferred_units":{"additionalProperties":{"type":"string"},"type":"object","title":"Preferred Units","default":{}},"auto_apply_code_requirements":{"type":"boolean","title":"Auto Apply Code Requirements","default":true},"show_clarification_questions":{"type":"boolean","title":"Show Clarification Questions","default":true},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["scope_config"],"title":"UserPreferences","description":"User preferences for scope generation."},"UserProfile":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"email":{"type":"string","title":"Email"},"picture":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Picture"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"company":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company"},"preferences":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Preferences"}},"type":"object","required":["email"],"title":"UserProfile"},"UserProfileUpdate":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"company":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company"},"preferences":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Preferences"}},"type":"object","title":"UserProfileUpdate"},"ValidationCategory":{"type":"string","enum":["xactimate_code","quantity_unit","consistency","action_code","location_code","hallucination","measurement","dependency","building_code","calculation"],"title":"ValidationCategory","description":"Categories of validation checks."},"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"},"ValidationIssue":{"properties":{"category":{"$ref":"#/components/schemas/ValidationCategory"},"severity":{"$ref":"#/components/schemas/ValidationSeverity"},"message":{"type":"string","title":"Message"},"location":{"type":"string","title":"Location"},"item_description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Item Description"},"xactimate_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Xactimate Code"},"suggested_fix":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Suggested Fix"},"reference":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reference"},"confidence":{"type":"number","maximum":1.0,"minimum":0.0,"title":"Confidence"}},"type":"object","required":["category","severity","message","location","confidence"],"title":"ValidationIssue","description":"Represents a validation issue found in the scope."},"ValidationIssueResponse":{"properties":{"severity":{"type":"string","title":"Severity"},"message":{"type":"string","title":"Message"},"room":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Room"},"xactimate_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Xactimate Code"},"suggestion":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Suggestion"},"source":{"type":"string","title":"Source","default":"validator"},"category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"},"confidence":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Confidence"},"needs_human_review":{"type":"boolean","title":"Needs Human Review","default":false},"model_used":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model Used"}},"type":"object","required":["severity","message"],"title":"ValidationIssueResponse","description":"A validation issue found during scope generation.\n\n`source` distinguishes rule-based findings (`\"validator\"` — the existing\npost-build validator agent) from PRP-008 AI reviewer findings\n(`\"ai_reviewer\"`). Defaults to `\"validator\"` for backward compatibility."},"ValidationResult":{"properties":{"valid":{"type":"boolean","title":"Valid","default":true},"issues":{"items":{"$ref":"#/components/schemas/ValidationIssue"},"type":"array","title":"Issues","default":[]},"confidence_score":{"type":"number","maximum":1.0,"minimum":0.0,"title":"Confidence Score"},"validated_at":{"type":"string","format":"date-time","title":"Validated At"},"execution_time":{"type":"number","title":"Execution Time","default":0.0},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata","default":{}}},"type":"object","required":["confidence_score"],"title":"ValidationResult","description":"Results of the accuracy validation process."},"ValidationSeverity":{"type":"string","enum":["info","warning","error","critical"],"title":"ValidationSeverity","description":"Severity levels for validation issues."},"VariableType":{"type":"string","enum":["W","F","C","WC","SQ","SF","H","W","L","D","P","A","V"],"title":"VariableType","description":"Variable types for dynamic quantities."},"Waste":{"properties":{"suggested_pct":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Suggested Pct"},"table":{"items":{"$ref":"#/components/schemas/WasteRow"},"type":"array","title":"Table"}},"type":"object","title":"Waste"},"WasteRow":{"properties":{"pct":{"type":"number","minimum":0.0,"title":"Pct"},"area_sf":{"type":"number","minimum":0.0,"title":"Area Sf"},"squares":{"type":"number","minimum":0.0,"title":"Squares"}},"type":"object","required":["pct","area_sf","squares"],"title":"WasteRow"},"WaterMitInputs":{"properties":{"length_ft":{"anyOf":[{"type":"number","exclusiveMinimum":0.0},{"type":"null"}],"title":"Length Ft"},"width_ft":{"anyOf":[{"type":"number","exclusiveMinimum":0.0},{"type":"null"}],"title":"Width Ft"},"area_sf":{"anyOf":[{"type":"number","exclusiveMinimum":0.0},{"type":"null"}],"title":"Area Sf"},"ceiling_height_ft":{"type":"number","exclusiveMinimum":0.0,"title":"Ceiling Height Ft","default":8.0},"water_class":{"type":"integer","enum":[1,2,3,4],"title":"Water Class"},"water_category":{"type":"integer","enum":[1,2,3],"title":"Water Category"},"chambers":{"type":"integer","minimum":1.0,"title":"Chambers","default":1},"wall_insets":{"type":"integer","minimum":0.0,"title":"Wall Insets","default":0},"affected_perimeter_lf":{"anyOf":[{"type":"number","exclusiveMinimum":0.0},{"type":"null"}],"title":"Affected Perimeter Lf"},"dehu_capacity_ppd":{"type":"number","exclusiveMinimum":0.0,"title":"Dehu Capacity Ppd","description":"AHAM pints/day per unit (editable)","default":70.0}},"type":"object","required":["water_class","water_category"],"title":"WaterMitInputs","description":"C4 inputs. Area geometry or direct SF, class/category, chambers."},"WholeBuildingBreakout":{"properties":{"whole_side":{"type":"string","title":"Whole Side"},"whole_room":{"type":"string","title":"Whole Room"},"whole_qty":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Whole Qty"},"distributed_total":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Distributed Total"},"unit":{"type":"string","title":"Unit","default":""},"distributed_rooms":{"items":{"$ref":"#/components/schemas/RoomQty"},"type":"array","title":"Distributed Rooms"}},"type":"object","required":["whole_side","whole_room"],"title":"WholeBuildingBreakout","description":"A building-wide item on one estimate reconciled against the same code\nspread across multiple rooms on the other estimate (B-662).\n\nOne estimate files whole-building work under a single pseudo-room\n(\"Footprint\"); the other distributes the same code per-room. This carries\nthe aggregation so the row compares total-vs-total with a per-room drill-down."},"XactimateRule":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"type":"string","title":"Description"},"rule_type":{"$ref":"#/components/schemas/RuleType"},"trigger":{"$ref":"#/components/schemas/RuleTrigger","default":"always"},"priority":{"$ref":"#/components/schemas/RulePriority","default":2},"primary_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Primary Code"},"related_codes":{"items":{"type":"string"},"type":"array","title":"Related Codes","default":[]},"damage_types":{"items":{"type":"string"},"type":"array","title":"Damage Types","default":[]},"jurisdictions":{"items":{"type":"string"},"type":"array","title":"Jurisdictions","default":[]},"property_types":{"items":{"type":"string"},"type":"array","title":"Property Types","default":[]},"carriers":{"items":{"type":"string"},"type":"array","title":"Carriers","default":[]},"action":{"additionalProperties":true,"type":"object","title":"Action","default":{}},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message"},"reference":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reference"},"is_active":{"type":"boolean","title":"Is Active","default":true},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["name","description","rule_type"],"title":"XactimateRule","description":"Rule for Xactimate code relationships and requirements."},"app__api__routes__intelligent_scope__ScopeGenerationRequest":{"properties":{"field_notes":{"type":"string","title":"Field Notes"},"project_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Project Id"},"property_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Property Type"},"damage_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Damage Type"},"jurisdiction":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jurisdiction"},"trade_context":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Trade Context"},"address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address"}},"type":"object","required":["field_notes"],"title":"ScopeGenerationRequest","description":"Request body for generating a scope from field notes."},"app__api__routes__intelligent_scope__ScopeGenerationResponse":{"properties":{"scope":{"$ref":"#/components/schemas/GeneratedScope-Output"},"clarification_questions":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Clarification Questions"},"pipeline_context":{"additionalProperties":true,"type":"object","title":"Pipeline Context"}},"type":"object","required":["scope","clarification_questions","pipeline_context"],"title":"ScopeGenerationResponse","description":"Response body containing the generated scope."},"app__api__routes__me__LedgerEntry":{"properties":{"delta":{"type":"integer","title":"Delta"},"reason":{"type":"string","title":"Reason"},"balance_after":{"type":"integer","title":"Balance After"},"created_at":{"type":"string","title":"Created At"}},"type":"object","required":["delta","reason","balance_after","created_at"],"title":"LedgerEntry"},"app__api__routes__rule_reviews__LedgerEntry":{"properties":{"reviewer_id":{"type":"string","title":"Reviewer Id"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"total_reviews":{"type":"integer","title":"Total Reviews"},"agree_count":{"type":"integer","title":"Agree Count"},"contest_count":{"type":"integer","title":"Contest Count"},"disciplines":{"items":{"type":"string"},"type":"array","title":"Disciplines"}},"type":"object","required":["reviewer_id","total_reviews","agree_count","contest_count","disciplines"],"title":"LedgerEntry"},"app__api__routes__scope__ScopeGenerationRequest":{"properties":{"field_notes":{"type":"string","title":"Field Notes","description":"Overview / house details, or flat concatenated notes"},"room_sections":{"anyOf":[{"items":{"$ref":"#/components/schemas/RoomSectionInput"},"type":"array"},{"type":"null"}],"title":"Room Sections","description":"Per-room notes (structured mode). When provided, field_notes becomes the overview (house details) and each section is routed to its specific room only."},"property_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Property Type"},"damage_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Damage Type"},"jurisdiction":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jurisdiction"},"rooms":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Rooms","description":"Legacy room list hint"},"cat3_toggle":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Cat3 Toggle"},"helpful_mode":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Helpful Mode","default":false},"debug_trace":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Debug Trace","default":false},"claim_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Claim Type","description":"flood_nfip | standard"},"estimate_facts":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Estimate Facts","description":"Estimate-level NFIP facts (API-only this PRP — no UI): policy_form, flood_zone, post_firm, foundation_type, principal_residence, rcv_eligible, prior_loss_unrepaired, drying_log_provided, drying_log_proper, hvac_operational, water_depth_exterior_in, waterline_documented. Unknown keys are dropped (fail-closed)."}},"type":"object","required":["field_notes"],"title":"ScopeGenerationRequest","description":"Request to generate a scope from field notes.\n\nStructured mode (preferred): set field_notes as the overview/house-details\nand provide room_sections for per-room notes. The engine routes each section\nto its own room and applies house-default facts from the overview.\n\nFlat mode (backward-compatible): set field_notes as the concatenated notes.\nThe engine identifies rooms from the text automatically."},"app__api__routes__scope__ScopeGenerationResponse":{"properties":{"rooms":{"items":{"$ref":"#/components/schemas/RoomScopeResponse"},"type":"array","title":"Rooms"},"general_conditions":{"items":{"$ref":"#/components/schemas/ScopeLineItemResponse"},"type":"array","title":"General Conditions"},"code_requirements":{"items":{"$ref":"#/components/schemas/CodeRequirementResponse"},"type":"array","title":"Code Requirements","default":[]},"validation_issues":{"items":{"$ref":"#/components/schemas/ValidationIssueResponse"},"type":"array","title":"Validation Issues","default":[]},"questions":{"items":{"type":"string"},"type":"array","title":"Questions","default":[]},"warnings":{"items":{"type":"string"},"type":"array","title":"Warnings","default":[]},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata","default":{}},"stats":{"additionalProperties":true,"type":"object","title":"Stats","default":{}},"rule_trace":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Rule Trace","default":[]}},"type":"object","required":["rooms","general_conditions"],"title":"ScopeGenerationResponse","description":"Complete scope generation response."},"app__models__scope__ScopeGenerationRequest":{"properties":{"field_notes":{"type":"string","title":"Field Notes"},"trade_context":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Trade Context"},"property_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Property Type"},"damage_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Damage Type"},"jurisdiction":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jurisdiction"},"include_expert_guidelines":{"type":"boolean","title":"Include Expert Guidelines","default":true},"include_code_references":{"type":"boolean","title":"Include Code References","default":true},"max_rag_results":{"type":"integer","title":"Max Rag Results","default":10}},"type":"object","required":["field_notes"],"title":"ScopeGenerationRequest","description":"Request for scope generation."},"app__models__scope__ScopeItem":{"properties":{"description":{"type":"string","title":"Description"},"category":{"type":"string","title":"Category"},"quantity":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Quantity"},"unit":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Unit"},"code_requirements":{"items":{"type":"string"},"type":"array","title":"Code Requirements","default":[]},"expert_notes":{"items":{"type":"string"},"type":"array","title":"Expert Notes","default":[]},"confidence_score":{"type":"number","maximum":1.0,"minimum":0.0,"title":"Confidence Score"}},"type":"object","required":["description","category","confidence_score"],"title":"ScopeItem","description":"Individual line item in a scope."},"app__models__unified_payload__ScopeItem":{"properties":{"id":{"type":"string","title":"Id","description":"Unique identifier for this scope item"},"category":{"type":"string","title":"Category","description":"Category (e.g., 'Drywall', 'Flooring', 'Electrical')"},"description":{"type":"string","title":"Description","description":"Detailed description of work"},"quantity":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Quantity","description":"Quantity if applicable"},"unit":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Unit","description":"Unit of measurement"},"priority":{"type":"string","title":"Priority","description":"Priority level: low, medium, high, critical","default":"medium"},"estimated_hours":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Estimated Hours","description":"Estimated labor hours"},"materials_needed":{"items":{"type":"string"},"type":"array","title":"Materials Needed","description":"Required materials"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes","description":"Additional notes"},"confidence_score":{"type":"number","title":"Confidence Score","description":"AI confidence in this item (0-1)","default":0.8}},"type":"object","required":["id","category","description"],"title":"ScopeItem","description":"Individual scope item in the structured response."},"app__models__unified_payload__XactimateCode":{"properties":{"code":{"type":"string","title":"Code","description":"Xactimate line item code"},"description":{"type":"string","title":"Description","description":"Description of the line item"},"category":{"type":"string","title":"Category","description":"Category/trade"},"unit":{"type":"string","title":"Unit","description":"Unit of measurement"},"suggested_quantity":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Suggested Quantity","description":"Suggested quantity"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes","description":"Additional notes or variations"}},"type":"object","required":["code","description","category","unit"],"title":"XactimateCode","description":"Xactimate line item code mapping."},"app__services__xactimate_code_manager__XactimateCode":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"code":{"type":"string","title":"Code"},"category":{"type":"string","title":"Category"},"selector":{"type":"string","title":"Selector"},"description":{"type":"string","title":"Description"},"unit":{"$ref":"#/components/schemas/UnitOfMeasurement"},"valid_actions":{"items":{"$ref":"#/components/schemas/ActionCode"},"type":"array","title":"Valid Actions"},"alternative_units":{"items":{"$ref":"#/components/schemas/UnitOfMeasurement"},"type":"array","title":"Alternative Units"},"variables":{"items":{"$ref":"#/components/schemas/VariableType"},"type":"array","title":"Variables"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"},"is_active":{"type":"boolean","title":"Is Active","default":true},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["code","category","selector","description","unit"],"title":"XactimateCode","description":"Detailed information about an Xactimate code."}}}}