{
  "openapi": "3.1.0",
  "info": {
    "title": "Tensient Integration API",
    "version": "1.0.0",
    "description": "Secret-key REST APIs for Tasks and Feedback, plus MCP for agents. Generate keys in Settings → Developer. See https://tensient.com/llms.txt for the agent index."
  },
  "servers": [{ "url": "https://tensient.com" }],
  "security": [{ "bearerAuth": [] }],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Secret API key: tns_... (not tns_pub_... for Tasks API)"
      }
    },
    "schemas": {
      "Actor": {
        "type": "object",
        "description": "Customer end-user on your product (not a Tensient login)",
        "properties": {
          "externalId": { "type": "string" },
          "email": { "type": "string", "format": "email" },
          "name": { "type": "string" }
        }
      },
      "TaskStatus": {
        "type": "string",
        "enum": ["backlog", "todo", "in_progress", "done"]
      },
      "TaskPriority": {
        "type": "string",
        "enum": ["critical", "high", "medium", "low"],
        "nullable": true
      },
      "Error": {
        "type": "object",
        "properties": { "error": { "type": "string" } }
      }
    }
  },
  "paths": {
    "/api/external/tasks": {
      "get": {
        "operationId": "listTasks",
        "summary": "List tasks",
        "parameters": [
          { "name": "status", "in": "query", "schema": { "$ref": "#/components/schemas/TaskStatus" } },
          { "name": "archived", "in": "query", "schema": { "type": "boolean" }, "description": "true = archived tasks only" },
          { "name": "workspaceId", "in": "query", "schema": { "type": "string", "format": "uuid" } }
        ],
        "responses": { "200": { "description": "Task array" }, "401": { "description": "Unauthorized" }, "429": { "description": "Rate limited" } }
      },
      "post": {
        "operationId": "createTask",
        "summary": "Create task",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["title"],
                "properties": {
                  "title": { "type": "string" },
                  "description": { "type": "string" },
                  "status": { "$ref": "#/components/schemas/TaskStatus" },
                  "priority": { "$ref": "#/components/schemas/TaskPriority" },
                  "categoryId": { "type": "string", "format": "uuid" },
                  "categoryName": { "type": "string" },
                  "milestoneId": { "type": "string", "format": "uuid" },
                  "milestoneName": { "type": "string" },
                  "assigneeName": { "type": "string" },
                  "assigneeRef": { "type": "string", "description": "user:UUID or person:UUID" },
                  "dueDate": { "type": "string", "format": "date-time" },
                  "actor": { "$ref": "#/components/schemas/Actor" }
                }
              }
            }
          }
        },
        "responses": { "201": { "description": "Created task" } }
      }
    },
    "/api/external/tasks/{id}": {
      "get": {
        "operationId": "getTask",
        "summary": "Get task",
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }],
        "responses": { "200": { "description": "Task with linkedFeedback" }, "404": { "description": "Not found" } }
      },
      "patch": {
        "operationId": "updateTask",
        "summary": "Update task",
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": { "type": "string" },
                  "description": { "type": "string" },
                  "status": { "$ref": "#/components/schemas/TaskStatus" },
                  "priority": { "$ref": "#/components/schemas/TaskPriority" },
                  "archive": { "type": "boolean" },
                  "unarchive": { "type": "boolean" },
                  "actor": { "$ref": "#/components/schemas/Actor" }
                }
              }
            }
          }
        },
        "responses": { "200": { "description": "Updated task" } }
      },
      "delete": {
        "operationId": "deleteTask",
        "summary": "Delete task",
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }],
        "responses": { "200": { "description": "Deleted" } }
      }
    },
    "/api/external/tasks/{id}/comments": {
      "get": {
        "operationId": "listTaskComments",
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }],
        "responses": { "200": { "description": "Comment array" } }
      },
      "post": {
        "operationId": "addTaskComment",
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["body"],
                "properties": {
                  "body": { "type": "string", "description": "Markdown" },
                  "actor": { "$ref": "#/components/schemas/Actor" }
                }
              }
            }
          }
        },
        "responses": { "201": { "description": "Created comment" } }
      }
    },
    "/api/external/task-categories": {
      "get": { "operationId": "listTaskCategories", "summary": "List categories", "responses": { "200": { "description": "Category array" } } },
      "post": {
        "operationId": "createTaskCategory",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": { "type": "object", "required": ["name"], "properties": { "name": { "type": "string" } } }
            }
          }
        },
        "responses": { "201": { "description": "Category" } }
      }
    },
    "/api/external/milestones": {
      "get": { "operationId": "listMilestones", "summary": "List milestones with stats", "responses": { "200": { "description": "Milestone array" } } },
      "post": {
        "operationId": "createMilestone",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["name"],
                "properties": {
                  "name": { "type": "string" },
                  "description": { "type": "string" },
                  "targetDate": { "type": "string", "format": "date-time" }
                }
              }
            }
          }
        },
        "responses": { "201": { "description": "Milestone" } }
      }
    },
    "/api/external/people": {
      "get": { "operationId": "listPeople", "summary": "List assignable people", "responses": { "200": { "description": "People options" } } },
      "post": {
        "operationId": "registerPerson",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "externalId": { "type": "string" },
                  "email": { "type": "string" },
                  "name": { "type": "string" }
                }
              }
            }
          }
        },
        "responses": { "201": { "description": "Workspace person" } }
      }
    },
    "/api/external/feedback": {
      "get": {
        "operationId": "searchFeedback",
        "summary": "Search feedback for task linking",
        "parameters": [
          { "name": "search", "in": "query", "required": true, "schema": { "type": "string" } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 20 } }
        ],
        "responses": { "200": { "description": "Feedback array" } }
      }
    },
    "/api/external/tasks/{id}/feedback-links": {
      "post": {
        "operationId": "linkTaskFeedback",
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["feedbackSubmissionId"],
                "properties": {
                  "feedbackSubmissionId": { "type": "string", "format": "uuid" },
                  "relationship": { "type": "string", "enum": ["related", "blocks"] }
                }
              }
            }
          }
        },
        "responses": { "201": { "description": "Link created" } }
      },
      "delete": {
        "operationId": "unlinkTaskFeedback",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } },
          { "name": "feedbackSubmissionId", "in": "query", "required": true, "schema": { "type": "string", "format": "uuid" } }
        ],
        "responses": { "200": { "description": "Unlinked" } }
      }
    },
    "/api/feedback/ingest": {
      "post": {
        "operationId": "ingestFeedback",
        "summary": "Submit feedback from your product",
        "description": "Accepts public or secret keys. Public keys require Origin allowlist.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["category", "subject", "description"],
                "properties": {
                  "category": { "type": "string" },
                  "subject": { "type": "string" },
                  "description": { "type": "string" },
                  "submitter": {
                    "type": "object",
                    "properties": {
                      "email": { "type": "string" },
                      "name": { "type": "string" },
                      "externalId": { "type": "string" }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": { "201": { "description": "trackingId and trackingUrl" } }
      }
    },
    "/api/mcp": {
      "post": {
        "operationId": "mcpStreamableHttp",
        "summary": "MCP Streamable HTTP (agents)",
        "description": "JSON-RPC MCP protocol. Use an MCP client (Cursor, Claude Desktop). Tools include signals, synthesis, and tasks. See /docs/quickstart.",
        "responses": { "200": { "description": "MCP protocol response" } }
      }
    }
  },
  "x-mcp": {
    "endpoint": "https://tensient.com/api/mcp",
    "documentation": "https://tensient.com/docs/quickstart",
    "llmsIndex": "https://tensient.com/llms.txt"
  }
}
