{
  "openapi": "3.1.0",
  "info": {
    "title": "Whagons External API",
    "version": "1.0.0",
    "description": "Public Whagons external API. New integrations should use /api/v1/*. Existing /api/ext/* callers remain supported by compatibility aliases. Tenant API-key requests act as the user who created the key. Claimed agent-token requests act as the user who approved the agent. Both inherit that user's current tenant permissions and workspace visibility."
  },
  "servers": [
    {
      "url": "https://cvx-share.whagons.com",
      "description": "Production HTTP action gateway. API-key requests are scoped to the key's tenant and require the matching tenantId."
    }
  ],
  "externalDocs": {
    "description": "Whagons External API documentation",
    "url": "https://docs.whagons.com/docs/external-api"
  },
  "tags": [
    {
      "name": "Session",
      "description": "First-party user session endpoints."
    },
    {
      "name": "Reference Data",
      "description": "Tenant reference data used to build task payloads."
    },
    {
      "name": "Tasks",
      "description": "Task reads and writes."
    },
    {
      "name": "Task Subresources",
      "description": "Comments, assignments, tags, logs, approvals, and acknowledgments."
    }
  ],
  "paths": {
    "/api/v1/me/tenants": {
      "get": {
        "tags": [
          "Session"
        ],
        "summary": "List tenants for the signed-in user",
        "description": "This endpoint is for first-party authenticated user sessions and does not authenticate with tenant API keys.",
        "security": [
          {
            "UserSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Tenants visible to the signed-in user.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/GenericRow"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workspaces": {
      "get": {
        "tags": [
          "Reference Data"
        ],
        "summary": "List workspaces",
        "description": "Lists active workspaces visible to the API-key creator.",
        "security": [
          {
            "ApiKeyHeader": []
          },
          {
            "BearerApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "tenantId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Tenant identifier. Must match the tenant attached to the API key."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/GenericRow"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/spots": {
      "get": {
        "tags": [
          "Reference Data"
        ],
        "summary": "List spots",
        "description": "Lists tenant spots when the API-key creator can view spots.",
        "security": [
          {
            "ApiKeyHeader": []
          },
          {
            "BearerApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "tenantId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Tenant identifier. Must match the tenant attached to the API key."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/GenericRow"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/users": {
      "get": {
        "tags": [
          "Reference Data"
        ],
        "summary": "List users",
        "description": "Lists active tenant users when the API-key creator can view users.",
        "security": [
          {
            "ApiKeyHeader": []
          },
          {
            "BearerApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "tenantId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Tenant identifier. Must match the tenant attached to the API key."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/GenericRow"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/categories": {
      "get": {
        "tags": [
          "Reference Data"
        ],
        "summary": "List categories",
        "description": "Lists task categories when the API-key creator can view categories.",
        "security": [
          {
            "ApiKeyHeader": []
          },
          {
            "BearerApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "tenantId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Tenant identifier. Must match the tenant attached to the API key."
          },
          {
            "name": "workspaceId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional workspace filter."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/GenericRow"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/statuses": {
      "get": {
        "tags": [
          "Reference Data"
        ],
        "summary": "List statuses",
        "description": "Lists statuses, optionally filtered by category.",
        "security": [
          {
            "ApiKeyHeader": []
          },
          {
            "BearerApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "tenantId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Tenant identifier. Must match the tenant attached to the API key."
          },
          {
            "name": "categoryId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional category filter."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/GenericRow"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/priorities": {
      "get": {
        "tags": [
          "Reference Data"
        ],
        "summary": "List priorities",
        "description": "Lists priorities, optionally filtered by category.",
        "security": [
          {
            "ApiKeyHeader": []
          },
          {
            "BearerApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "tenantId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Tenant identifier. Must match the tenant attached to the API key."
          },
          {
            "name": "categoryId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional category filter."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/GenericRow"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/teams": {
      "get": {
        "tags": [
          "Reference Data"
        ],
        "summary": "List teams",
        "description": "Lists teams when the API-key creator can view teams.",
        "security": [
          {
            "ApiKeyHeader": []
          },
          {
            "BearerApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "tenantId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Tenant identifier. Must match the tenant attached to the API key."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/GenericRow"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/templates": {
      "get": {
        "tags": [
          "Reference Data"
        ],
        "summary": "List templates",
        "description": "Lists templates, optionally filtered by workspace or category.",
        "security": [
          {
            "ApiKeyHeader": []
          },
          {
            "BearerApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "tenantId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Tenant identifier. Must match the tenant attached to the API key."
          },
          {
            "name": "workspaceId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional workspace filter."
          },
          {
            "name": "categoryId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional category filter."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/GenericRow"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tags": {
      "get": {
        "tags": [
          "Reference Data"
        ],
        "summary": "List tags",
        "description": "Lists tags when the API-key creator can view tags.",
        "security": [
          {
            "ApiKeyHeader": []
          },
          {
            "BearerApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "tenantId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Tenant identifier. Must match the tenant attached to the API key."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/GenericRow"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tasks": {
      "get": {
        "tags": [
          "Tasks"
        ],
        "summary": "List or fetch visible tasks",
        "description": "Lists visible tasks for the API-key creator. Passing taskId or pgId returns a single visible task.",
        "security": [
          {
            "ApiKeyHeader": []
          },
          {
            "BearerApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "tenantId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Tenant identifier. Must match the tenant attached to the API key."
          },
          {
            "name": "taskId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Convex task ID."
          },
          {
            "name": "pgId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number"
            },
            "description": "Legacy numeric task ID. Use instead of taskId when needed."
          },
          {
            "name": "workspaceId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional workspace filter."
          },
          {
            "name": "categoryId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional category filter."
          },
          {
            "name": "statusId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional status filter."
          },
          {
            "name": "priorityId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional priority filter."
          },
          {
            "name": "teamId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional team filter."
          },
          {
            "name": "spotId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional spot filter."
          },
          {
            "name": "templateId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional template filter."
          },
          {
            "name": "assignedTo",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Use me for the API-key creator or pass a user ID."
          },
          {
            "name": "assignedToMe",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean"
            },
            "description": "Boolean alternative to assignedTo=me."
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Case-insensitive task name or description search."
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500
            },
            "description": "Maximum result count. The server clamps large values."
          }
        ],
        "responses": {
          "200": {
            "description": "A task row or an array of task rows.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/GenericRow"
                    },
                    {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/GenericRow"
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Tasks"
        ],
        "summary": "Create a task",
        "description": "Creates a task as the API-key creator and optionally assigns users.",
        "security": [
          {
            "ApiKeyHeader": []
          },
          {
            "BearerApiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TaskCreateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created task identifiers.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskCreateResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Tasks"
        ],
        "summary": "Update a task",
        "description": "Updates allowed fields on a visible task. Field-level task permissions still apply.",
        "security": [
          {
            "ApiKeyHeader": []
          },
          {
            "BearerApiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TaskUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated task identifier.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskMutationResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Tasks"
        ],
        "summary": "Delete a task",
        "description": "Soft-deletes a visible task when the API-key creator has delete-task permission.",
        "security": [
          {
            "ApiKeyHeader": []
          },
          {
            "BearerApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "tenantId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Tenant identifier. Must match the tenant attached to the API key."
          },
          {
            "name": "taskId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Convex task ID."
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TaskIdentityRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Deletion result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeleteTaskResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/task-comments": {
      "get": {
        "tags": [
          "Task Subresources"
        ],
        "summary": "List task comments",
        "security": [
          {
            "ApiKeyHeader": []
          },
          {
            "BearerApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "tenantId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Tenant identifier. Must match the tenant attached to the API key."
          },
          {
            "name": "taskId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Convex task ID."
          }
        ],
        "responses": {
          "200": {
            "description": "Task comments.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/GenericRow"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Task Subresources"
        ],
        "summary": "Create a task comment or attachment note",
        "security": [
          {
            "ApiKeyHeader": []
          },
          {
            "BearerApiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TaskCommentRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created comment identifier.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubresourceMutationResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/task-assignments": {
      "get": {
        "tags": [
          "Task Subresources"
        ],
        "summary": "List task assignments",
        "security": [
          {
            "ApiKeyHeader": []
          },
          {
            "BearerApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "tenantId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Tenant identifier. Must match the tenant attached to the API key."
          },
          {
            "name": "taskId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Convex task ID."
          }
        ],
        "responses": {
          "200": {
            "description": "Task assignment rows.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/GenericRow"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Task Subresources"
        ],
        "summary": "Update task assignments",
        "description": "Sets, adds, or removes assignees. assign-tasks permission applies unless the API-key creator only removes themselves.",
        "security": [
          {
            "ApiKeyHeader": []
          },
          {
            "BearerApiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TaskAssignmentsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Assignment update result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SetMutationResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/task-tags": {
      "get": {
        "tags": [
          "Task Subresources"
        ],
        "summary": "List task tags",
        "security": [
          {
            "ApiKeyHeader": []
          },
          {
            "BearerApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "tenantId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Tenant identifier. Must match the tenant attached to the API key."
          },
          {
            "name": "taskId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Convex task ID."
          }
        ],
        "responses": {
          "200": {
            "description": "Task tag rows.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/GenericRow"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Task Subresources"
        ],
        "summary": "Update task tags",
        "security": [
          {
            "ApiKeyHeader": []
          },
          {
            "BearerApiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TaskTagsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tag update result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SetMutationResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/task-logs": {
      "get": {
        "tags": [
          "Task Subresources"
        ],
        "summary": "List task logs",
        "security": [
          {
            "ApiKeyHeader": []
          },
          {
            "BearerApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "tenantId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Tenant identifier. Must match the tenant attached to the API key."
          },
          {
            "name": "taskId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Convex task ID."
          }
        ],
        "responses": {
          "200": {
            "description": "Task log rows.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/GenericRow"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/task-approval": {
      "post": {
        "tags": [
          "Task Subresources"
        ],
        "summary": "Approve or reject a task approval context",
        "security": [
          {
            "ApiKeyHeader": []
          },
          {
            "BearerApiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TaskApprovalRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Approval decision result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericRow"
                }
              }
            }
          },
          "400": {
            "description": "Bad request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/task-acknowledgment": {
      "post": {
        "tags": [
          "Task Subresources"
        ],
        "summary": "Acknowledge a task context",
        "security": [
          {
            "ApiKeyHeader": []
          },
          {
            "BearerApiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TaskAcknowledgmentRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledgment result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericRow"
                }
              }
            }
          },
          "400": {
            "description": "Bad request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyHeader": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "Tenant API key. Requests act as the key creator."
      },
      "BearerApiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "Tenant API key or claimed agent token passed as Authorization: Bearer whg_live_... or Authorization: Bearer whg_agent_.... API-key requests act as the key creator; agent-token requests act as the approving user."
      },
      "UserSession": {
        "type": "http",
        "scheme": "bearer",
        "description": "First-party authenticated user session token."
      }
    },
    "schemas": {
      "GenericRow": {
        "type": "object",
        "description": "Whagons row object. Shape depends on the resource.",
        "additionalProperties": true
      },
      "ErrorResponse": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string"
          }
        },
        "additionalProperties": true
      },
      "TaskCreateRequest": {
        "type": "object",
        "required": [
          "tenantId",
          "name",
          "workspaceId"
        ],
        "properties": {
          "tenantId": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "workspaceId": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "categoryId": {
            "type": "string"
          },
          "teamId": {
            "type": "string"
          },
          "templateId": {
            "type": "string"
          },
          "spotId": {
            "type": "string"
          },
          "statusId": {
            "type": "string"
          },
          "priorityId": {
            "type": "string"
          },
          "slaId": {
            "type": "string"
          },
          "dueDate": {
            "type": "number",
            "description": "Epoch milliseconds."
          },
          "startDate": {
            "type": "number",
            "description": "Epoch milliseconds."
          },
          "latitude": {
            "type": "number"
          },
          "longitude": {
            "type": "number"
          },
          "reportedByTeamId": {
            "type": "string"
          },
          "reportedByUserId": {
            "type": "string"
          },
          "userIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "additionalProperties": false
      },
      "TaskCreateResponse": {
        "type": "object",
        "required": [
          "id"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "pgId": {
            "type": [
              "number",
              "null"
            ]
          }
        },
        "additionalProperties": true
      },
      "TaskIdentityRequest": {
        "type": "object",
        "required": [
          "tenantId",
          "taskId"
        ],
        "properties": {
          "tenantId": {
            "type": "string"
          },
          "taskId": {
            "type": "string"
          }
        },
        "additionalProperties": false
      },
      "TaskUpdateRequest": {
        "type": "object",
        "required": [
          "tenantId",
          "taskId"
        ],
        "properties": {
          "tenantId": {
            "type": "string"
          },
          "taskId": {
            "type": "string"
          },
          "updates": {
            "$ref": "#/components/schemas/TaskUpdates"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "statusId": {
            "type": [
              "string",
              "null"
            ]
          },
          "priorityId": {
            "type": [
              "string",
              "null"
            ]
          },
          "teamId": {
            "type": [
              "string",
              "null"
            ]
          },
          "spotId": {
            "type": [
              "string",
              "null"
            ]
          },
          "categoryId": {
            "type": [
              "string",
              "null"
            ]
          },
          "templateId": {
            "type": [
              "string",
              "null"
            ]
          },
          "dueDate": {
            "type": [
              "number",
              "null"
            ],
            "description": "Epoch milliseconds."
          },
          "startDate": {
            "type": [
              "number",
              "null"
            ],
            "description": "Epoch milliseconds."
          },
          "latitude": {
            "type": [
              "number",
              "null"
            ]
          },
          "longitude": {
            "type": [
              "number",
              "null"
            ]
          }
        },
        "additionalProperties": false
      },
      "TaskUpdates": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "statusId": {
            "type": [
              "string",
              "null"
            ]
          },
          "priorityId": {
            "type": [
              "string",
              "null"
            ]
          },
          "teamId": {
            "type": [
              "string",
              "null"
            ]
          },
          "spotId": {
            "type": [
              "string",
              "null"
            ]
          },
          "categoryId": {
            "type": [
              "string",
              "null"
            ]
          },
          "templateId": {
            "type": [
              "string",
              "null"
            ]
          },
          "dueDate": {
            "type": [
              "number",
              "null"
            ],
            "description": "Epoch milliseconds."
          },
          "startDate": {
            "type": [
              "number",
              "null"
            ],
            "description": "Epoch milliseconds."
          },
          "latitude": {
            "type": [
              "number",
              "null"
            ]
          },
          "longitude": {
            "type": [
              "number",
              "null"
            ]
          }
        },
        "additionalProperties": false
      },
      "TaskMutationResponse": {
        "type": "object",
        "required": [
          "taskId"
        ],
        "properties": {
          "taskId": {
            "type": "string"
          }
        },
        "additionalProperties": true
      },
      "DeleteTaskResponse": {
        "type": "object",
        "required": [
          "ok",
          "taskId"
        ],
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "taskId": {
            "type": "string"
          }
        },
        "additionalProperties": true
      },
      "SubresourceMutationResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "taskId": {
            "type": "string"
          }
        },
        "additionalProperties": true
      },
      "SetMutationResponse": {
        "type": "object",
        "required": [
          "taskId"
        ],
        "properties": {
          "taskId": {
            "type": "string"
          },
          "added": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "removed": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "additionalProperties": true
      },
      "AttachmentInput": {
        "type": "object",
        "required": [
          "storageId",
          "fileName",
          "fileSize",
          "fileType"
        ],
        "properties": {
          "storageId": {
            "type": "string"
          },
          "fileName": {
            "type": "string"
          },
          "fileSize": {
            "type": "number"
          },
          "fileType": {
            "type": "string"
          }
        },
        "additionalProperties": false
      },
      "TaskCommentRequest": {
        "type": "object",
        "required": [
          "tenantId",
          "taskId"
        ],
        "properties": {
          "tenantId": {
            "type": "string"
          },
          "taskId": {
            "type": "string"
          },
          "note": {
            "type": "string"
          },
          "source": {
            "type": "string",
            "enum": [
              "comment",
              "task_attachment"
            ],
            "default": "comment"
          },
          "attachments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AttachmentInput"
            }
          },
          "mentionedUserIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "additionalProperties": false
      },
      "TaskAssignmentsRequest": {
        "type": "object",
        "required": [
          "tenantId",
          "taskId",
          "userIds"
        ],
        "properties": {
          "tenantId": {
            "type": "string"
          },
          "taskId": {
            "type": "string"
          },
          "mode": {
            "type": "string",
            "enum": [
              "set",
              "add",
              "remove"
            ],
            "default": "set"
          },
          "userIds": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "string"
            }
          }
        },
        "additionalProperties": false
      },
      "TaskTagsRequest": {
        "type": "object",
        "required": [
          "tenantId",
          "taskId"
        ],
        "properties": {
          "tenantId": {
            "type": "string"
          },
          "taskId": {
            "type": "string"
          },
          "mode": {
            "type": "string",
            "enum": [
              "set",
              "add",
              "remove"
            ],
            "default": "set"
          },
          "tagIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "additionalProperties": false
      },
      "TaskApprovalRequest": {
        "type": "object",
        "required": [
          "tenantId",
          "taskId",
          "decision"
        ],
        "properties": {
          "tenantId": {
            "type": "string"
          },
          "taskId": {
            "type": "string"
          },
          "contextId": {
            "type": "string"
          },
          "decision": {
            "type": "string",
            "enum": [
              "approved",
              "rejected"
            ]
          },
          "comment": {
            "type": "string"
          },
          "signatureStorageId": {
            "type": "string"
          }
        },
        "additionalProperties": false
      },
      "TaskAcknowledgmentRequest": {
        "type": "object",
        "required": [
          "tenantId",
          "taskId"
        ],
        "properties": {
          "tenantId": {
            "type": "string"
          },
          "taskId": {
            "type": "string"
          },
          "contextId": {
            "type": "string"
          },
          "comment": {
            "type": "string"
          }
        },
        "additionalProperties": false
      }
    }
  }
}
