{
  "openapi": "3.1.0",
  "info": {
    "title": "Plaineo Public API",
    "version": "1.0.0",
    "summary": "Public REST API v1 for tasks, files, categories, groups, search, and recurring exceptions."
  },
  "servers": [
    {
      "url": "https://api.plaineo.com",
      "description": "Production"
    },
    {
      "url": "http://localhost:5001/sc-firebase-8526b/europe-west1/api",
      "description": "Local Firebase emulator"
    }
  ],
  "security": [
    {
      "ApiKeyAuth": []
    }
  ],
  "tags": [
    {
      "name": "Tasks"
    },
    {
      "name": "Files"
    },
    {
      "name": "Categories"
    },
    {
      "name": "Recurring Exceptions"
    },
    {
      "name": "Groups"
    },
    {
      "name": "Search"
    }
  ],
  "paths": {
    "/api/v1/openapi.json": {
      "get": {
        "operationId": "getOpenApi",
        "tags": [
          "Reference"
        ],
        "summary": "Get the OpenAPI document",
        "security": [],
        "responses": {
          "200": {
            "description": "OpenAPI document"
          }
        }
      }
    },
    "/api/v1/tasks": {
      "get": {
        "operationId": "listTasks",
        "tags": [
          "Tasks"
        ],
        "summary": "List owned and accepted shared tasks",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          },
          {
            "name": "dateFrom",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "dateTo",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "categoryCode",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Case-insensitive substring match against task title only."
          },
          {
            "name": "finished",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "$ref": "#/components/parameters/IncludeParticipants"
          }
        ],
        "responses": {
          "200": {
            "description": "Task list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Task"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      },
      "post": {
        "operationId": "createTask",
        "tags": [
          "Tasks"
        ],
        "summary": "Create a task",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateTaskRequest"
              },
              "examples": {
                "minimal": {
                  "value": {
                    "title": "Call dentist",
                    "date": "2026-06-10"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created task",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Task"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/api/v1/tasks/from-content": {
      "post": {
        "operationId": "createTaskFromContent",
        "tags": [
          "Tasks"
        ],
        "summary": "Create tasks from text, base64 content, or URL using AI extraction",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateFromContentRequest"
              },
              "examples": {
                "text": {
                  "value": {
                    "text": "Dentist appointment next Monday at 3pm"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created tasks",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "tasks"
                  ],
                  "properties": {
                    "tasks": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Task"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          }
        }
      }
    },
    "/api/v1/tasks/{id}": {
      "get": {
        "operationId": "getTask",
        "tags": [
          "Tasks"
        ],
        "summary": "Get a task detail, including safe attachment metadata",
        "parameters": [
          {
            "$ref": "#/components/parameters/TaskId"
          },
          {
            "name": "include",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated optional sections. Supported values: attachments,comments,subtasks,notes,metadata,customFields,recurring,reminders,all. When omitted, default full task DTO behavior is preserved."
          }
        ],
        "responses": {
          "200": {
            "description": "Task detail",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Task"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "put": {
        "operationId": "updateTask",
        "tags": [
          "Tasks"
        ],
        "summary": "Update a task; shared recipients need write permission",
        "parameters": [
          {
            "$ref": "#/components/parameters/TaskId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateTaskRequest"
              },
              "examples": {
                "notes": {
                  "value": {
                    "notes": "Updated via API"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated task",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Task"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "delete": {
        "operationId": "deleteTask",
        "tags": [
          "Tasks"
        ],
        "summary": "Soft-delete a task; shared recipients need write permission",
        "parameters": [
          {
            "$ref": "#/components/parameters/TaskId"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/Ok"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/v1/files": {
      "post": {
        "operationId": "uploadFile",
        "tags": [
          "Files"
        ],
        "summary": "Upload a base64 file",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UploadFileRequest"
              },
              "examples": {
                "image": {
                  "value": {
                    "fileName": "receipt.jpg",
                    "mimeType": "image/jpeg",
                    "base64": "<base64>"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "File metadata",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/File"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          }
        }
      }
    },
    "/api/v1/files/{id}": {
      "get": {
        "operationId": "getFile",
        "tags": [
          "Files"
        ],
        "summary": "Get file metadata and base64 content",
        "parameters": [
          {
            "$ref": "#/components/parameters/FileId"
          },
          {
            "name": "onlyThumb",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            },
            "description": "Return thumbnailBase64Content instead of base64Content."
          }
        ],
        "responses": {
          "200": {
            "description": "File DTO",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/File"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "delete": {
        "operationId": "deleteFile",
        "tags": [
          "Files"
        ],
        "summary": "Soft-delete an owned file",
        "parameters": [
          {
            "$ref": "#/components/parameters/FileId"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/Ok"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/v1/categories": {
      "get": {
        "operationId": "listCategories",
        "tags": [
          "Categories"
        ],
        "summary": "List owned and accepted shared categories",
        "responses": {
          "200": {
            "description": "Category list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Category"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/IncludeParticipants"
          }
        ]
      },
      "post": {
        "operationId": "createCategory",
        "tags": [
          "Categories"
        ],
        "summary": "Create a custom category with optional custom field schema",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCategoryRequest"
              },
              "examples": {
                "custom": {
                  "value": {
                    "code": "api_smoke",
                    "name": "API Smoke",
                    "resultStructure": [
                      {
                        "param": "severity",
                        "type": "text",
                        "description": "Severity label"
                      },
                      {
                        "param": "referenceUrl",
                        "type": "url",
                        "description": "Related issue or document URL"
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created category",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Category"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/api/v1/categories/{id}": {
      "get": {
        "operationId": "getCategory",
        "tags": [
          "Categories"
        ],
        "summary": "Get one category by id or code",
        "parameters": [
          {
            "$ref": "#/components/parameters/CategoryIdOrCode"
          }
        ],
        "responses": {
          "200": {
            "description": "Category",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Category"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "put": {
        "operationId": "updateCategory",
        "tags": [
          "Categories"
        ],
        "summary": "Update a custom category by id or code",
        "parameters": [
          {
            "$ref": "#/components/parameters/CategoryIdOrCode"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateCategoryRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated category",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Category"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/v1/recurring-exceptions/task/{taskId}": {
      "get": {
        "operationId": "listRecurringExceptions",
        "tags": [
          "Recurring Exceptions"
        ],
        "summary": "List exceptions for an accessible recurring task",
        "parameters": [
          {
            "$ref": "#/components/parameters/TaskIdPath"
          }
        ],
        "responses": {
          "200": {
            "description": "Exception list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/RecurringException"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "post": {
        "operationId": "createRecurringException",
        "tags": [
          "Recurring Exceptions"
        ],
        "summary": "Create or upsert an exception; shared recipients need write permission",
        "parameters": [
          {
            "$ref": "#/components/parameters/TaskIdPath"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RecurringExceptionWrite"
              },
              "examples": {
                "finished": {
                  "value": {
                    "instanceDate": "2026-06-10",
                    "finished": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated existing exception",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RecurringException"
                }
              }
            }
          },
          "201": {
            "description": "Created exception",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RecurringException"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/v1/recurring-exceptions/{id}": {
      "put": {
        "operationId": "updateRecurringException",
        "tags": [
          "Recurring Exceptions"
        ],
        "summary": "Update an exception; shared recipients need write permission on the parent task",
        "parameters": [
          {
            "$ref": "#/components/parameters/ExceptionId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RecurringExceptionWrite"
              },
              "examples": {
                "unfinished": {
                  "value": {
                    "finished": false
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated exception",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RecurringException"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/v1/groups": {
      "get": {
        "operationId": "listGroups",
        "tags": [
          "Groups"
        ],
        "summary": "List visible category groups and share groups",
        "parameters": [
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Case-insensitive substring match against group name, code, id, type, or category codes."
          },
          {
            "name": "includeStats",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": true
            },
            "description": "Include task counts for each group."
          },
          {
            "$ref": "#/components/parameters/IncludeParticipants"
          }
        ],
        "responses": {
          "200": {
            "description": "Group list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Group"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/api/v1/groups/{id}": {
      "get": {
        "operationId": "getGroup",
        "tags": [
          "Groups"
        ],
        "summary": "Get a visible group by id or code",
        "parameters": [
          {
            "$ref": "#/components/parameters/GroupId"
          },
          {
            "$ref": "#/components/parameters/IncludeParticipants"
          }
        ],
        "responses": {
          "200": {
            "description": "Group detail",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Group"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/v1/groups/{id}/categories": {
      "put": {
        "operationId": "updateGroupCategories",
        "tags": [
          "Groups"
        ],
        "summary": "Update category membership for an owned category group",
        "description": "Use categoryCodes to replace the full membership, or add/remove to patch it. Only category-group records owned by the API-key user can be updated.",
        "parameters": [
          {
            "$ref": "#/components/parameters/GroupId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateGroupCategoriesRequest"
              },
              "examples": {
                "addAutomation": {
                  "value": {
                    "add": [
                      "automation"
                    ]
                  }
                },
                "replaceAll": {
                  "value": {
                    "categoryCodes": [
                      "bugs",
                      "improvements",
                      "automation"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated group",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Group"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/v1/groups/{id}/tasks": {
      "get": {
        "operationId": "listGroupTasks",
        "tags": [
          "Groups"
        ],
        "summary": "List tasks resolved under a group",
        "parameters": [
          {
            "$ref": "#/components/parameters/GroupId"
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          },
          {
            "$ref": "#/components/parameters/IncludeParticipants"
          }
        ],
        "responses": {
          "200": {
            "description": "Tasks in group",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Task"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/v1/groups/{id}/context": {
      "get": {
        "operationId": "getGroupContext",
        "tags": [
          "Groups"
        ],
        "summary": "Get compact group context with counts, category breakdown, and representative tasks",
        "parameters": [
          {
            "$ref": "#/components/parameters/GroupId"
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 50
            },
            "description": "Maximum recent/unfinished tasks returned in each list."
          }
        ],
        "responses": {
          "200": {
            "description": "Group context",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GroupContext"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/v1/search": {
      "get": {
        "operationId": "search",
        "tags": [
          "Search"
        ],
        "summary": "Search visible tasks, groups, and categories using indexed task search by default",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Search text."
          },
          {
            "name": "types",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated subset: tasks,groups,categories."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "categoryCode",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Optional fast task-search scope: only search tasks in this category code."
          },
          {
            "name": "groupId",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Optional fast task-search scope: only search tasks in this group id or code."
          },
          {
            "name": "scope",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "indexed",
                "all"
              ],
              "default": "indexed"
            },
            "description": "Task search scope. Default uses the compact task search index. Use all to force the slower exhaustive task scan fallback."
          }
        ],
        "responses": {
          "200": {
            "description": "Search results",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SearchResult"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        },
        "description": "Task search uses the compact search index by default. Scoped task search with categoryCode or groupId avoids global scans. Existing unindexed accounts fall back to an exhaustive scan until POST /api/v1/search/reindex is run."
      }
    },
    "/api/v1/categories/{id}/tasks": {
      "get": {
        "operationId": "listCategoryTasks",
        "tags": [
          "Categories"
        ],
        "summary": "List tasks in a category by id or code",
        "parameters": [
          {
            "$ref": "#/components/parameters/CategoryIdOrCode"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          },
          {
            "name": "finished",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Case-insensitive title substring search."
          },
          {
            "name": "hasComments",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean"
            },
            "description": "Only include tasks that have at least one non-deleted comment when true, or no visible comments when false."
          },
          {
            "name": "hasAttachments",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean"
            },
            "description": "Only include tasks that have attachments when true, or no attachments when false."
          },
          {
            "name": "attachmentMimeType",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Only include tasks with an attachment matching this MIME type or prefix, e.g. image/ or image/jpeg."
          },
          {
            "name": "include",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated optional sections. Supported values: attachments,comments,subtasks,notes,metadata,customFields,recurring,reminders,all. When omitted, default full task DTO behavior is preserved."
          }
        ],
        "responses": {
          "200": {
            "description": "Tasks in category",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Task"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/v1/categories/{id}/context": {
      "get": {
        "operationId": "getCategoryContext",
        "tags": [
          "Categories"
        ],
        "summary": "Get compact category context with task, photo, and comment counts",
        "parameters": [
          {
            "$ref": "#/components/parameters/CategoryIdOrCode"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 50
            },
            "description": "Maximum recent/unfinished tasks returned in each list."
          }
        ],
        "responses": {
          "200": {
            "description": "Category context",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CategoryContext"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/v1/files/{id}/inspect": {
      "get": {
        "operationId": "inspectFile",
        "tags": [
          "Files"
        ],
        "summary": "Inspect file metadata and thumbnail readability",
        "parameters": [
          {
            "$ref": "#/components/parameters/FileId"
          }
        ],
        "responses": {
          "200": {
            "description": "File inspection",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileInspection"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/v1/search/reindex": {
      "post": {
        "operationId": "reindexPublicSearch",
        "tags": [
          "Search"
        ],
        "summary": "Backfill the compact task search index for the authenticated API-key user",
        "responses": {
          "200": {
            "description": "Reindex result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "total",
                    "indexed",
                    "skipped"
                  ],
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "total": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "indexed": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "skipped": {
                      "type": "integer",
                      "minimum": 0
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key"
      }
    },
    "parameters": {
      "TaskId": {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "TaskIdPath": {
        "name": "taskId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "FileId": {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "ExceptionId": {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "GroupId": {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "description": "Group id or group code."
      },
      "CategoryIdOrCode": {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "description": "Category id or category code."
      },
      "IncludeParticipants": {
        "name": "includeParticipants",
        "in": "query",
        "required": false,
        "schema": {
          "type": "boolean",
          "default": false
        },
        "description": "Include full access participant metadata. Defaults to false for faster list/search/agent reads."
      }
    },
    "responses": {
      "Ok": {
        "description": "Success",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "ok"
              ],
              "properties": {
                "ok": {
                  "const": true
                }
              }
            }
          }
        }
      },
      "BadRequest": {
        "description": "Bad request",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing, invalid, or revoked API key",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Forbidden": {
        "description": "The API key user does not have the required permission",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "Resource not found or not visible to this API key",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "PayloadTooLarge": {
        "description": "Payload too large",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unprocessable": {
        "description": "Request could not be processed",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string"
          }
        },
        "additionalProperties": false
      },
      "Permissions": {
        "type": "object",
        "required": [
          "read",
          "write",
          "share"
        ],
        "properties": {
          "read": {
            "const": true
          },
          "write": {
            "type": "boolean"
          },
          "share": {
            "type": "boolean"
          }
        },
        "additionalProperties": false
      },
      "Participant": {
        "type": "object",
        "required": [
          "participantId",
          "permissions"
        ],
        "properties": {
          "participantId": {
            "type": "string"
          },
          "permissions": {
            "$ref": "#/components/schemas/Permissions"
          }
        },
        "additionalProperties": false
      },
      "Access": {
        "type": "object",
        "required": [
          "access",
          "ownerId",
          "permissions"
        ],
        "properties": {
          "access": {
            "enum": [
              "owner",
              "shared"
            ]
          },
          "ownerId": {
            "type": "string"
          },
          "shareId": {
            "type": "string"
          },
          "permissions": {
            "$ref": "#/components/schemas/Permissions"
          },
          "participants": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Participant"
            }
          }
        },
        "additionalProperties": false
      },
      "Comment": {
        "type": "object",
        "required": [
          "id",
          "text",
          "authorId",
          "createdAt"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "text": {
            "type": "string"
          },
          "authorId": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "editedAt": {
            "type": "string",
            "format": "date-time"
          },
          "deletedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "additionalProperties": false
      },
      "Subtask": {
        "type": "object",
        "required": [
          "text"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "text": {
            "type": "string"
          },
          "finished": {
            "type": "boolean"
          },
          "deleted": {
            "type": "boolean"
          }
        },
        "additionalProperties": false
      },
      "TaskAttachment": {
        "type": "object",
        "required": [
          "fileId",
          "thumbnailAvailable"
        ],
        "properties": {
          "fileId": {
            "type": "string"
          },
          "fileName": {
            "type": "string"
          },
          "mimeType": {
            "type": "string"
          },
          "fileType": {
            "type": "string"
          },
          "fileSize": {
            "type": "integer"
          },
          "description": {
            "type": "string"
          },
          "order": {
            "type": "number"
          },
          "addedAt": {
            "type": "string",
            "format": "date-time"
          },
          "thumbnailAvailable": {
            "type": "boolean"
          }
        },
        "additionalProperties": false
      },
      "Task": {
        "type": "object",
        "required": [
          "id",
          "title",
          "access"
        ],
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "notes": {
            "type": "string"
          },
          "date": {
            "type": "string",
            "format": "date"
          },
          "start": {
            "type": "string"
          },
          "end": {
            "type": "string"
          },
          "allDay": {
            "type": "boolean"
          },
          "categoryId": {
            "type": "string"
          },
          "categoryCode": {
            "type": "string"
          },
          "categoryName": {
            "type": "string",
            "description": "Human-readable category display name, useful for custom category codes."
          },
          "finished": {
            "type": "boolean"
          },
          "cancelled": {
            "type": "boolean"
          },
          "assignment": {
            "type": "string"
          },
          "week": {
            "type": "object"
          },
          "locationText": {
            "type": "string"
          },
          "titleImageId": {
            "type": "string"
          },
          "listOrder": {
            "type": "number"
          },
          "comments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Comment"
            }
          },
          "subtasks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Subtask"
            }
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true
          },
          "customFields": {
            "type": "object",
            "additionalProperties": true
          },
          "recurring": {
            "type": "object",
            "additionalProperties": true
          },
          "recurrenceUnmapped": {
            "type": "boolean"
          },
          "reminders": {
            "type": "array",
            "items": {}
          },
          "attachments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TaskAttachment"
            }
          },
          "access": {
            "$ref": "#/components/schemas/Access"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CreateTaskRequest": {
        "type": "object",
        "required": [
          "title"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "notes": {
            "type": "string"
          },
          "date": {
            "type": "string",
            "format": "date"
          },
          "start": {
            "type": "string"
          },
          "end": {
            "type": "string"
          },
          "categoryId": {
            "type": "string"
          },
          "categoryCode": {
            "type": "string"
          },
          "finished": {
            "type": "boolean"
          },
          "cancelled": {
            "type": "boolean"
          },
          "recurring": {
            "type": "object",
            "additionalProperties": true
          },
          "subtasks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Subtask"
            }
          },
          "reminders": {
            "type": "array",
            "items": {}
          },
          "attachments": {
            "type": "array",
            "items": {
              "oneOf": [
                {
                  "$ref": "#/components/schemas/InlineAttachmentInput"
                },
                {
                  "$ref": "#/components/schemas/FileAttachmentInput"
                }
              ]
            }
          },
          "comments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CommentInput"
            }
          },
          "customFields": {
            "type": "object",
            "additionalProperties": true
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "additionalProperties": false
      },
      "UpdateTaskRequest": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string"
          },
          "notes": {
            "type": "string"
          },
          "date": {
            "type": "string",
            "format": "date"
          },
          "start": {
            "type": "string"
          },
          "end": {
            "type": "string"
          },
          "categoryId": {
            "type": "string"
          },
          "categoryCode": {
            "type": "string"
          },
          "finished": {
            "type": "boolean"
          },
          "cancelled": {
            "type": "boolean"
          },
          "recurring": {
            "type": "object",
            "additionalProperties": true
          },
          "subtasks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Subtask"
            }
          },
          "reminders": {
            "type": "array",
            "items": {}
          },
          "attachments": {
            "type": "array",
            "items": {
              "oneOf": [
                {
                  "$ref": "#/components/schemas/InlineAttachmentInput"
                },
                {
                  "$ref": "#/components/schemas/FileAttachmentInput"
                }
              ]
            }
          },
          "comments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CommentInput"
            }
          },
          "customFields": {
            "type": "object",
            "additionalProperties": true
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "additionalProperties": false
      },
      "InlineAttachmentInput": {
        "type": "object",
        "required": [
          "fileName",
          "mimeType",
          "base64"
        ],
        "properties": {
          "fileName": {
            "type": "string"
          },
          "mimeType": {
            "type": "string"
          },
          "base64": {
            "type": "string"
          },
          "thumbBase64": {
            "type": "string"
          },
          "order": {
            "type": "number"
          }
        },
        "additionalProperties": false
      },
      "FileAttachmentInput": {
        "type": "object",
        "required": [
          "fileId"
        ],
        "properties": {
          "fileId": {
            "type": "string"
          },
          "order": {
            "type": "number"
          }
        },
        "additionalProperties": false
      },
      "CreateFromContentRequest": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string"
          },
          "base64": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "mimeType": {
            "type": "string"
          },
          "fileName": {
            "type": "string"
          },
          "categoryCode": {
            "type": "string"
          },
          "idempotencyKey": {
            "type": "string",
            "description": "Optional stable key supplied by the caller. Reusing the same key for the same request prevents duplicate task/file documents on retries."
          }
        },
        "additionalProperties": false
      },
      "UploadFileRequest": {
        "type": "object",
        "required": [
          "fileName",
          "mimeType",
          "base64"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "fileName": {
            "type": "string"
          },
          "mimeType": {
            "type": "string"
          },
          "base64": {
            "type": "string"
          },
          "thumbBase64": {
            "type": "string"
          },
          "description": {
            "type": "string"
          }
        },
        "additionalProperties": false
      },
      "File": {
        "type": "object",
        "required": [
          "id",
          "fileName",
          "mimeType",
          "fileType",
          "access"
        ],
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string"
          },
          "fileName": {
            "type": "string"
          },
          "mimeType": {
            "type": "string"
          },
          "fileType": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "fileSize": {
            "type": "integer"
          },
          "thumbnailAvailable": {
            "type": "boolean"
          },
          "base64Content": {
            "type": "string"
          },
          "thumbnailBase64Content": {
            "type": "string"
          },
          "access": {
            "$ref": "#/components/schemas/Access"
          }
        }
      },
      "Category": {
        "type": "object",
        "required": [
          "id",
          "code",
          "access"
        ],
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "color": {
            "type": "string"
          },
          "icon": {
            "type": "string"
          },
          "isBuiltIn": {
            "type": "boolean"
          },
          "access": {
            "$ref": "#/components/schemas/Access"
          },
          "participants": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Participant"
            }
          },
          "resultStructure": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CategoryField"
            }
          },
          "voiceTextDescription": {
            "type": "string"
          },
          "imageDescription": {
            "type": "string"
          },
          "keywords": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "enabledForImage": {
            "type": "boolean"
          },
          "enabledForVoiceText": {
            "type": "boolean"
          }
        }
      },
      "RecurringException": {
        "type": "object",
        "required": [
          "id",
          "taskId",
          "instanceDate",
          "createdAt",
          "access"
        ],
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string"
          },
          "taskId": {
            "type": "string"
          },
          "instanceDate": {
            "type": "string"
          },
          "cancelled": {
            "type": "boolean"
          },
          "finished": {
            "type": "boolean"
          },
          "comments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Comment"
            }
          },
          "standaloneTaskId": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "access": {
            "$ref": "#/components/schemas/Access"
          }
        }
      },
      "RecurringExceptionWrite": {
        "type": "object",
        "properties": {
          "instanceDate": {
            "type": "string"
          },
          "cancelled": {
            "type": "boolean"
          },
          "finished": {
            "type": "boolean"
          },
          "comments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Comment"
            }
          }
        },
        "additionalProperties": false
      },
      "Group": {
        "type": "object",
        "required": [
          "id",
          "kind",
          "access"
        ],
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string"
          },
          "kind": {
            "enum": [
              "category-group",
              "share-group"
            ]
          },
          "name": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "groupType": {
            "type": "string"
          },
          "categoryCodes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "access": {
            "$ref": "#/components/schemas/Access"
          },
          "taskCount": {
            "type": "integer"
          },
          "unfinishedTaskCount": {
            "type": "integer"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "UpdateGroupCategoriesRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "categoryCodes": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{2,80}$"
            },
            "description": "Full replacement list of category codes for a category group."
          },
          "add": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{2,80}$"
            },
            "description": "Category codes to add to a category group."
          },
          "remove": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{2,80}$"
            },
            "description": "Category codes to remove from a category group."
          }
        }
      },
      "GroupCategorySummary": {
        "type": "object",
        "required": [
          "code",
          "taskCount",
          "unfinishedTaskCount"
        ],
        "additionalProperties": false,
        "properties": {
          "code": {
            "type": "string"
          },
          "name": {
            "type": "string",
            "description": "Human-readable category display name, useful for custom category codes."
          },
          "taskCount": {
            "type": "integer"
          },
          "unfinishedTaskCount": {
            "type": "integer"
          }
        }
      },
      "GroupContext": {
        "type": "object",
        "required": [
          "group",
          "counts",
          "categories",
          "recentTasks",
          "unfinishedTasks"
        ],
        "additionalProperties": false,
        "properties": {
          "group": {
            "$ref": "#/components/schemas/Group"
          },
          "counts": {
            "type": "object",
            "required": [
              "total",
              "unfinished",
              "finished",
              "dated",
              "undated",
              "overdue"
            ],
            "additionalProperties": false,
            "properties": {
              "total": {
                "type": "integer"
              },
              "unfinished": {
                "type": "integer"
              },
              "finished": {
                "type": "integer"
              },
              "dated": {
                "type": "integer"
              },
              "undated": {
                "type": "integer"
              },
              "overdue": {
                "type": "integer"
              }
            }
          },
          "categories": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GroupCategorySummary"
            }
          },
          "recentTasks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Task"
            }
          },
          "unfinishedTasks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Task"
            }
          }
        }
      },
      "SearchResult": {
        "type": "object",
        "required": [
          "type",
          "id",
          "title",
          "score",
          "matchFields"
        ],
        "additionalProperties": false,
        "properties": {
          "type": {
            "enum": [
              "task",
              "group",
              "category"
            ]
          },
          "id": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "score": {
            "type": "number"
          },
          "matchFields": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "categoryCode": {
            "type": "string"
          },
          "categoryName": {
            "type": "string",
            "description": "Human-readable category display name, useful for custom category codes."
          },
          "groupIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "access": {
            "$ref": "#/components/schemas/Access"
          },
          "task": {
            "$ref": "#/components/schemas/Task"
          },
          "group": {
            "$ref": "#/components/schemas/Group"
          },
          "category": {
            "$ref": "#/components/schemas/Category"
          }
        }
      },
      "CategoryContext": {
        "type": "object",
        "required": [
          "category",
          "counts",
          "recentTasks",
          "unfinishedTasks"
        ],
        "additionalProperties": false,
        "properties": {
          "category": {
            "$ref": "#/components/schemas/Category"
          },
          "counts": {
            "type": "object",
            "required": [
              "total",
              "unfinished",
              "finished",
              "withAttachments",
              "withComments",
              "withPhotos"
            ],
            "additionalProperties": false,
            "properties": {
              "total": {
                "type": "integer"
              },
              "unfinished": {
                "type": "integer"
              },
              "finished": {
                "type": "integer"
              },
              "withAttachments": {
                "type": "integer"
              },
              "withComments": {
                "type": "integer"
              },
              "withPhotos": {
                "type": "integer"
              }
            }
          },
          "recentTasks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Task"
            }
          },
          "unfinishedTasks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Task"
            }
          }
        }
      },
      "FileInspection": {
        "type": "object",
        "required": [
          "id",
          "fileName",
          "mimeType",
          "fileType",
          "thumbnailAvailable",
          "thumbnailReadable",
          "isImage",
          "isDocument"
        ],
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string"
          },
          "fileName": {
            "type": "string"
          },
          "mimeType": {
            "type": "string"
          },
          "fileType": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "fileSize": {
            "type": "integer"
          },
          "thumbnailAvailable": {
            "type": "boolean"
          },
          "thumbnailReadable": {
            "type": "boolean"
          },
          "thumbnailBase64Length": {
            "type": "integer"
          },
          "isImage": {
            "type": "boolean"
          },
          "isDocument": {
            "type": "boolean"
          }
        }
      },
      "CommentInput": {
        "type": "object",
        "required": [
          "text"
        ],
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string"
          },
          "text": {
            "type": "string"
          },
          "authorId": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "editedAt": {
            "type": "string",
            "format": "date-time"
          },
          "deletedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CategoryField": {
        "type": "object",
        "required": [
          "param",
          "type",
          "description"
        ],
        "additionalProperties": false,
        "properties": {
          "param": {
            "type": "string",
            "pattern": "^[A-Za-z][A-Za-z0-9_]{0,79}$"
          },
          "type": {
            "enum": [
              "text",
              "number",
              "boolean",
              "currency",
              "date",
              "datetime",
              "url",
              "phone",
              "email",
              "place",
              "json"
            ]
          },
          "description": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "options": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CategoryFieldOption"
            }
          },
          "aiFormatHint": {
            "type": "string"
          },
          "calendarRole": {
            "enum": [
              "event-start",
              "event-end"
            ]
          }
        }
      },
      "CategoryFieldOption": {
        "type": "object",
        "required": [
          "value",
          "label"
        ],
        "additionalProperties": false,
        "properties": {
          "value": {
            "type": "string",
            "pattern": "^[a-z][a-z0-9_]{0,79}$"
          },
          "label": {
            "type": "string",
            "maxLength": 80
          }
        }
      },
      "CreateCategoryRequest": {
        "type": "object",
        "required": [
          "code"
        ],
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string"
          },
          "code": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_-]{2,80}$"
          },
          "name": {
            "type": "string"
          },
          "color": {
            "type": "string"
          },
          "icon": {
            "type": "string"
          },
          "resultStructure": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CategoryField"
            }
          },
          "voiceTextDescription": {
            "type": "string"
          },
          "imageDescription": {
            "type": "string"
          },
          "keywords": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "enabledForImage": {
            "type": "boolean"
          },
          "enabledForVoiceText": {
            "type": "boolean"
          }
        }
      },
      "UpdateCategoryRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string"
          },
          "color": {
            "type": "string"
          },
          "icon": {
            "type": "string"
          },
          "resultStructure": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CategoryField"
            }
          },
          "voiceTextDescription": {
            "type": "string"
          },
          "imageDescription": {
            "type": "string"
          },
          "keywords": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "enabledForImage": {
            "type": "boolean"
          },
          "enabledForVoiceText": {
            "type": "boolean"
          }
        }
      }
    }
  }
}
