{
  "openapi": "3.1.0",
  "info": {
    "title": "Impactly External API",
    "version": "1.0.0",
    "description": "API for third-party AI systems to interact with Impactly workspaces. Agents can understand context, take actions, and leave traces."
  },
  "servers": [{ "url": "/api/v1" }],
  "security": [{ "bearerAuth": [] }],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key obtained from Impactly workspace settings"
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": { "type": "string" },
          "message": { "type": "string" },
          "field": { "type": "string" },
          "request_id": { "type": "string", "format": "uuid" }
        },
        "required": ["error", "message", "request_id"]
      },
      "Task": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "title": { "type": "string" },
          "description": { "type": "string", "nullable": true },
          "status": { "type": "string", "enum": ["active", "completed"] },
          "priority": { "type": "string", "enum": ["low", "medium", "high", "urgent"], "nullable": true },
          "assignee_id": { "type": "string", "format": "uuid", "nullable": true },
          "due_date": { "type": "string", "format": "date", "nullable": true },
          "created_at": { "type": "string", "format": "date-time" },
          "updated_at": { "type": "string", "format": "date-time" }
        }
      },
      "Project": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "name": { "type": "string" },
          "color": { "type": "string", "nullable": true },
          "visibility": { "type": "string", "enum": ["public", "private"] },
          "created_at": { "type": "string", "format": "date-time" }
        }
      },
      "Comment": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "task_id": { "type": "string", "format": "uuid" },
          "author_id": { "type": "string", "format": "uuid" },
          "content": { "type": "string" },
          "created_at": { "type": "string", "format": "date-time" }
        }
      },
      "TaskDependency": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "title": { "type": "string" },
          "status": { "type": "string", "enum": ["active", "completed"] }
        }
      },
      "WebhookSubscription": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "url": { "type": "string", "format": "uri" },
          "events": { "type": "array", "items": { "type": "string" } },
          "active": { "type": "boolean" },
          "consecutive_failures": { "type": "integer" },
          "created_at": { "type": "string", "format": "date-time" }
        }
      },
      "AgentProfile": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "name": { "type": "string" },
          "role": { "type": "string" },
          "allowed_actions": { "type": "object" },
          "created_at": { "type": "string", "format": "date-time" }
        }
      },
      "WebhookEvent": {
        "type": "object",
        "description": "Payload delivered to webhook subscribers",
        "properties": {
          "event": { "type": "string", "enum": ["task.created", "task.updated", "task.completed", "comment.created"] },
          "timestamp": { "type": "string", "format": "date-time" },
          "data": { "type": "object", "description": "The full task or comment row that triggered the event" }
        },
        "required": ["event", "timestamp", "data"]
      }
    },
    "responses": {
      "TaskList": {
        "description": "Paginated list of tasks",
        "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Task" } }, "next_cursor": { "type": "string", "nullable": true } }, "required": ["data"] } } }
      },
      "TaskDetail": {
        "description": "A single task",
        "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "$ref": "#/components/schemas/Task" } }, "required": ["data"] } } }
      },
      "ProjectList": {
        "description": "Paginated list of projects",
        "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Project" } }, "next_cursor": { "type": "string", "nullable": true } }, "required": ["data"] } } }
      },
      "ProjectDetail": {
        "description": "A single project",
        "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "$ref": "#/components/schemas/Project" } }, "required": ["data"] } } }
      },
      "CommentList": {
        "description": "Paginated list of comments",
        "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Comment" } }, "next_cursor": { "type": "string", "nullable": true } }, "required": ["data"] } } }
      },
      "CommentDetail": {
        "description": "A single comment",
        "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "$ref": "#/components/schemas/Comment" } }, "required": ["data"] } } }
      },
      "DependencyList": {
        "description": "Array of task dependencies",
        "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/TaskDependency" } } }, "required": ["data"] } } }
      },
      "WebhookList": {
        "description": "List of webhook subscriptions",
        "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/WebhookSubscription" } } }, "required": ["data"] } } }
      },
      "WebhookDetail": {
        "description": "A single webhook subscription",
        "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "$ref": "#/components/schemas/WebhookSubscription" } }, "required": ["data"] } } }
      },
      "ValidationError": {
        "description": "Validation error",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      },
      "Forbidden": {
        "description": "Insufficient permissions",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      },
      "NotFound": {
        "description": "Resource not found",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      }
    },
    "parameters": {
      "cursor": { "name": "cursor", "in": "query", "schema": { "type": "string" }, "description": "Pagination cursor" },
      "limit": { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 25 }, "description": "Results per page (max 100)" }
    }
  },
  "paths": {
    "/tasks": {
      "get": {
        "summary": "List tasks",
        "parameters": [
          { "name": "project_id", "in": "query", "schema": { "type": "string" } },
          { "name": "status", "in": "query", "schema": { "type": "string", "enum": ["active", "completed"] } },
          { "name": "priority", "in": "query", "schema": { "type": "string", "enum": ["low", "medium", "high", "urgent"] }, "description": "Filter by priority" },
          { "name": "assignee_id", "in": "query", "schema": { "type": "string", "format": "uuid" }, "description": "Filter by assignee" },
          { "name": "due_date_before", "in": "query", "schema": { "type": "string", "format": "date" }, "description": "Tasks due on or before this date" },
          { "name": "due_date_after", "in": "query", "schema": { "type": "string", "format": "date" }, "description": "Tasks due on or after this date" },
          { "$ref": "#/components/parameters/cursor" },
          { "$ref": "#/components/parameters/limit" }
        ],
        "responses": {
          "200": { "$ref": "#/components/responses/TaskList" },
          "403": { "$ref": "#/components/responses/Forbidden" }
        }
      },
      "post": {
        "summary": "Create a task",
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": {
            "type": "object",
            "required": ["title"],
            "properties": {
              "title": { "type": "string" },
              "project_id": { "type": "string", "format": "uuid" },
              "description": { "type": "string" },
              "assignee_id": { "type": "string", "format": "uuid" },
              "priority": { "type": "string", "enum": ["low", "medium", "high", "urgent"] },
              "parent_task_id": { "type": "string", "format": "uuid", "description": "Parent task ID for creating subtasks" },
              "due_date": { "type": "string", "format": "date" }
            }
          } } }
        },
        "responses": {
          "201": { "$ref": "#/components/responses/TaskDetail" },
          "400": { "$ref": "#/components/responses/ValidationError" },
          "403": { "$ref": "#/components/responses/Forbidden" }
        }
      }
    },
    "/tasks/{id}": {
      "get": {
        "summary": "Get a task",
        "responses": {
          "200": { "$ref": "#/components/responses/TaskDetail" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      },
      "patch": {
        "summary": "Update a task",
        "requestBody": {
          "content": { "application/json": { "schema": {
            "type": "object",
            "properties": {
              "title": { "type": "string" },
              "description": { "type": "string" },
              "status": { "type": "string", "enum": ["active", "completed"] },
              "priority": { "type": "string", "enum": ["low", "medium", "high", "urgent"] },
              "assignee_id": { "type": "string", "format": "uuid" },
              "due_date": { "type": "string", "format": "date" },
              "parent_task_id": { "type": "string", "format": "uuid", "description": "Set parent task for subtask relationship" }
            }
          } } }
        },
        "responses": {
          "200": { "$ref": "#/components/responses/TaskDetail" },
          "400": { "$ref": "#/components/responses/ValidationError" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/tasks/{id}/blockers": {
      "get": { "summary": "List tasks blocking this task", "responses": { "200": { "$ref": "#/components/responses/DependencyList" } } },
      "post": {
        "summary": "Add a blocker to this task",
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "type": "object", "required": ["blocker_id"], "properties": { "blocker_id": { "type": "string", "format": "uuid" } } } } }
        },
        "responses": { "201": { "$ref": "#/components/responses/DependencyList" }, "200": { "description": "Blocker already exists (idempotent)" } }
      }
    },
    "/tasks/{id}/blockers/{blockerId}": {
      "delete": { "summary": "Remove a blocker from this task", "responses": { "200": { "description": "Blocker removed" } } }
    },
    "/tasks/{id}/dependents": {
      "get": { "summary": "List tasks that depend on this task", "responses": { "200": { "$ref": "#/components/responses/DependencyList" } } },
      "post": {
        "summary": "Add a dependent to this task",
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "type": "object", "required": ["dependent_id"], "properties": { "dependent_id": { "type": "string", "format": "uuid" } } } } }
        },
        "responses": { "201": { "$ref": "#/components/responses/DependencyList" }, "200": { "description": "Dependent already exists (idempotent)" } }
      }
    },
    "/tasks/{id}/dependents/{dependentId}": {
      "delete": { "summary": "Remove a dependent from this task", "responses": { "200": { "description": "Dependent removed" } } }
    },
    "/tasks/{id}/comments": {
      "get": { "summary": "List task comments", "responses": { "200": { "$ref": "#/components/responses/CommentList" } } },
      "post": {
        "summary": "Add a comment",
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "type": "object", "required": ["content"], "properties": { "content": { "type": "string" } } } } }
        },
        "responses": {
          "201": { "$ref": "#/components/responses/CommentDetail" },
          "400": { "$ref": "#/components/responses/ValidationError" },
          "403": { "$ref": "#/components/responses/Forbidden" }
        }
      }
    },
    "/projects": {
      "get": { "summary": "List projects", "responses": { "200": { "$ref": "#/components/responses/ProjectList" } } }
    },
    "/projects/{id}": {
      "get": {
        "summary": "Get a project",
        "responses": {
          "200": { "$ref": "#/components/responses/ProjectDetail" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/projects/{id}/tasks": {
      "get": { "summary": "List tasks in a project", "responses": { "200": { "$ref": "#/components/responses/TaskList" } } }
    },
    "/agents/me": {
      "get": {
        "summary": "Get calling agent profile and usage",
        "responses": {
          "200": {
            "description": "Agent profile with usage stats",
            "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "$ref": "#/components/schemas/AgentProfile" } }, "required": ["data"] } } }
          }
        }
      }
    },
    "/agents/activity": {
      "get": {
        "summary": "Query agent activity",
        "parameters": [
          { "name": "since", "in": "query", "schema": { "type": "string" }, "description": "ISO 8601 timestamp or relative duration (24h, 7d, 30d)" },
          { "name": "project_id", "in": "query", "schema": { "type": "string" } },
          { "name": "agent_id", "in": "query", "schema": { "type": "string" } },
          { "$ref": "#/components/parameters/cursor" },
          { "$ref": "#/components/parameters/limit" }
        ],
        "responses": {
          "200": {
            "description": "Paginated activity feed",
            "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "type": "object" } }, "next_cursor": { "type": "string", "nullable": true } }, "required": ["data"] } } }
          }
        }
      }
    },
    "/webhooks": {
      "get": { "summary": "List webhook subscriptions", "responses": { "200": { "$ref": "#/components/responses/WebhookList" } } },
      "post": {
        "summary": "Create a webhook subscription",
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": {
            "type": "object",
            "required": ["url", "events"],
            "properties": {
              "url": { "type": "string", "format": "uri" },
              "events": { "type": "array", "items": { "type": "string", "enum": ["task.created", "task.updated", "task.completed", "comment.created"] } },
              "secret": { "type": "string" }
            }
          } } }
        },
        "responses": {
          "201": { "$ref": "#/components/responses/WebhookDetail" },
          "400": { "$ref": "#/components/responses/ValidationError" },
          "403": { "$ref": "#/components/responses/Forbidden" }
        }
      }
    },
    "/webhooks/{id}": {
      "delete": { "summary": "Delete a webhook subscription", "responses": { "204": { "description": "Deleted" } } }
    },
    "/search": {
      "post": {
        "summary": "Search tasks, projects, and people",
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "type": "object", "required": ["query"], "properties": { "query": { "type": "string" } } } } }
        },
        "responses": {
          "200": {
            "description": "Search results",
            "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "type": "object", "properties": { "type": { "type": "string", "enum": ["task", "project", "member"] }, "id": { "type": "string", "format": "uuid" }, "title": { "type": "string" }, "match_score": { "type": "number" } } } } }, "required": ["data"] } } }
          }
        }
      }
    },
    "/health": {
      "get": {
        "summary": "Health check (no auth required)",
        "security": [],
        "responses": {
          "200": {
            "description": "OK",
            "content": { "application/json": { "schema": { "type": "object", "properties": { "status": { "type": "string", "example": "ok" } } } } }
          }
        }
      }
    }
  }
}
