{"openapi":"3.1.0","info":{"title":"LLM Survey Backend","description":"Backend API for LLM Survey with occupations and tasks management","version":"1.0.0"},"paths":{"/api/occupations/":{"post":{"tags":["occupations"],"summary":"Create Occupation Endpoint","description":"Create a new occupation","operationId":"create_occupation_endpoint_api_occupations__post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OccupationCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OccupationRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["occupations"],"summary":"Read Occupations Endpoint","description":"Get all occupations with optional filtering and search","operationId":"read_occupations_endpoint_api_occupations__get","parameters":[{"name":"skip","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Skip"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":100,"title":"Limit"}},{"name":"available","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Available"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search occupations by substring (case-insensitive)","title":"Search"},"description":"Search occupations by substring (case-insensitive)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/OccupationRead"},"title":"Response Read Occupations Endpoint Api Occupations  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/occupations/tasks-completion":{"get":{"tags":["occupations"],"summary":"Get Remaining Task Instances Endpoint","description":"Get occupations with remaining task instance counts (paginated).\n\nReturns available occupations (available=True) that have available (not deleted) task instances.\n\nArgs:\n    limit: Number of records to return (default: 10, max: 50)\n    skip: Number of records to skip for pagination (default: 0)\n    search: Optional search string to filter occupations by name (case-insensitive)\n    touched: When true, only occupations selected by a consented participant; when false, only not\n    completed: When true, only occupations with completed=true; when false, only not completed\n    sort_by: Column to sort by: available_count, unavailable_count, total_count, or completion_percentage\n    order: Sort order: asc or desc\n\nReturns:\n    - items: List of available occupations with occupation_id, occupation_name, available_count,\n      total_count, unavailable_count, completion_percentage, completed (occupation fully done),\n      touched (selected by at least one consented participant)\n    - total: Total count of matching records\n    - skip: Applied skip (for pagination)\n    - limit: Applied limit (for pagination)\n    - occupation_touch_summary: Catalog occupations not yet taken by participants","operationId":"get_remaining_task_instances_endpoint_api_occupations_tasks_completion_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"description":"Number of records to return","default":10,"title":"Limit"},"description":"Number of records to return"},{"name":"skip","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Number of records to skip (for pagination)","default":0,"title":"Skip"},"description":"Number of records to skip (for pagination)"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search occupations by substring (case-insensitive)","title":"Search"},"description":"Search occupations by substring (case-insensitive)"},{"name":"touched","in":"query","required":false,"schema":{"type":"boolean","description":"Filter by participant selection: true=Yes, false=No","default":true,"title":"Touched"},"description":"Filter by participant selection: true=Yes, false=No"},{"name":"completed","in":"query","required":false,"schema":{"type":"boolean","description":"Filter by occupation completed flag: true=Yes, false=No","default":false,"title":"Completed"},"description":"Filter by occupation completed flag: true=Yes, false=No"},{"name":"sort_by","in":"query","required":false,"schema":{"enum":["available_count","unavailable_count","total_count","completion_percentage"],"type":"string","description":"Column to sort by","default":"available_count","title":"Sort By"},"description":"Column to sort by"},{"name":"order","in":"query","required":false,"schema":{"enum":["asc","desc"],"type":"string","description":"Sort order: asc or desc","default":"desc","title":"Order"},"description":"Sort order: asc or desc"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OccupationTaskCountResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/occupations/semantic_search":{"get":{"tags":["occupations"],"summary":"Semantic Search Endpoint","description":"Perform semantic search over available occupations using embeddings.\n\nThis endpoint uses a machine learning model to find occupations that are semantically\nsimilar to the provided query, then filters to only return available occupations.\n\nArgs:\n    query: Search query string (e.g., \"financial data engineering\", \"software development\")\n    top_k: Number of top results to return (default: 10, max: 100)\n\nReturns:\n    - query: The original search query\n    - results: List of matching occupations with similarity scores\n    - total: Total number of results returned","operationId":"semantic_search_endpoint_api_occupations_semantic_search_get","parameters":[{"name":"query","in":"query","required":true,"schema":{"type":"string","description":"Search query string for semantic search","title":"Query"},"description":"Search query string for semantic search"},{"name":"top_k","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":100,"minimum":1},{"type":"null"}],"description":"Number of top results to return","default":10,"title":"Top K"},"description":"Number of top results to return"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SemanticSearchResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/occupations/{occupation_id}":{"get":{"tags":["occupations"],"summary":"Read Occupation Endpoint","description":"Get a specific occupation by ID","operationId":"read_occupation_endpoint_api_occupations__occupation_id__get","parameters":[{"name":"occupation_id","in":"path","required":true,"schema":{"type":"string","title":"Occupation Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OccupationRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["occupations"],"summary":"Update Occupation Endpoint","description":"Update an occupation","operationId":"update_occupation_endpoint_api_occupations__occupation_id__put","parameters":[{"name":"occupation_id","in":"path","required":true,"schema":{"type":"string","title":"Occupation Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OccupationUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OccupationRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["occupations"],"summary":"Delete Occupation Endpoint","description":"Delete an occupation","operationId":"delete_occupation_endpoint_api_occupations__occupation_id__delete","parameters":[{"name":"occupation_id","in":"path","required":true,"schema":{"type":"string","title":"Occupation Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/tasks":{"post":{"tags":["tasks"],"summary":"Create Task Endpoint","description":"Create a new task","operationId":"create_task_endpoint_api_tasks_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["tasks"],"summary":"Read Tasks Endpoint","description":"Get all tasks with optional filtering","operationId":"read_tasks_endpoint_api_tasks_get","parameters":[{"name":"skip","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Skip"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":100,"title":"Limit"}},{"name":"occupation_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Occupation Id"}},{"name":"available","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Available"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TaskRead"},"title":"Response Read Tasks Endpoint Api Tasks Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/tasks/{task_id}":{"get":{"tags":["tasks"],"summary":"Read Task Endpoint","description":"Get a specific task by ID","operationId":"read_task_endpoint_api_tasks__task_id__get","parameters":[{"name":"task_id","in":"path","required":true,"schema":{"type":"string","title":"Task Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["tasks"],"summary":"Update Task Endpoint","description":"Update a task","operationId":"update_task_endpoint_api_tasks__task_id__put","parameters":[{"name":"task_id","in":"path","required":true,"schema":{"type":"string","title":"Task Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["tasks"],"summary":"Delete Task Endpoint","description":"Delete a task","operationId":"delete_task_endpoint_api_tasks__task_id__delete","parameters":[{"name":"task_id","in":"path","required":true,"schema":{"type":"string","title":"Task Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/previews/tasks":{"get":{"tags":["tasks"],"summary":"Get Task Previews Endpoint","description":"Get task previews with filtering options","operationId":"get_task_previews_endpoint_api_previews_tasks_get","parameters":[{"name":"occupation_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Occupation Id"}},{"name":"available","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Available"}},{"name":"num","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":100,"minimum":1},{"type":"null"}],"title":"Num"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TasksPreviewResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/previews/tasks/{task_id}":{"get":{"tags":["tasks"],"summary":"Get Task Preview Endpoint","description":"Get a single task preview by ID","operationId":"get_task_preview_endpoint_api_previews_tasks__task_id__get","parameters":[{"name":"task_id","in":"path","required":true,"schema":{"type":"string","title":"Task Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/tasks/lock":{"post":{"tags":["tasks"],"summary":"Lock Tasks Endpoint","description":"Lock available tasks for a specific occupation and prolific_id.\n\n**Parameters:**\n- **occupation_id**: The occupation ID to filter tasks\n- **prolific_id**: The prolific ID to assign tasks to\n- **limit**: Maximum number of task groups to return (default: 6). Each group contains 1-3 task instances.\n             For example, limit=6 returns 6 groups with a total of 6-18 tasks.\n- **preview**: Preview mode flag (default: True)\n    - **True**: Returns available tasks without locking them. No database changes are made.\n    - **False**: Actually locks the tasks in the database and assigns them to the prolific_id.\n\n**Task Grouping Logic:**\n- Tasks are formatted as xxx-1, xxx-2, xxx-3, xxx-4, xxx-5, xxx-6\n- Tasks are grouped by prefix (xxx)\n- **Only available tasks are fetched.** Completed groups (groups with >= 2 unavailable task instances) are excluded at the database level and are never returned.\n- For each prefix returned, up to 3 newest task instances are selected (created_at desc)\n- Groups are returned in newest-first order (max created_at in the group)\n- Each group will have at least 1 task instance and at most 3 task instances\n- If a prefix has more than 3 available tasks, the 3 newest are selected\n- If a prefix has 1-3 available tasks, all are included\n- Up to 'limit' groups are returned (e.g., limit=6 returns 6 groups)\n- Total tasks returned will be between 6 (6 groups × 1 task min) and 18 (6 groups × 3 tasks max)\n\n**Example:**\n- Prefix 1: has 3 available tasks (e.g. 1-1, 1-2, 1-4) → group is included with those 3 tasks\n- Prefix 2: is completed (>= 2 unavailable) → group is not fetched at all; only groups with < 2 unavailable are returned\n\n**Returns:**\nTaskGroupResponse containing grouped tasks with metadata (total_groups, total_tasks).","operationId":"lock_tasks_endpoint_api_tasks_lock_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LockTasksRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskGroupResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/tasks/select":{"post":{"tags":["tasks"],"summary":"Select Task Endpoint","description":"Select a specific task and mark it as unavailable.\n\n**Behavior:**\n- Marks the selected task_id as unavailable\n- Adds prolific_id to the selected task's history\n- Releases all other tasks with the same prolific_id and occupation_id (makes them available and clears their prolific_id)\n- Only operates on non-deleted tasks (is_deleted is None)\n\n**Returns:**\nThe selected task with updated status.","operationId":"select_task_endpoint_api_tasks_select_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SelectTaskRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/tasks/release":{"post":{"tags":["tasks"],"summary":"Release Tasks Endpoint","description":"Release tasks matching the prolific_id and occupation_id.\n\nMakes tasks available again for other users and clears their prolific_id.\n\nThis endpoint is used to manage task lifecycle when a user abandons tasks\nor needs to release locked tasks back to the available pool.\nOnly updates tasks where is_deleted is None.","operationId":"release_tasks_endpoint_api_tasks_release_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReleaseTasksRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/tasks/update_availability":{"post":{"tags":["tasks"],"summary":"Update Task Availability Endpoint","description":"Update task availability based on the cleaning result.\n\n**Parameters:**\n- **prolific_id**: The prolific ID of the user\n- **action**: The action to perform - must be 'available' or 'unavailable' or 'locked'\n    - **'available'**: Makes tasks available again and clears their prolific_id\n    - **'unavailable'**: Keeps tasks unavailable\n    - **'locked'**: Keeps tasks locked\n\n**Behavior:**\n- Finds all tasks with the specified prolific_id\n- Updates their availability status based on the action\n- Only operates on non-deleted tasks (is_deleted is None)\n\n**Returns:**\nThe first task from the updated group.\n\n**Raises:**\n- 400: Invalid action (must be 'available' or 'unavailable' or 'locked')\n- 404: No tasks found for the specified prolific_id","operationId":"update_task_availability_endpoint_api_tasks_update_availability_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTaskAvailabilityRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/tasks/soft_delete":{"post":{"tags":["tasks"],"summary":"Mark Task As Deleted Endpoint","description":"Mark multiple tasks as deleted by setting the is_deleted field to the current timestamp.\n\n**Parameters:**\n- **task_ids**: List of task IDs to mark as deleted\n- **occupation_id**: The occupation ID of the tasks\n- **prolific_id**: The prolific ID of the user who has the tasks locked\n\n**Returns:**\nList of updated tasks with is_deleted timestamp set.\n\n**Raises:**\n- 400: task_ids is empty or null\n- 404: No tasks found with the given task_ids and occupation_id","operationId":"mark_task_as_deleted_endpoint_api_tasks_soft_delete_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SoftDeleteRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/TaskRead"},"type":"array","title":"Response Mark Task As Deleted Endpoint Api Tasks Soft Delete Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/exports/":{"get":{"tags":["exports"],"summary":"Get Exports","description":"Get all export records","operationId":"get_exports_exports__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/Export"},"type":"array","title":"Response Get Exports Exports  Get"}}}}}}},"/exports/latest":{"get":{"tags":["exports"],"summary":"Get Latest Export","description":"Get the latest export record","operationId":"get_latest_export_exports_latest_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Export"}}}}}}},"/exports/trigger":{"post":{"tags":["exports"],"summary":"Trigger Export","description":"Manually trigger the export processing job","operationId":"trigger_export_exports_trigger_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/exports/status":{"get":{"tags":["exports"],"summary":"Get Export Status","description":"Get export status summary","operationId":"get_export_status_exports_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/files/":{"get":{"tags":["files"],"summary":"List Survey Directories","description":"List all subdirectories in Survey_Files and their contents","operationId":"list_survey_directories_files__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response List Survey Directories Files  Get"}}}}}}},"/files/{directory_name}":{"get":{"tags":["files"],"summary":"List Directory Files","description":"List all files in a specific subdirectory","operationId":"list_directory_files_files__directory_name__get","parameters":[{"name":"directory_name","in":"path","required":true,"schema":{"type":"string","title":"Directory Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response List Directory Files Files  Directory Name  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/files/{directory_name}/{filename}":{"get":{"tags":["files"],"summary":"Download File","description":"Download a specific CSV file from a subdirectory","operationId":"download_file_files__directory_name___filename__get","parameters":[{"name":"directory_name","in":"path","required":true,"schema":{"type":"string","title":"Directory Name"}},{"name":"filename","in":"path","required":true,"schema":{"type":"string","title":"Filename"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/files/search/{filename}":{"get":{"tags":["files"],"summary":"Search File","description":"Search for a file across all subdirectories","operationId":"search_file_files_search__filename__get","parameters":[{"name":"filename","in":"path","required":true,"schema":{"type":"string","title":"Filename"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/files/clean-all":{"delete":{"tags":["files"],"summary":"Clean All Directories","description":"Remove all files from Cleaned_Data, Prolific_Review, and Raw_Data directories","operationId":"clean_all_directories_files_clean_all_delete","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Clean All Directories Files Clean All Delete"}}}}}}},"/files/clean/{directory_name}":{"delete":{"tags":["files"],"summary":"Clean Directory","description":"Remove all files from a specific directory (Cleaned_Data, Prolific_Review, or Raw_Data)","operationId":"clean_directory_files_clean__directory_name__delete","parameters":[{"name":"directory_name","in":"path","required":true,"schema":{"type":"string","title":"Directory Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Clean Directory Files Clean  Directory Name  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/cron/export/start":{"post":{"tags":["cron"],"summary":"Start Export Cron","description":"Start the export cron job","operationId":"start_export_cron_cron_export_start_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/cron/export/stop":{"post":{"tags":["cron"],"summary":"Stop Export Cron","description":"Stop the export cron job","operationId":"stop_export_cron_cron_export_stop_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/cron/review/start":{"post":{"tags":["cron"],"summary":"Start Review Cron","description":"Start the review cron job","operationId":"start_review_cron_cron_review_start_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/cron/review/stop":{"post":{"tags":["cron"],"summary":"Stop Review Cron","description":"Stop the review cron job","operationId":"stop_review_cron_cron_review_stop_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/cron/prolific/start":{"post":{"tags":["cron"],"summary":"Start Prolific Cron","description":"Start the prolific cron job","operationId":"start_prolific_cron_cron_prolific_start_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/cron/prolific/stop":{"post":{"tags":["cron"],"summary":"Stop Prolific Cron","description":"Stop the prolific cron job","operationId":"stop_prolific_cron_cron_prolific_stop_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/cron/cleanup/start":{"post":{"tags":["cron"],"summary":"Start Cleanup Cron","description":"Start the cleanup cron job","operationId":"start_cleanup_cron_cron_cleanup_start_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/cron/cleanup/stop":{"post":{"tags":["cron"],"summary":"Stop Cleanup Cron","description":"Stop the cleanup cron job","operationId":"stop_cleanup_cron_cron_cleanup_stop_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/cron/email/start":{"post":{"tags":["cron"],"summary":"Start Email Cron","description":"Start the email invite cron job","operationId":"start_email_cron_cron_email_start_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/cron/email/stop":{"post":{"tags":["cron"],"summary":"Stop Email Cron","description":"Stop the email invite cron job","operationId":"stop_email_cron_cron_email_stop_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/cron/all/start":{"post":{"tags":["cron"],"summary":"Start All Cron Jobs","description":"Start all cron jobs","operationId":"start_all_cron_jobs_cron_all_start_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/cron/all/stop":{"post":{"tags":["cron"],"summary":"Stop All Cron Jobs","description":"Stop all cron jobs","operationId":"stop_all_cron_jobs_cron_all_stop_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/cron/status":{"get":{"tags":["cron"],"summary":"Get Cron Status","description":"Get the status of all cron jobs","operationId":"get_cron_status_cron_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/cron/state-memory":{"get":{"tags":["cron"],"summary":"Get State Memory","description":"Get the state memory of all cron jobs (what state they were in before restart)","operationId":"get_state_memory_cron_state_memory_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/history":{"post":{"tags":["history"],"summary":"Create History Endpoint","description":"Create a new history entry","operationId":"create_history_endpoint_api_history_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HistoryCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HistoryRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["history"],"summary":"Read Histories Endpoint","description":"Get all history entries with optional filtering","operationId":"read_histories_endpoint_api_history_get","parameters":[{"name":"skip","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Skip"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":100,"title":"Limit"}},{"name":"participant_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Participant Id"}},{"name":"occupation_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Occupation Id"}},{"name":"start_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Start Date"}},{"name":"end_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"End Date"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/HistoryRead"},"title":"Response Read Histories Endpoint Api History Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/history/{device_key}":{"get":{"tags":["history"],"summary":"Read History Endpoint","description":"Get a specific history entry by device_key","operationId":"read_history_endpoint_api_history__device_key__get","parameters":[{"name":"device_key","in":"path","required":true,"schema":{"type":"string","title":"Device Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HistoryRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["history"],"summary":"Update History Endpoint","description":"Update a history entry","operationId":"update_history_endpoint_api_history__device_key__put","parameters":[{"name":"device_key","in":"path","required":true,"schema":{"type":"string","title":"Device Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HistoryUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HistoryRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["history"],"summary":"Delete History Endpoint","description":"Delete a history entry","operationId":"delete_history_endpoint_api_history__device_key__delete","parameters":[{"name":"device_key","in":"path","required":true,"schema":{"type":"string","title":"Device Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/history/participant/{participant_id}":{"get":{"tags":["history"],"summary":"Get Histories By Participant Endpoint","description":"Get all history entries for a specific participant","operationId":"get_histories_by_participant_endpoint_api_history_participant__participant_id__get","parameters":[{"name":"participant_id","in":"path","required":true,"schema":{"type":"string","title":"Participant Id"}},{"name":"skip","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Skip"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/HistoryRead"},"title":"Response Get Histories By Participant Endpoint Api History Participant  Participant Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/qualtrics/qualtrics-overview":{"get":{"tags":["qualtrics"],"summary":"Get Qualtrics Overview","description":"Get overview statistics for Qualtrics survey data\n\nReturns:\n    - total_participants: Total number of participants\n    - total_approved_participants: Number of participants where status=APPROVED\n    - daily_submission_count: Array of submissions grouped by date\n    - average_daily_submission: Average number of daily submissions\n    - daily_task_fulfillment: Array of task fulfillments grouped by date\n    - average_daily_approved_submission: Average number of daily task fulfillment (approved)\n    - occupations_info: Total and available occupation counts, plus completed occupations updated in the last 7 days\n    - tasks_info: Total tasks count, remaining tasks count, total instances, remaining instances, unavailable instances updated in the last 7 days, and completed tasks updated in the last 7 days\n    - quality: Quality breakdown (approved_high_quality, approved_low_quality, rejected, screened_out, other)\n    - completion_projections: Estimated remaining days (overall average and last 7 days)","operationId":"get_qualtrics_overview_api_qualtrics_qualtrics_overview_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Get Qualtrics Overview Api Qualtrics Qualtrics Overview Get"}}}}}}},"/api/qualtrics/feedback":{"get":{"tags":["qualtrics"],"summary":"Get Feedback","description":"Get participant feedback from Qualtrics survey data\n\nArgs:\n    limit: Maximum number of feedback items to return (default: 10)\n    skip: Number of items to skip (default: 0)\n\nReturns:\n    - total: Total number of matched records\n    - limit: Input limit value\n    - skip: Input skip value\n    - items: Array of feedback items with prolific_id, selected_occupation, optional_comment, recorded_date, valid_responses, status","operationId":"get_feedback_api_qualtrics_feedback_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Maximum number of feedback items to return","default":10,"title":"Limit"},"description":"Maximum number of feedback items to return"},{"name":"skip","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Number of items to skip","default":0,"title":"Skip"},"description":"Number of items to skip"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Get Feedback Api Qualtrics Feedback Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/qualtrics/status-analysis":{"get":{"tags":["qualtrics"],"summary":"Get Status Analysis","description":"Get status analysis grouped by selected_occupation with pagination\n\nArgs:\n    limit: Maximum number of items to return (default: 10)\n    skip: Number of items to skip (default: 0)\n    search: Optional search filter for selected_occupation\n\nReturns:\n    - total: Total number of unique occupations\n    - limit: Input limit value\n    - skip: Input skip value\n    - items: Array of status analysis items per occupation\n    - occupation_confirm_by_week: Weekly yes/no counts for occupation_confirm\n      (consented participants with end_date), grouped by week start (Sunday)\n    - newly_taken_occupations_by_week: Count of catalog occupations whose\n      first consented completion falls in each week (Sunday week start)","operationId":"get_status_analysis_api_qualtrics_status_analysis_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Maximum number of items to return","default":10,"title":"Limit"},"description":"Maximum number of items to return"},{"name":"skip","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Number of items to skip","default":0,"title":"Skip"},"description":"Number of items to skip"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search filter for selected_occupation","title":"Search"},"description":"Search filter for selected_occupation"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Get Status Analysis Api Qualtrics Status Analysis Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/prolific/compensation-overview":{"get":{"tags":["prolific"],"summary":"Get Compensation Overview","description":"Get compensation overview by scanning prolific_actions table.\n\nReturns:\n    - paid_participants: (action APPROVE and result not pending) or status SCREENED OUT\n    - total_spent: same cohort ($4 per completed APPROVE, $0.14 per SCREENED OUT)\n    - average_compensation: total_spent / paid_participants\n    - average_duration: total sum of time_taken / number of non-RETURNED participants","operationId":"get_compensation_overview_api_prolific_compensation_overview_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/prolific/actions":{"get":{"tags":["prolific"],"summary":"Get Prolific Actions","description":"Get prolific actions with pagination and optional status filter.\n\nArgs:\n    limit: Number of records to return (default: 50, max: 1000)\n    skip: Number of records to skip (default: 0)\n    status: Optional list of statuses to filter by (OR logic)\n\nReturns:\n    - items: List of prolific actions\n    - total: Total count of matching records\n    - limit: Current limit value\n    - skip: Current skip value","operationId":"get_prolific_actions_api_prolific_actions_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"description":"Number of records to return","default":50,"title":"Limit"},"description":"Number of records to return"},{"name":"skip","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Number of records to skip","default":0,"title":"Skip"},"description":"Number of records to skip"},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by status (OR logic, e.g., APPROVED, SCREENED OUT)","title":"Status"},"description":"Filter by status (OR logic, e.g., APPROVED, SCREENED OUT)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Get Prolific Actions Api Prolific Actions Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/prolific/return-requests":{"get":{"tags":["prolific"],"summary":"Get Return Requests","description":"Get return requests with pagination and optional days filter.","operationId":"get_return_requests_api_prolific_return_requests_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"description":"Number of records to return","default":50,"title":"Limit"},"description":"Number of records to return"},{"name":"skip","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Number of records to skip","default":0,"title":"Skip"},"description":"Number of records to skip"},{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":30,"minimum":0,"description":"Number of days to filter by","default":3,"title":"Days"},"description":"Number of days to filter by"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Get Return Requests Api Prolific Return Requests Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/quality-checks/occupations":{"get":{"tags":["quality-checks"],"summary":"Get Completed Occupations","description":"Get occupations for quality checks.\n\n**Ordering:**\n- Ordered by updated_at DESC\n\n**Pagination:**\n- limit: Number of occupations to return (default: 10, max: 100)\n- skip: Number of occupations to skip (default: 0)\n\n**Search:**\n- search: Optional search string to filter by occupation (case-insensitive)\n\n**Status Filter:**\n- completed: completed_tasks equals total_tasks (and total_tasks > 0)\n- in_progress: completed_tasks is greater than 0 but less than total_tasks\n- pending: completed_tasks equals 0 (and total_tasks > 0)\n- na: both completed_tasks and total_tasks are 0\n\n**Returns:**\n- total: Total number of matching occupations\n- limit: Limit used\n- skip: Skip used\n- items: Array of occupation_id, occupation, total_tasks, completed_tasks","operationId":"get_completed_occupations_api_quality_checks_occupations_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":10,"title":"Limit"}},{"name":"skip","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Skip"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search string for occupation (case-insensitive)","title":"Search"},"description":"Search string for occupation (case-insensitive)"},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"enum":["completed","in_progress","pending","na"],"type":"string"},{"type":"null"}],"description":"Filter by status: completed (completed_tasks=total_tasks, total_tasks>0), in_progress (0<completed_tasks<total_tasks), pending (completed_tasks=0, total_tasks>0), na (both are 0)","title":"Status"},"description":"Filter by status: completed (completed_tasks=total_tasks, total_tasks>0), in_progress (0<completed_tasks<total_tasks), pending (completed_tasks=0, total_tasks>0), na (both are 0)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompletedOccupationsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/quality-checks/instances":{"get":{"tags":["quality-checks"],"summary":"Get Task Instances","description":"Get task instances for quality checks.\n\n**Filters:**\n- is_deleted is null\n- available: filtered by 'filter' param (if not specified, returns all records)\n\n**Ordering:**\n- Ordered by updated_at DESC\n\n**Pagination:**\n- limit: Number of items to return (default: 10, max: 100)\n- skip: Number of items to skip (default: 0)\n\n**Search:**\n- search: Optional search string to filter by task_description (case-insensitive)\n\n**Filter:**\n- filter: Optional filter for task availability (\"unavailable\", \"locked\", \"available\"). If not provided, returns all records.\n\n**Returns:**\n- total: Total number of matching items\n- limit: Limit used\n- skip: Skip used\n- items: Array of task instances with task_id, prolific_id, task_description, occupation_name","operationId":"get_task_instances_api_quality_checks_instances_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":10,"title":"Limit"}},{"name":"skip","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Skip"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search string for task_description","title":"Search"},"description":"Search string for task_description"},{"name":"filter","in":"query","required":false,"schema":{"anyOf":[{"enum":["unavailable","locked","available"],"type":"string"},{"type":"null"}],"description":"Filter by task availability status","title":"Filter"},"description":"Filter by task availability status"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskInstancesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/quality-checks/tasks":{"get":{"tags":["quality-checks"],"summary":"Get Completed Tasks","description":"Get task groups for quality checks.\n\n**Task Grouping:**\n- Task IDs are formatted as xxx-1, xxx-2, xxx-y\n- Tasks are grouped by prefix (xxx - the part before the last dash)\n\n**Filters (applied to individual task instances):**\n- is_deleted is null\n\n**Status Filter (applied to task groups based on unavailable task instances):**\n- completed: Groups with >= 2 unavailable task instances\n- in_progress: Groups with exactly 1 unavailable task instance\n- pending: Groups with 0 unavailable task instances\n- Not provided: All groups\n\n**Ordering:**\n- Ordered by updated_at DESC and task_id\n\n**Pagination:**\n- limit: Number of task groups to return (default: 10, max: 100)\n- skip: Number of task groups to skip (default: 0)\n\n**Search:**\n- search: Optional search string to filter by task_description (case-insensitive)\n\n**Returns:**\n- total: Total number of task groups\n- limit: Limit used\n- skip: Skip used\n- items: Array of task groups with task_group_id, task_description, occupation_name, unavailable_instance_count (number of unavailable task instances), instances","operationId":"get_completed_tasks_api_quality_checks_tasks_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":10,"title":"Limit"}},{"name":"skip","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Skip"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search string for task_description","title":"Search"},"description":"Search string for task_description"},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"enum":["completed","in_progress","pending"],"type":"string"},{"type":"null"}],"description":"Filter by status: completed (>=2 unavailable instances), in_progress (=1 unavailable instance), pending (=0 unavailable instances)","title":"Status"},"description":"Filter by status: completed (>=2 unavailable instances), in_progress (=1 unavailable instance), pending (=0 unavailable instances)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompletedTasksResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/users/new":{"post":{"tags":["users"],"summary":"Register User","description":"Register a new participant from the intake form.","operationId":"register_user_api_users_new_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserRegisterRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserRegisterResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/api/users/{email}":{"get":{"tags":["users"],"summary":"Get User","description":"Get a user by email (case-insensitive).","operationId":"get_user_api_users__email__get","parameters":[{"name":"email","in":"path","required":true,"schema":{"type":"string","title":"Email"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserRead"}}}},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}},"description":"Not Found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["users"],"summary":"Update User","description":"Update a user by email (case-insensitive). Only provided fields are changed.","operationId":"update_user_api_users__email__patch","parameters":[{"name":"email","in":"path","required":true,"schema":{"type":"string","title":"Email"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserUpdateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserRead"}}}},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}},"description":"Not Found"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}},"description":"Unprocessable Entity"}}},"delete":{"tags":["users"],"summary":"Delete User","description":"Delete a user by email (case-insensitive).","operationId":"delete_user_api_users__email__delete","parameters":[{"name":"email","in":"path","required":true,"schema":{"type":"string","title":"Email"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}},"description":"Not Found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/":{"get":{"summary":"Root","description":"Root endpoint","operationId":"root__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/health":{"get":{"summary":"Health Check","description":"Health check endpoint","operationId":"health_check_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/run-export-job-once":{"get":{"summary":"Run Export Job","description":"Run export job once","operationId":"run_export_job_run_export_job_once_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/run-review-job-once":{"get":{"summary":"Run Review Job","description":"Run review job once","operationId":"run_review_job_run_review_job_once_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/run-email-job-once":{"get":{"summary":"Run Email Job","description":"Run email invite job once","operationId":"run_email_job_run_email_job_once_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"ApiErrorResponse":{"properties":{"code":{"type":"string","title":"Code"},"message":{"type":"string","title":"Message"}},"type":"object","required":["code","message"],"title":"ApiErrorResponse"},"CompletedOccupationItem":{"properties":{"occupation_id":{"type":"string","title":"Occupation Id"},"occupation":{"type":"string","title":"Occupation"},"total_tasks":{"type":"integer","title":"Total Tasks"},"completed_tasks":{"type":"integer","title":"Completed Tasks"}},"type":"object","required":["occupation_id","occupation","total_tasks","completed_tasks"],"title":"CompletedOccupationItem","description":"Model for completed occupation item"},"CompletedOccupationsResponse":{"properties":{"total":{"type":"integer","title":"Total"},"limit":{"type":"integer","title":"Limit"},"skip":{"type":"integer","title":"Skip"},"items":{"items":{"$ref":"#/components/schemas/CompletedOccupationItem"},"type":"array","title":"Items"}},"type":"object","required":["total","limit","skip","items"],"title":"CompletedOccupationsResponse","description":"Model for completed occupations response with pagination"},"CompletedTaskGroup":{"properties":{"task_group_id":{"type":"string","title":"Task Group Id"},"task_description":{"type":"string","title":"Task Description"},"occupation_id":{"type":"string","title":"Occupation Id"},"occupation_name":{"type":"string","title":"Occupation Name"},"unavailable_instance_count":{"type":"integer","title":"Unavailable Instance Count"},"instances":{"items":{"$ref":"#/components/schemas/CompletedTaskInstance"},"type":"array","title":"Instances"}},"type":"object","required":["task_group_id","task_description","occupation_id","occupation_name","unavailable_instance_count","instances"],"title":"CompletedTaskGroup","description":"Model for a completed task group"},"CompletedTaskInstance":{"properties":{"task_id":{"type":"string","title":"Task Id"},"available":{"type":"string","title":"Available"}},"type":"object","required":["task_id","available"],"title":"CompletedTaskInstance","description":"Model for a single task instance within a completed task group"},"CompletedTasksResponse":{"properties":{"total":{"type":"integer","title":"Total"},"limit":{"type":"integer","title":"Limit"},"skip":{"type":"integer","title":"Skip"},"items":{"items":{"$ref":"#/components/schemas/CompletedTaskGroup"},"type":"array","title":"Items"}},"type":"object","required":["total","limit","skip","items"],"title":"CompletedTasksResponse","description":"Model for completed tasks response with pagination"},"Export":{"properties":{"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"progress_id":{"type":"string","title":"Progress Id","description":"Qualtrics progress ID"},"status":{"type":"string","title":"Status","description":"Export status (inProgress, failed, complete)"},"percent_complete":{"type":"number","title":"Percent Complete","description":"Export completion percentage","default":0.0},"continuation_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Continuation Token","description":"Continuation token for pagination"},"http_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Http Status","description":"HTTP status from Qualtrics API"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error","description":"Error message if any"},"file_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"File Id","description":"Qualtrics file ID when export is complete"}},"type":"object","required":["progress_id","status"],"title":"Export","description":"Model for tracking Qualtrics survey export progress"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HistoryCreate":{"properties":{"ip_address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ip Address"},"preview":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Preview"},"participant_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Participant Id"},"occupation_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Occupation Id"},"user_agent":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Agent"},"browser":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Browser"},"os":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Os"},"platform":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Platform"},"device_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Type"},"viewport_width":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Viewport Width"},"viewport_height":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Viewport Height"},"screen_width":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Screen Width"},"screen_height":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Screen Height"},"timezone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Timezone"},"languages":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Languages"},"hardware_threads":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Hardware Threads"},"device_memory":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Device Memory"},"touch_capable":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Touch Capable"},"cookies_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Cookies Enabled"},"device_key":{"type":"string","title":"Device Key"}},"type":"object","required":["participant_id","occupation_id","device_key"],"title":"HistoryCreate","description":"Model for creating a new history entry"},"HistoryRead":{"properties":{"ip_address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ip Address"},"preview":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Preview"},"participant_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Participant Id"},"occupation_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Occupation Id"},"user_agent":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Agent"},"browser":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Browser"},"os":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Os"},"platform":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Platform"},"device_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Type"},"viewport_width":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Viewport Width"},"viewport_height":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Viewport Height"},"screen_width":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Screen Width"},"screen_height":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Screen Height"},"timezone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Timezone"},"languages":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Languages"},"hardware_threads":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Hardware Threads"},"device_memory":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Device Memory"},"touch_capable":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Touch Capable"},"cookies_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Cookies Enabled"},"device_key":{"type":"string","title":"Device Key"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["participant_id","occupation_id","device_key","created_at","updated_at"],"title":"HistoryRead","description":"Model for reading history data"},"HistoryUpdate":{"properties":{"ip_address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ip Address"},"preview":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Preview"},"participant_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Participant Id"},"occupation_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Occupation Id"},"user_agent":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Agent"},"browser":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Browser"},"os":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Os"},"platform":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Platform"},"device_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Type"},"viewport_width":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Viewport Width"},"viewport_height":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Viewport Height"},"screen_width":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Screen Width"},"screen_height":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Screen Height"},"timezone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Timezone"},"languages":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Languages"},"hardware_threads":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Hardware Threads"},"device_memory":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Device Memory"},"touch_capable":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Touch Capable"},"cookies_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Cookies Enabled"}},"type":"object","title":"HistoryUpdate","description":"Model for updating history data"},"LockTasksRequest":{"properties":{"occupation_id":{"type":"string","title":"Occupation Id"},"prolific_id":{"type":"string","title":"Prolific Id"},"limit":{"type":"integer","title":"Limit","default":6},"preview":{"type":"boolean","title":"Preview","default":true}},"type":"object","required":["occupation_id","prolific_id"],"title":"LockTasksRequest"},"OccupationCreate":{"properties":{"occupation":{"type":"string","title":"Occupation"},"available":{"type":"boolean","title":"Available","default":false},"completed":{"type":"boolean","title":"Completed","default":false},"total_tasks":{"type":"integer","title":"Total Tasks","default":0},"completed_tasks":{"type":"integer","title":"Completed Tasks","default":0}},"type":"object","required":["occupation"],"title":"OccupationCreate","description":"Model for creating a new occupation"},"OccupationRead":{"properties":{"occupation":{"type":"string","title":"Occupation"},"available":{"type":"boolean","title":"Available","default":false},"completed":{"type":"boolean","title":"Completed","default":false},"total_tasks":{"type":"integer","title":"Total Tasks","default":0},"completed_tasks":{"type":"integer","title":"Completed Tasks","default":0},"occupation_id":{"type":"string","title":"Occupation Id"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["occupation","occupation_id","created_at","updated_at"],"title":"OccupationRead","description":"Model for reading occupation data"},"OccupationTaskCount":{"properties":{"occupation_id":{"type":"string","title":"Occupation Id"},"occupation_name":{"type":"string","title":"Occupation Name"},"available_count":{"type":"integer","title":"Available Count"},"total_count":{"type":"integer","title":"Total Count"},"unavailable_count":{"type":"integer","title":"Unavailable Count"},"completion_percentage":{"type":"number","title":"Completion Percentage"},"completed":{"type":"boolean","title":"Completed"},"touched":{"type":"boolean","title":"Touched"}},"type":"object","required":["occupation_id","occupation_name","available_count","total_count","unavailable_count","completion_percentage","completed","touched"],"title":"OccupationTaskCount","description":"Model for occupation with task instance counts"},"OccupationTaskCountResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/OccupationTaskCount"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"skip":{"type":"integer","title":"Skip"},"limit":{"type":"integer","title":"Limit"},"occupation_touch_summary":{"$ref":"#/components/schemas/OccupationTouchSummary"}},"type":"object","required":["items","total","skip","limit","occupation_touch_summary"],"title":"OccupationTaskCountResponse","description":"Response model for occupation task count endpoint"},"OccupationTouchSummary":{"properties":{"catalog_count":{"type":"integer","title":"Catalog Count"},"ever_taken_count":{"type":"integer","title":"Ever Taken Count"},"completed_count":{"type":"integer","title":"Completed Count"}},"type":"object","required":["catalog_count","ever_taken_count","completed_count"],"title":"OccupationTouchSummary","description":"Raw catalog occupation counts for tasks page summary cards."},"OccupationUpdate":{"properties":{"occupation":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Occupation"},"available":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Available"},"completed":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Completed"},"total_tasks":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Tasks"},"completed_tasks":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Completed Tasks"}},"type":"object","title":"OccupationUpdate","description":"Model for updating occupation data"},"ReleaseTasksRequest":{"properties":{"prolific_id":{"type":"string","title":"Prolific Id"},"occupation_id":{"type":"string","title":"Occupation Id"}},"type":"object","required":["prolific_id","occupation_id"],"title":"ReleaseTasksRequest"},"SelectTaskRequest":{"properties":{"task_id":{"type":"string","title":"Task Id"},"prolific_id":{"type":"string","title":"Prolific Id"},"occupation_id":{"type":"string","title":"Occupation Id"}},"type":"object","required":["task_id","prolific_id","occupation_id"],"title":"SelectTaskRequest"},"SemanticSearchResponse":{"properties":{"query":{"type":"string","title":"Query"},"results":{"items":{"$ref":"#/components/schemas/SemanticSearchResult"},"type":"array","title":"Results"},"total":{"type":"integer","title":"Total"}},"type":"object","required":["query","results","total"],"title":"SemanticSearchResponse","description":"Response model for semantic search endpoint"},"SemanticSearchResult":{"properties":{"occupation_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Occupation Id"},"occupation":{"type":"string","title":"Occupation"},"similarity":{"type":"number","title":"Similarity"},"normalized_score":{"type":"number","title":"Normalized Score"}},"type":"object","required":["occupation","similarity","normalized_score"],"title":"SemanticSearchResult","description":"Model for a single semantic search result"},"SoftDeleteRequest":{"properties":{"task_ids":{"items":{"type":"string"},"type":"array","title":"Task Ids"},"occupation_id":{"type":"string","title":"Occupation Id"},"prolific_id":{"type":"string","title":"Prolific Id"}},"type":"object","required":["task_ids","occupation_id","prolific_id"],"title":"SoftDeleteRequest"},"TaskCreate":{"properties":{"occupation_id":{"type":"string","title":"Occupation Id"},"task_url":{"type":"string","title":"Task Url"},"task_desc":{"type":"string","title":"Task Desc"},"response_url_1":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Response Url 1"},"response_url_2":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Response Url 2"},"response_url_3":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Response Url 3"},"response_url_4":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Response Url 4"},"response_url_5":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Response Url 5"},"available":{"type":"string","title":"Available","default":"available"},"prolific_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prolific Id"},"qualtrics_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Qualtrics Id"},"history":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"History"},"locked_history":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Locked History"},"is_deleted":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Is Deleted"},"models_order":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Models Order"},"task_id":{"type":"string","title":"Task Id"}},"type":"object","required":["occupation_id","task_url","task_desc","task_id"],"title":"TaskCreate","description":"Model for creating a new task"},"TaskGroup":{"properties":{"group_id":{"type":"string","title":"Group Id"},"task_desc":{"type":"string","title":"Task Desc"},"items":{"items":{"$ref":"#/components/schemas/TaskRead"},"type":"array","title":"Items"}},"type":"object","required":["group_id","task_desc","items"],"title":"TaskGroup"},"TaskGroupResponse":{"properties":{"groups":{"items":{"$ref":"#/components/schemas/TaskGroup"},"type":"array","title":"Groups"},"total_groups":{"type":"integer","title":"Total Groups"},"total_tasks":{"type":"integer","title":"Total Tasks"}},"type":"object","required":["groups","total_groups","total_tasks"],"title":"TaskGroupResponse"},"TaskInstanceItem":{"properties":{"task_id":{"type":"string","title":"Task Id"},"prolific_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prolific Id"},"task_description":{"type":"string","title":"Task Description"},"occupation_id":{"type":"string","title":"Occupation Id"},"occupation_name":{"type":"string","title":"Occupation Name"},"available":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Available"}},"type":"object","required":["task_id","prolific_id","task_description","occupation_id","occupation_name"],"title":"TaskInstanceItem","description":"Model for task instance item in quality checks response"},"TaskInstancesResponse":{"properties":{"total":{"type":"integer","title":"Total"},"limit":{"type":"integer","title":"Limit"},"skip":{"type":"integer","title":"Skip"},"items":{"items":{"$ref":"#/components/schemas/TaskInstanceItem"},"type":"array","title":"Items"}},"type":"object","required":["total","limit","skip","items"],"title":"TaskInstancesResponse","description":"Model for task instances response with pagination"},"TaskPreview":{"properties":{"task_id":{"type":"string","title":"Task Id"},"url":{"type":"string","title":"Url"},"description":{"type":"string","title":"Description"}},"type":"object","required":["task_id","url","description"],"title":"TaskPreview","description":"Model for task preview responses"},"TaskRead":{"properties":{"occupation_id":{"type":"string","title":"Occupation Id"},"task_url":{"type":"string","title":"Task Url"},"task_desc":{"type":"string","title":"Task Desc"},"response_url_1":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Response Url 1"},"response_url_2":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Response Url 2"},"response_url_3":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Response Url 3"},"response_url_4":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Response Url 4"},"response_url_5":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Response Url 5"},"available":{"type":"string","title":"Available","default":"available"},"prolific_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prolific Id"},"qualtrics_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Qualtrics Id"},"history":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"History"},"locked_history":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Locked History"},"is_deleted":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Is Deleted"},"models_order":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Models Order"},"task_id":{"type":"string","title":"Task Id"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["occupation_id","task_url","task_desc","task_id","created_at","updated_at"],"title":"TaskRead","description":"Model for reading task data"},"TaskUpdate":{"properties":{"occupation_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Occupation Id"},"task_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Task Url"},"task_desc":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Task Desc"},"response_url_1":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Response Url 1"},"response_url_2":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Response Url 2"},"response_url_3":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Response Url 3"},"response_url_4":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Response Url 4"},"response_url_5":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Response Url 5"},"available":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Available"},"prolific_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prolific Id"},"qualtrics_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Qualtrics Id"},"history":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"History"},"locked_history":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Locked History"},"is_deleted":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Is Deleted"},"models_order":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Models Order"}},"type":"object","title":"TaskUpdate","description":"Model for updating task data"},"TasksPreviewResponse":{"properties":{"tasks":{"items":{"$ref":"#/components/schemas/TaskPreview"},"type":"array","title":"Tasks"}},"type":"object","required":["tasks"],"title":"TasksPreviewResponse","description":"Model for task preview list responses"},"UpdateTaskAvailabilityRequest":{"properties":{"prolific_id":{"type":"string","title":"Prolific Id"},"action":{"type":"string","title":"Action"}},"type":"object","required":["prolific_id","action"],"title":"UpdateTaskAvailabilityRequest"},"UserRead":{"properties":{"first_name":{"type":"string","title":"First Name"},"last_name":{"type":"string","title":"Last Name"},"email":{"type":"string","title":"Email"},"email_sent":{"type":"boolean","title":"Email Sent","default":false},"registered_at":{"type":"string","format":"date-time","title":"Registered At"},"qualtrics_survey_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Qualtrics Survey Url"},"email_sent_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Email Sent At"},"status":{"type":"string","title":"Status","default":"registered"},"user_id":{"type":"string","title":"User Id"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["first_name","last_name","email","user_id","created_at","updated_at"],"title":"UserRead","description":"Model for reading user data"},"UserRegisterRequest":{"properties":{"first_name":{"type":"string","maxLength":100,"minLength":1,"title":"First Name"},"last_name":{"type":"string","maxLength":100,"minLength":1,"title":"Last Name"},"email":{"type":"string","maxLength":254,"minLength":3,"title":"Email"}},"type":"object","required":["first_name","last_name","email"],"title":"UserRegisterRequest"},"UserRegisterResponse":{"properties":{"message":{"type":"string","title":"Message"},"user_id":{"type":"string","title":"User Id"}},"type":"object","required":["message","user_id"],"title":"UserRegisterResponse"},"UserUpdateRequest":{"properties":{"first_name":{"anyOf":[{"type":"string","maxLength":100,"minLength":1},{"type":"null"}],"title":"First Name"},"last_name":{"anyOf":[{"type":"string","maxLength":100,"minLength":1},{"type":"null"}],"title":"Last Name"},"email_sent":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Email Sent"},"status":{"anyOf":[{"type":"string","maxLength":100,"minLength":1},{"type":"null"}],"title":"Status"}},"type":"object","title":"UserUpdateRequest","description":"Optional fields to update on an existing user. Only provided fields change."},"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"}}}}