{"openapi":"3.1.0","info":{"title":"kis-image-gen-backend API","version":"0.1.0"},"paths":{"/":{"get":{"summary":"Root","operationId":"root__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Root  Get"}}}}}}},"/api/v1/users":{"post":{"tags":["user"],"summary":"Create a new user","description":"Create a new user record.\n\n### Request body\n- `id`: User UUID — auto-generated if omitted\n- `username`: Display name\n- `email`: Must be a valid email address and must be unique","operationId":"create_user_api_v1_users_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserCreate"}}},"required":true},"responses":{"201":{"description":"User created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserRead"}}}},"401":{"description":"Invalid or missing `X-API-Key` header","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}},"400":{"description":"User with this email or ID already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}},"422":{"description":"Invalid request body — failed field validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}}},"security":[{"ApiKeyAuth":[]}]}},"/api/v1/users/lookup":{"get":{"tags":["user"],"summary":"Look up user by email","description":"Look up a single user by email address.\n\n### Query parameters\n- `email`: Email address to look up (required)","operationId":"get_user_by_email_api_v1_users_lookup_get","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"email","in":"query","required":true,"schema":{"type":"string","description":"Email address to look up","title":"Email"},"description":"Email address to look up"}],"responses":{"200":{"description":"User found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserRead"}}}},"401":{"description":"Invalid or missing `X-API-Key` header","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}},"404":{"description":"No user with the given email address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}},"422":{"description":"Missing or invalid `email` query parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}}}}},"/api/v1/users/{user_id}":{"get":{"tags":["user"],"summary":"Get user by ID","description":"Fetch a single user by their UUID.\n\n### Path parameters\n- `user_id`: UUID of the user","operationId":"get_user_api_v1_users__user_id__get","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"200":{"description":"User found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserRead"}}}},"401":{"description":"Invalid or missing `X-API-Key` header","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}},"404":{"description":"No user with the given ID","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}},"422":{"description":"Malformed UUID in path","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}}}}},"/api/v1/sessions":{"post":{"tags":["session"],"summary":"Create a new session","description":"Create a new session.\n\n### Request body\n- `mode`: Session mode — one of `image_gen`, `survey`, `image_comment`\n- `language`: Response language — `pl` (default) or `en`\n\n### Query parameters\n- `user_id`: UUID of the owning user (optional — an anonymous UUID is generated if omitted)","operationId":"create_session_api_v1_sessions_post","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"user_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"User Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionCreate"}}}},"responses":{"201":{"description":"Session created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionRead"}}}},"401":{"description":"Invalid or missing `X-API-Key` header","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}},"422":{"description":"Invalid request body — unrecognised `mode` or `language` value","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}}}},"get":{"tags":["session"],"summary":"List sessions","description":"List sessions, optionally filtered by owner.\n\n### Query parameters\n- `user_id`: Filter by owner UUID (optional — omit to list all sessions)","operationId":"list_sessions_api_v1_sessions_get","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"user_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"User Id"}}],"responses":{"200":{"description":"List of sessions (empty array if none match)","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SessionRead"},"title":"Response 200 List Sessions Api V1 Sessions Get"}}}},"401":{"description":"Invalid or missing `X-API-Key` header","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}},"422":{"description":"Malformed UUID in `user_id` query parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}}}}},"/api/v1/sessions/{session_id}":{"get":{"tags":["session"],"summary":"Get session by ID","description":"Fetch a single session by its UUID.\n\n### Path parameters\n- `session_id`: UUID of the session","operationId":"get_session_api_v1_sessions__session_id__get","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"responses":{"200":{"description":"Session found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionRead"}}}},"401":{"description":"Invalid or missing `X-API-Key` header","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}},"404":{"description":"No session with the given ID","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}},"422":{"description":"Malformed UUID in path","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}}}}},"/api/v1/sessions/{session_id}/generations":{"post":{"tags":["generation"],"summary":"Upload image and start generation","description":"Upload an image and start async generation via Celery.\n\nReturns 202 Accepted with the generation ID immediately. The final result is\ndelivered to `callback_url` (if provided) via POST when generation completes.\n\n### Path parameters\n- `session_id`: UUID of the session — must be an `image_gen` session\n\n### Form fields\n- `file`: Image file to transform — JPEG, PNG, or WebP; max configured size\n- `transformation_type`: One of `better_quality`, `better_lighting`, `add_life`,\n  `real_materials`, `better_composition`, `post_production`, `for_client`,\n  `enhance_style`, `custom`, `upscale`, `cut_object`, `replace_object`\n- `user_instructions`: Free-text instructions — required for `replace_object` (describes\n  what to place); optional context for `cut_object`; primary prompt for `custom`;\n  max 2000 characters (optional for all other types)\n- `mask`: Mask image (JPEG, PNG, or WebP). **Required** for `cut_object` and\n  `replace_object` — white pixels (255,255,255) mark the active area to edit, black\n  pixels (0,0,0) are left untouched. Optional for all other types, where it restricts\n  edits to the masked region\n- `target_width`: Target output width in pixels.\n  If both width and height are provided, output is resized to exact dimensions.\n  **Required** for `upscale` transformation type\n- `target_height`: Target output height in pixels.\n  If both width and height are provided, output is resized to exact dimensions.\n  **Required** for `upscale` transformation type\n- `callback_url`: URL to receive a POST when generation completes (optional)","operationId":"create_generation_api_v1_sessions__session_id__generations_post","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_create_generation_api_v1_sessions__session_id__generations_post"}}}},"responses":{"202":{"description":"Generation accepted and queued; result delivered via callback POST","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerationStatusRead"}}}},"401":{"description":"Invalid or missing `X-API-Key` header","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}},"404":{"description":"Session not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}},"422":{"description":"Validation failed — possible causes:\n- Image file is empty or exceeds the configured size limit\n- Unsupported image format (only JPEG, PNG, WebP accepted)\n- Session mode is not `image_gen`\n- `user_instructions` exceeds 4000 characters\n- `transformation_type` is `cut_object` or `replace_object` and no mask was provided\n- `transformation_type` is `replace_object` and no `user_instructions` was provided\n- `transformation_type` is `upscale` and `target_width` or `target_height` is missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}},"503":{"description":"Upstream service unavailable — S3 upload, DB write, or Celery task dispatch failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}}}}},"/api/v1/generations/{generation_id}":{"get":{"tags":["generation"],"summary":"Get full generation details","description":"Retrieve all fields for a generation record.\n\n### Path parameters\n- `generation_id`: UUID of the generation","operationId":"get_generation_api_v1_generations__generation_id__get","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"generation_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Generation Id"}}],"responses":{"200":{"description":"Full generation record","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerationRead"}}}},"401":{"description":"Invalid or missing `X-API-Key` header","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}},"404":{"description":"Generation not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}},"422":{"description":"Malformed UUID in path","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}}}}},"/api/v1/generations/{generation_id}/status":{"get":{"tags":["generation"],"summary":"Get lightweight generation status","description":"Lightweight status endpoint — backup for the callback mechanism.\n\nReturns only `id`, `status`, `generated_image_key`, `error_message`, and `completed_at`.\n\n### Path parameters\n- `generation_id`: UUID of the generation","operationId":"get_generation_status_api_v1_generations__generation_id__status_get","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"generation_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Generation Id"}}],"responses":{"200":{"description":"Lightweight status snapshot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerationStatusRead"}}}},"401":{"description":"Invalid or missing `X-API-Key` header","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}},"404":{"description":"Generation not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}},"422":{"description":"Malformed UUID in path","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}}}}},"/api/v1/generations/{generation_id}/image":{"get":{"tags":["generation"],"summary":"Download generated image","description":"Download the generated image for a completed generation.\n\n- When S3 is **enabled**: streams the image directly as `image/png`\n- When S3 is **disabled**: returns a `302` redirect to the Replicate-hosted output URL\n\n### Path parameters\n- `generation_id`: UUID of the generation\n\n### Error cases\n- `404` with `code: generation_not_found`: no record with the given ID\n- `404` with `code: object_not_found`: record exists but generation has not yet completed","operationId":"get_generation_image_api_v1_generations__generation_id__image_get","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"generation_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Generation Id"}}],"responses":{"200":{"description":"Image binary streamed as `image/png`","content":{"application/json":{"schema":{}},"image/png":{}}},"401":{"description":"Invalid or missing `X-API-Key` header","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}},"302":{"description":"Redirect to Replicate-hosted URL (when S3 is disabled)"},"404":{"description":"Not found — two distinct cases:\n- Generation record does not exist\n- Generation exists but the image is not yet available (still pending or failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}},"422":{"description":"Malformed UUID in path","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}}}}},"/api/v1/usage":{"get":{"tags":["usage"],"summary":"Get usage summary","description":"Aggregated usage stats: total generations, cost, and average response time.","operationId":"get_usage_summary_api_v1_usage_get","responses":{"200":{"description":"Aggregated usage statistics across all generations","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageSummary"}}}},"401":{"description":"Invalid or missing `X-API-Key` header","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}}},"security":[{"ApiKeyAuth":[]}]}},"/api/v1/usage/generations/{generation_id}":{"get":{"tags":["usage"],"summary":"Get usage logs for a generation","description":"Retrieve all AI usage log entries recorded for a given generation.\n\n### Path parameters\n- `generation_id`: UUID of the generation","operationId":"get_generation_usage_api_v1_usage_generations__generation_id__get","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"generation_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Generation Id"}}],"responses":{"200":{"description":"List of AI usage log entries for the generation (empty if none recorded)","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AiUsageLogRead"},"title":"Response 200 Get Generation Usage Api V1 Usage Generations  Generation Id  Get"}}}},"401":{"description":"Invalid or missing `X-API-Key` header","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}},"404":{"description":"Generation not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}},"422":{"description":"Malformed UUID in path","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}}}}},"/api/v1/sessions/{session_id}/conversations":{"post":{"tags":["conversation"],"summary":"Create a new conversation in a session","operationId":"create_conversation_api_v1_sessions__session_id__conversations_post","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["conversation"],"summary":"List conversations in a session","operationId":"list_conversations_api_v1_sessions__session_id__conversations_get","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ConversationRead"},"title":"Response List Conversations Api V1 Sessions  Session Id  Conversations Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/conversations/{conversation_id}":{"get":{"tags":["conversation"],"summary":"Get conversation by ID","operationId":"get_conversation_api_v1_conversations__conversation_id__get","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"conversation_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Conversation Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["conversation"],"summary":"Archive a conversation","operationId":"archive_conversation_api_v1_conversations__conversation_id__delete","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"conversation_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Conversation Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/conversations/{conversation_id}/messages":{"get":{"tags":["conversation"],"summary":"List messages in a conversation (paginated)","operationId":"list_messages_api_v1_conversations__conversation_id__messages_get","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"conversation_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Conversation Id"}},{"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"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MessageRead"},"title":"Response List Messages Api V1 Conversations  Conversation Id  Messages Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["conversation"],"summary":"Send a message to a conversation","operationId":"send_message_api_v1_conversations__conversation_id__messages_post","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"conversation_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Conversation Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/conversations/{conversation_id}/chat":{"post":{"tags":["chat"],"summary":"Send a message and queue AI response","description":"Queue a user message for AI processing. Returns 202 immediately.\n\nThe AI response is generated asynchronously by a background worker.\nPoll `GET /conversations/{conversation_id}/messages/{message_id}/status`\nor wait for the callback POST to `callback_url` (if provided).\n\nReturns a `MessageStatusRead` with `status: pending` and an empty `content`.\nWhen the worker finishes, `status` transitions to `completed` (or `failed`)\nand `content` is filled with the assistant reply.","operationId":"chat_api_v1_conversations__conversation_id__chat_post","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"conversation_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Conversation Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatRequest"}}}},"responses":{"202":{"description":"Message accepted and queued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageStatusRead"}}}},"409":{"description":"Another message is already being processed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}},"503":{"description":"Task dispatch failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}}}}},"/api/v1/conversations/{conversation_id}/messages/{message_id}/status":{"get":{"tags":["chat"],"summary":"Poll async chat message status","description":"Lightweight polling endpoint for async chat messages.\n\nReturns `status` (`pending`, `processing`, `completed`, or `failed`) and\n`content` (empty until completed). Use this as a fallback if you do not\nreceive the callback.","operationId":"get_message_status_api_v1_conversations__conversation_id__messages__message_id__status_get","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"conversation_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Conversation Id"}},{"name":"message_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Message Id"}}],"responses":{"200":{"description":"Message status snapshot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageStatusRead"}}}},"404":{"description":"Message not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/survey-templates":{"get":{"tags":["survey"],"summary":"List active survey templates","operationId":"list_templates_api_v1_survey_templates_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/SurveyTemplateRead"},"type":"array","title":"Response List Templates Api V1 Survey Templates Get"}}}}},"security":[{"ApiKeyAuth":[]}]},"post":{"tags":["survey"],"summary":"Create a survey template","operationId":"create_template_api_v1_survey_templates_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SurveyTemplateCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SurveyTemplateRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"ApiKeyAuth":[]}]}},"/api/v1/survey-templates/{key}":{"get":{"tags":["survey"],"summary":"Get survey template by key","operationId":"get_template_api_v1_survey_templates__key__get","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string","title":"Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SurveyTemplateRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/survey-templates/{template_id}":{"put":{"tags":["survey"],"summary":"Update a survey template","operationId":"update_template_api_v1_survey_templates__template_id__put","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SurveyTemplateUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SurveyTemplateRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/sessions/{session_id}/survey":{"get":{"tags":["survey"],"summary":"Get current survey state for a session","operationId":"get_survey_state_api_v1_sessions__session_id__survey_get","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SurveyStateRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/sessions/{session_id}/survey/reset":{"post":{"tags":["survey"],"summary":"Reset survey state for a session","operationId":"reset_survey_state_api_v1_sessions__session_id__survey_reset_post","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SurveyStateRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/config/system-prompt":{"get":{"tags":["config"],"summary":"Get current system prompt config (response language)","operationId":"get_system_prompt_config_api_v1_config_system_prompt_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SystemPromptConfig"}}}}},"security":[{"ApiKeyAuth":[]}]},"post":{"tags":["config"],"summary":"Update system prompt config (response language; creates new version)","operationId":"set_system_prompt_config_api_v1_config_system_prompt_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SystemPromptConfig"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentConfigRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"ApiKeyAuth":[]}]}},"/api/v1/config/agent":{"get":{"tags":["config"],"summary":"Get current agent parameters (model, temperature)","operationId":"get_agent_params_config_api_v1_config_agent_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentParamsConfig"}}}}},"security":[{"ApiKeyAuth":[]}]},"post":{"tags":["config"],"summary":"Update agent parameters (creates new version)","operationId":"set_agent_params_config_api_v1_config_agent_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentParamsConfig"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentConfigRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"ApiKeyAuth":[]}]}},"/api/v1/prompt-templates":{"get":{"tags":["prompt-template"],"summary":"List effective prompt templates per transformation type","description":"Return the currently effective prompt template for every\n`TransformationType`.  For each type:\n\n- if a DB-backed active row exists, the latest one is returned with\n  `source=\"db\"`,\n- otherwise the static fallback baked into the service is returned\n  with `source=\"static\"`.\n\nThe list always covers the full enum.","operationId":"list_effective_templates_api_v1_prompt_templates_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/PromptTemplateEffective"},"type":"array","title":"Response List Effective Templates Api V1 Prompt Templates Get"}}}},"401":{"description":"Invalid or missing admin API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}},"409":{"description":"Admin API key not configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}}},"security":[{"AdminApiKeyAuth":[]}]}},"/api/v1/prompt-templates/{transformation_type}":{"patch":{"tags":["prompt-template"],"summary":"Set a new prompt template for a transformation type","description":"Set a new active prompt template for the given `transformation_type`.\n\nInsert-only — every call appends a new row preserving full history.\nPreviously active rows for the same type are deactivated so only the\nnew row is effective.  To revert, PATCH again with the older template\ncontents.","operationId":"set_template_api_v1_prompt_templates__transformation_type__patch","security":[{"AdminApiKeyAuth":[]}],"parameters":[{"name":"transformation_type","in":"path","required":true,"schema":{"$ref":"#/components/schemas/TransformationType"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromptTemplatePatch"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromptTemplateRead"}}}},"401":{"description":"Invalid or missing admin API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}},"409":{"description":"Admin API key not configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}},"422":{"description":"Invalid template body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}}}}},"/api/v1/chat-prompts":{"get":{"tags":["chat-prompt"],"summary":"List effective chat prompt fragments per section","description":"Return the currently effective editable fragment for every\n`ChatPromptSection`.  For each section:\n\n- if a DB-backed active row exists, the latest one is returned with\n  `source=\"db\"`,\n- otherwise the static fallback baked into the agent is returned with\n  `source=\"static\"`.\n\nThe list always covers the full enum.  The ReAct instructions and\nrouter prompt are internal and never exposed here.","operationId":"list_effective_chat_prompts_api_v1_chat_prompts_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ChatPromptTemplateEffective"},"type":"array","title":"Response List Effective Chat Prompts Api V1 Chat Prompts Get"}}}},"401":{"description":"Invalid or missing admin API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}},"409":{"description":"Admin API key not configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}}},"security":[{"AdminApiKeyAuth":[]}]}},"/api/v1/chat-prompts/{section}":{"patch":{"tags":["chat-prompt"],"summary":"Set a new fragment for a chat prompt section","description":"Set a new active fragment for the given `section`.\n\nOnly the sections in `ChatPromptSection` are editable — the ReAct\ninstructions and router prompt cannot be modified.\n\nInsert-only — every call appends a new row preserving full history.\nPreviously active rows for the same section are deactivated so only the\nnew row is effective.  To revert, PATCH again with the older contents.\n\nFor `guardrails_response_rules`, the literal token `{word_limit}` is\nsubstituted at render time with the agent's configured word cap, which\nalso drives the actual response-length enforcement.","operationId":"set_chat_prompt_api_v1_chat_prompts__section__patch","security":[{"AdminApiKeyAuth":[]}],"parameters":[{"name":"section","in":"path","required":true,"schema":{"$ref":"#/components/schemas/ChatPromptSection"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatPromptTemplatePatch"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatPromptTemplateRead"}}}},"401":{"description":"Invalid or missing admin API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}},"409":{"description":"Admin API key not configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}},"422":{"description":"Invalid fragment body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorResponse"}}}}}}}},"components":{"schemas":{"AgentConfigRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"key":{"type":"string","title":"Key"},"value":{"additionalProperties":true,"type":"object","title":"Value"},"version":{"type":"integer","title":"Version"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","key","value","version","created_at"],"title":"AgentConfigRead"},"AgentParamsConfig":{"properties":{"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model","description":"Override LLM model ID"},"temperature":{"anyOf":[{"type":"number","maximum":2.0,"minimum":0.0},{"type":"null"}],"title":"Temperature","description":"Override LLM temperature"},"max_iterations":{"anyOf":[{"type":"integer","maximum":50.0,"minimum":1.0},{"type":"null"}],"title":"Max Iterations","description":"Override max agent iterations"},"word_limit":{"anyOf":[{"type":"integer","maximum":2000.0,"minimum":50.0},{"type":"null"}],"title":"Word Limit","description":"Override response word limit"}},"type":"object","title":"AgentParamsConfig","description":"Configurable agent parameters — model, temperature, etc."},"AgentStateRead":{"properties":{"phase":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phase"},"images_uploaded":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Images Uploaded"},"images_assessed":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Images Assessed"},"survey_completed":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Survey Completed"},"questions_answered":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Questions Answered"}},"type":"object","title":"AgentStateRead","description":"Agent processing state returned alongside message status.\n\nFields are mode-specific — only the relevant subset is populated.\nIMAGE_COMMENT: phase, images_uploaded, images_assessed.\nSURVEY: survey_completed, questions_answered."},"AiUsageLogRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"generation_id":{"type":"string","format":"uuid","title":"Generation Id"},"provider":{"type":"string","title":"Provider"},"model":{"type":"string","title":"Model"},"input_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Input Tokens"},"output_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Output Tokens"},"response_time_ms":{"type":"integer","title":"Response Time Ms"},"cost":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Cost"},"success":{"type":"boolean","title":"Success"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","generation_id","provider","model","input_tokens","output_tokens","response_time_ms","cost","success","error_message","created_at"],"title":"AiUsageLogRead"},"AppErrorDetail":{"properties":{"code":{"type":"string","title":"Code"},"message":{"type":"string","title":"Message"}},"type":"object","required":["code","message"],"title":"AppErrorDetail","description":"Structured error body for all non-2xx responses."},"AppErrorResponse":{"properties":{"detail":{"$ref":"#/components/schemas/AppErrorDetail"}},"type":"object","required":["detail"],"title":"AppErrorResponse","description":"Standard error response body returned on all non-2xx responses."},"Body_create_generation_api_v1_sessions__session_id__generations_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"},"transformation_type":{"$ref":"#/components/schemas/TransformationType"},"model_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model Id"},"effort":{"$ref":"#/components/schemas/EffortLevel","default":"high"},"user_instructions":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Instructions"},"mask":{"anyOf":[{"type":"string","contentMediaType":"application/octet-stream"},{"type":"null"}],"title":"Mask"},"target_width":{"anyOf":[{"type":"integer","minimum":100.0},{"type":"null"}],"title":"Target Width"},"target_height":{"anyOf":[{"type":"integer","minimum":100.0},{"type":"null"}],"title":"Target Height"},"callback_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Callback Url"}},"type":"object","required":["file","transformation_type"],"title":"Body_create_generation_api_v1_sessions__session_id__generations_post"},"ChatPromptSection":{"type":"string","enum":["system_tone_of_voice","system_custom_rules","guardrails_response_rules"],"title":"ChatPromptSection","description":"Editable, versioned sections of the chat agent's prompt stack.\n\nOnly these sections are admin-modifiable. The ReAct instructions and the\nrouter prompt are intentionally absent — they are internal mechanics and\nnot editable by construction."},"ChatPromptTemplateEffective":{"properties":{"section":{"$ref":"#/components/schemas/ChatPromptSection"},"template":{"type":"string","title":"Template"},"source":{"type":"string","enum":["db","static"],"title":"Source"},"id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Id"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"}},"type":"object","required":["section","template","source"],"title":"ChatPromptTemplateEffective","description":"Effective (currently used) fragment per section.\n\n`source` discriminates DB-backed rows from static fallbacks.  Static rows\nhave no DB identifiers."},"ChatPromptTemplatePatch":{"properties":{"template":{"type":"string","maxLength":4000,"minLength":1,"title":"Template"}},"type":"object","required":["template"],"title":"ChatPromptTemplatePatch","description":"API request body for PATCH /chat-prompts/{section}."},"ChatPromptTemplateRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"section":{"$ref":"#/components/schemas/ChatPromptSection"},"template":{"type":"string","title":"Template"},"is_active":{"type":"boolean","title":"Is Active"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","section","template","is_active","created_at"],"title":"ChatPromptTemplateRead"},"ChatRequest":{"properties":{"content":{"type":"string","maxLength":10000,"minLength":1,"title":"Content"},"attachments":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Attachments"},"images":{"anyOf":[{"items":{"$ref":"#/components/schemas/ImageAttachment"},"type":"array","maxItems":5},{"type":"null"}],"title":"Images"},"callback_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Callback Url"}},"type":"object","required":["content"],"title":"ChatRequest","description":"API input for the /chat endpoint — user content with optional images and callback."},"ConversationCreate":{"properties":{"system_prompt_override":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"System Prompt Override"}},"type":"object","title":"ConversationCreate","description":"API input — user-provided fields for creating a conversation."},"ConversationRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"session_id":{"type":"string","format":"uuid","title":"Session Id"},"status":{"$ref":"#/components/schemas/ConversationStatus"},"system_prompt_override":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"System Prompt Override"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","session_id","status","system_prompt_override","created_at","updated_at"],"title":"ConversationRead"},"ConversationStatus":{"type":"string","enum":["active","archived","completed"],"title":"ConversationStatus"},"EffortLevel":{"type":"string","enum":["low","medium","high"],"title":"EffortLevel"},"GenerationRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"session_id":{"type":"string","format":"uuid","title":"Session Id"},"status":{"$ref":"#/components/schemas/GenerationStatus"},"effort":{"$ref":"#/components/schemas/EffortLevel"},"original_image_key":{"type":"string","title":"Original Image Key"},"mask_image_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mask Image Key"},"generated_image_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Generated Image Key"},"transformation_type":{"$ref":"#/components/schemas/TransformationType"},"prompt_template":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prompt Template"},"prompt_composed":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prompt Composed"},"user_instructions":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Instructions"},"ai_provider":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ai Provider"},"ai_model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ai Model"},"ai_response_time_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Ai Response Time Ms"},"input_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Input Tokens"},"output_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Output Tokens"},"callback_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Callback Url"},"estimated_cost":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Estimated Cost"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"target_width":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Target Width"},"target_height":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Target Height"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"completed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Completed At"}},"type":"object","required":["id","session_id","status","effort","original_image_key","mask_image_key","generated_image_key","transformation_type","prompt_template","prompt_composed","user_instructions","ai_provider","ai_model","ai_response_time_ms","input_tokens","output_tokens","callback_url","estimated_cost","error_message","target_width","target_height","created_at","updated_at","completed_at"],"title":"GenerationRead"},"GenerationStatus":{"type":"string","enum":["pending","processing","completed","failed"],"title":"GenerationStatus"},"GenerationStatusRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"status":{"$ref":"#/components/schemas/GenerationStatus"},"generated_image_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Generated Image Key"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"completed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Completed At"}},"type":"object","required":["id","status","generated_image_key","error_message","completed_at"],"title":"GenerationStatusRead","description":"Lightweight status response — used for polling backup and callback payload."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ImageAttachment":{"properties":{"data":{"type":"string","title":"Data","description":"Base64-encoded image data"},"content_type":{"type":"string","pattern":"^image/(png|jpeg|webp|gif)$","title":"Content Type","default":"image/png"},"filename":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filename"}},"type":"object","required":["data"],"title":"ImageAttachment","description":"A single base64-encoded image attachment."},"MessageCreate":{"properties":{"role":{"$ref":"#/components/schemas/MessageRole","default":"user"},"content":{"type":"string","maxLength":10000,"minLength":1,"title":"Content"},"attachments":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Attachments"},"images":{"anyOf":[{"items":{"$ref":"#/components/schemas/ImageAttachment"},"type":"array","maxItems":5},{"type":"null"}],"title":"Images"}},"type":"object","required":["content"],"title":"MessageCreate","description":"API input — user sends a message to a conversation."},"MessageRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"conversation_id":{"type":"string","format":"uuid","title":"Conversation Id"},"role":{"$ref":"#/components/schemas/MessageRole"},"content":{"type":"string","title":"Content"},"attachments":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Attachments"},"metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Metadata"},"status":{"type":"string","title":"Status"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","conversation_id","role","content","attachments","status","created_at"],"title":"MessageRead"},"MessageRole":{"type":"string","enum":["user","assistant","system"],"title":"MessageRole"},"MessageStatusRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"conversation_id":{"type":"string","format":"uuid","title":"Conversation Id"},"status":{"type":"string","title":"Status"},"content":{"type":"string","title":"Content"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"agent_state":{"anyOf":[{"$ref":"#/components/schemas/AgentStateRead"},{"type":"null"}]}},"type":"object","required":["id","conversation_id","status","content","created_at","updated_at"],"title":"MessageStatusRead","description":"Lightweight schema for polling the status of an async chat message."},"PromptTemplateEffective":{"properties":{"transformation_type":{"$ref":"#/components/schemas/TransformationType"},"template":{"type":"string","title":"Template"},"source":{"type":"string","enum":["db","static"],"title":"Source"},"id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Id"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"}},"type":"object","required":["transformation_type","template","source"],"title":"PromptTemplateEffective","description":"Effective (currently used) template per transformation_type.\n\n`source` discriminates DB-backed rows from static fallbacks.  Static rows\nhave no DB identifiers."},"PromptTemplatePatch":{"properties":{"template":{"type":"string","maxLength":4000,"minLength":1,"title":"Template"}},"type":"object","required":["template"],"title":"PromptTemplatePatch","description":"API request body for PATCH /prompt-templates/{transformation_type}."},"PromptTemplateRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"transformation_type":{"$ref":"#/components/schemas/TransformationType"},"template":{"type":"string","title":"Template"},"is_active":{"type":"boolean","title":"Is Active"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","transformation_type","template","is_active","created_at"],"title":"PromptTemplateRead"},"SessionCreate":{"properties":{"mode":{"$ref":"#/components/schemas/SessionMode"},"language":{"$ref":"#/components/schemas/SessionLanguage","default":"pl"}},"type":"object","required":["mode"],"title":"SessionCreate","description":"API input — only user-provided fields."},"SessionLanguage":{"type":"string","enum":["pl","en"],"title":"SessionLanguage"},"SessionMode":{"type":"string","enum":["image_gen","survey","image_comment"],"title":"SessionMode"},"SessionRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"user_id":{"type":"string","format":"uuid","title":"User Id"},"mode":{"$ref":"#/components/schemas/SessionMode"},"status":{"$ref":"#/components/schemas/SessionStatus"},"language":{"$ref":"#/components/schemas/SessionLanguage"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","user_id","mode","status","language","created_at","updated_at"],"title":"SessionRead"},"SessionStatus":{"type":"string","enum":["active","inactive","closed"],"title":"SessionStatus"},"SurveyStateRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"session_id":{"type":"string","format":"uuid","title":"Session Id"},"template_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Template Id"},"state_json":{"additionalProperties":true,"type":"object","title":"State Json"},"completed":{"type":"boolean","title":"Completed"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","session_id","template_id","state_json","completed","created_at","updated_at"],"title":"SurveyStateRead"},"SurveyTemplateCreate":{"properties":{"key":{"type":"string","maxLength":50,"minLength":1,"title":"Key"},"template_json":{"additionalProperties":true,"type":"object","title":"Template Json","description":"JSON structure defining survey questions and flow"}},"type":"object","required":["key","template_json"],"title":"SurveyTemplateCreate","description":"API input — create a survey template."},"SurveyTemplateRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"key":{"type":"string","title":"Key"},"template_json":{"additionalProperties":true,"type":"object","title":"Template Json"},"version":{"type":"integer","title":"Version"},"is_active":{"type":"boolean","title":"Is Active"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","key","template_json","version","is_active","created_at","updated_at"],"title":"SurveyTemplateRead"},"SurveyTemplateUpdate":{"properties":{"template_json":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Template Json"},"version":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Version"},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"}},"type":"object","title":"SurveyTemplateUpdate"},"SystemPromptConfig":{"properties":{"language":{"type":"string","title":"Language","description":"Default response language","default":"Polish"}},"type":"object","title":"SystemPromptConfig","description":"Configurable, non-prompt agent settings carried alongside the system prompt.\n\nTone of voice and custom rules are no longer configured here — they are\nversioned, admin-editable prompt fragments owned by ``ChatPromptService``\n(``ChatPromptSection``) and exposed via the ``/chat-prompts`` endpoints.\nOnly the response language remains here."},"TransformationType":{"type":"string","enum":["better_quality","better_lighting","add_life","real_materials","better_composition","post_production","for_client","enhance_style","custom","upscale","cut_object","replace_object"],"title":"TransformationType"},"UsageSummary":{"properties":{"total_generations":{"type":"integer","minimum":0.0,"title":"Total Generations"},"completed_generations":{"type":"integer","minimum":0.0,"title":"Completed Generations"},"failed_generations":{"type":"integer","minimum":0.0,"title":"Failed Generations"},"total_cost":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Total Cost"},"avg_response_time_ms":{"type":"number","minimum":0.0,"title":"Avg Response Time Ms"},"total_input_tokens":{"type":"integer","minimum":0.0,"title":"Total Input Tokens"},"total_output_tokens":{"type":"integer","minimum":0.0,"title":"Total Output Tokens"}},"type":"object","required":["total_generations","completed_generations","failed_generations","total_cost","avg_response_time_ms","total_input_tokens","total_output_tokens"],"title":"UsageSummary"},"UserCreate":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"username":{"type":"string","title":"Username"},"email":{"type":"string","format":"email","title":"Email"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["username","email"],"title":"UserCreate"},"UserRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"username":{"type":"string","title":"Username"},"email":{"type":"string","format":"email","title":"Email"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","username","email","created_at","updated_at"],"title":"UserRead"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}},"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key"},"AdminApiKeyAuth":{"type":"apiKey","in":"header","name":"X-Admin-API-Key"}}}}