{
  "openapi": "3.1.0",
  "info": {
    "title": "Andru — Operational Empathy for B2B",
    "description": "Operational empathy for technical SaaS founders. Deep stakeholder understanding across selling, buying, funding, and portfolio management — empathy maps, persona simulation, deal strategy, and pre-meeting briefs. Powered by 20 years of B2B sales wisdom.",
    "version": "1.0.0",
    "contact": {
      "name": "Andru (H&S)",
      "url": "https://andru-ai.com"
    },
    "x-logo": {
      "url": "https://andru-ai.com/logo.png"
    }
  },
  "servers": [
    {
      "url": "https://hs-andru-test.onrender.com",
      "description": "Production"
    }
  ],
  "paths": {
    "/.well-known/agent.json": {
      "get": {
        "operationId": "getAgentCard",
        "summary": "A2A AgentCard discovery",
        "description": "Returns the A2A AgentCard describing Andru's capabilities, skills, and pricing.",
        "tags": [
          "Discovery"
        ],
        "responses": {
          "200": {
            "description": "AgentCard metadata",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentCard"
                }
              }
            }
          }
        }
      }
    },
    "/api/a2a/register": {
      "post": {
        "operationId": "registerAgent",
        "summary": "Get an API key for your Andru account",
        "description": "Requires a signed-in Andru account: send your Supabase session token as Authorization: Bearer <token>. Returns an API key for that account + 25 free calls/month (shared with MCP). Body fields are labels only.",
        "tags": [
          "Registration"
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RegisterRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Existing user — credentials returned",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RegisterResponse"
                }
              }
            }
          },
          "201": {
            "description": "Registration successful (new user)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RegisterResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/a2a/capabilities": {
      "get": {
        "operationId": "getCapabilities",
        "summary": "Machine-readable capabilities catalog",
        "description": "Returns all tools with prices, tiers, skills, and response time estimates. Use this to make cost/benefit decisions before submitting tasks.",
        "tags": [
          "Discovery"
        ],
        "responses": {
          "200": {
            "description": "Capabilities catalog",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Capabilities"
                }
              }
            }
          }
        }
      }
    },
    "/api/a2a/tasks": {
      "post": {
        "operationId": "submitTask",
        "summary": "Submit a task (JSON-RPC 2.0)",
        "description": "Submit a new task for execution. The body must be a JSON-RPC 2.0 request with method \"tasks/send\".",
        "tags": [
          "Tasks"
        ],
        "security": [
          {
            "apiKey": []
          },
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TaskSubmitRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Task created and queued",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcResponse"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listTasks",
        "summary": "List tasks for authenticated user",
        "tags": [
          "Tasks"
        ],
        "security": [
          {
            "apiKey": []
          },
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "submitted",
                "working",
                "completed",
                "failed",
                "canceled"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 20
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Task list",
            "content": {
              "application/json": {}
            }
          }
        }
      }
    },
    "/api/a2a/tasks/{taskId}": {
      "get": {
        "operationId": "getTask",
        "summary": "Get task status and result",
        "tags": [
          "Tasks"
        ],
        "security": [
          {
            "apiKey": []
          },
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "taskId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Task details",
            "content": {
              "application/json": {}
            }
          },
          "404": {
            "description": "Task not found"
          }
        }
      }
    },
    "/api/a2a/tasks/{taskId}/cancel": {
      "post": {
        "operationId": "cancelTask",
        "summary": "Cancel a running task",
        "tags": [
          "Tasks"
        ],
        "security": [
          {
            "apiKey": []
          },
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "taskId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Task canceled"
          },
          "404": {
            "description": "Task not found"
          }
        }
      }
    },
    "/api/a2a/tasks/{taskId}/stream": {
      "get": {
        "operationId": "streamTask",
        "summary": "Stream task updates (SSE)",
        "tags": [
          "Tasks"
        ],
        "security": [
          {
            "apiKey": []
          },
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "taskId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "SSE event stream",
            "content": {
              "text/event-stream": {}
            }
          },
          "404": {
            "description": "Task not found"
          }
        }
      }
    },
    "/api/a2a/quota": {
      "get": {
        "operationId": "getQuota",
        "summary": "Check free tier quota",
        "tags": [
          "Account"
        ],
        "security": [
          {
            "apiKey": []
          },
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Quota info",
            "content": {
              "application/json": {}
            }
          }
        }
      }
    },
    "/api/a2a/usage/summary": {
      "get": {
        "operationId": "getUsageSummary",
        "summary": "Current month usage overview",
        "tags": [
          "Analytics"
        ],
        "security": [
          {
            "apiKey": []
          },
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Usage summary"
          }
        }
      }
    },
    "/api/a2a/usage/by-agent": {
      "get": {
        "operationId": "getUsageByAgent",
        "summary": "Usage grouped by API key (agent)",
        "tags": [
          "Analytics"
        ],
        "security": [
          {
            "apiKey": []
          },
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Agent usage breakdown"
          }
        }
      }
    },
    "/api/a2a/usage/by-tool": {
      "get": {
        "operationId": "getUsageByTool",
        "summary": "Usage grouped by tool",
        "tags": [
          "Analytics"
        ],
        "security": [
          {
            "apiKey": []
          },
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Tool usage breakdown"
          }
        }
      }
    },
    "/api/a2a/usage/history": {
      "get": {
        "operationId": "getUsageHistory",
        "summary": "Daily usage time-series",
        "tags": [
          "Analytics"
        ],
        "security": [
          {
            "apiKey": []
          },
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 30,
              "maximum": 90
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Daily usage data"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "API key from /api/a2a/register"
      },
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Bearer token (same API key)"
      }
    },
    "schemas": {
      "AgentCard": {
        "type": "object",
        "description": "A2A protocol AgentCard",
        "properties": {
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "skills": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "description": {
                  "type": "string"
                },
                "tags": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "pricing": {
                  "type": "object"
                }
              }
            }
          }
        }
      },
      "RegisterRequest": {
        "type": "object",
        "description": "Registration request. All fields optional; the key is issued to the signed-in account.",
        "properties": {
          "company_name": {
            "type": "string",
            "description": "Company name, used in the key label"
          },
          "agent_name": {
            "type": "string",
            "description": "Name of the requesting agent"
          }
        }
      },
      "RegisterResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "apiKey": {
            "type": "string"
          },
          "keyId": {
            "type": "string"
          },
          "userId": {
            "type": "string"
          },
          "isNew": {
            "type": "boolean"
          },
          "freeQuota": {
            "type": "object",
            "properties": {
              "limit": {
                "type": "integer",
                "const": 25
              },
              "used": {
                "type": "integer"
              },
              "remaining": {
                "type": "integer"
              }
            }
          }
        }
      },
      "Capabilities": {
        "type": "object",
        "properties": {
          "tools": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string"
                },
                "tier": {
                  "type": "string",
                  "enum": [
                    "signal",
                    "intelligence",
                    "strategy"
                  ]
                },
                "price_cents": {
                  "type": "integer"
                },
                "price_display": {
                  "type": "string"
                },
                "skill": {
                  "type": "string"
                },
                "description": {
                  "type": "string"
                },
                "avg_response_ms": {
                  "type": "integer"
                }
              }
            }
          },
          "tiers": {
            "type": "object"
          },
          "free_tier": {
            "type": "object"
          }
        }
      },
      "TaskSubmitRequest": {
        "type": "object",
        "description": "JSON-RPC 2.0 request for task submission",
        "required": [
          "jsonrpc",
          "method",
          "params"
        ],
        "properties": {
          "jsonrpc": {
            "type": "string",
            "const": "2.0"
          },
          "method": {
            "type": "string",
            "const": "tasks/send"
          },
          "id": {
            "type": "string"
          },
          "params": {
            "type": "object",
            "description": "Name the skill (skill or skillId), then give the tool and its arguments either in a data part of message.parts or in input. Text parts are accepted but are not used as product context.",
            "properties": {
              "skill": {
                "type": "string",
                "description": "Target skill ID"
              },
              "skillId": {
                "type": "string",
                "description": "Target skill ID (same as skill)"
              },
              "taskId": {
                "type": "string",
                "description": "Answer a task paused in input-required: send its taskId with the requested fields in a data part (for product context, just { website }). The task resumes and finishes."
              },
              "message": {
                "type": "object",
                "required": [
                  "parts",
                  "role"
                ],
                "properties": {
                  "role": {
                    "type": "string",
                    "const": "user"
                  },
                  "parts": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "description": "A data part carries { tool?, args? } (or the args themselves), e.g. { kind: \"data\", data: { tool: \"get_icp_fit_score\", args: { productDescription, vertical, targetRole } } }.",
                      "properties": {
                        "kind": {
                          "type": "string",
                          "enum": [
                            "text",
                            "data"
                          ]
                        },
                        "type": {
                          "type": "string",
                          "description": "Older name for kind"
                        },
                        "text": {
                          "type": "string"
                        },
                        "data": {
                          "type": "object"
                        }
                      }
                    }
                  }
                }
              },
              "input": {
                "type": "object",
                "description": "Alternative to a data part: { tool, args }. Wins if both are given.",
                "properties": {
                  "tool": {
                    "type": "string"
                  },
                  "args": {
                    "type": "object"
                  }
                }
              }
            }
          }
        }
      },
      "JsonRpcResponse": {
        "type": "object",
        "properties": {
          "jsonrpc": {
            "type": "string",
            "const": "2.0"
          },
          "result": {
            "type": "object"
          },
          "error": {
            "type": "object"
          },
          "id": {
            "type": "string"
          }
        }
      }
    }
  },
  "x-tools": [
    {
      "name": "get_icp_fit_score",
      "tier": "signal",
      "price_cents": 500,
      "price_display": "$5.00",
      "skill": "buyer-understanding",
      "description": "Score a company against your Ideal Customer Profile"
    },
    {
      "name": "get_persona_profile",
      "tier": "intelligence",
      "price_cents": 1900,
      "price_display": "$19.00",
      "skill": "buyer-understanding",
      "description": "Deep-dive buyer persona analysis with empathy terrain mapping"
    },
    {
      "name": "get_disqualification_signals",
      "tier": "signal",
      "price_cents": 500,
      "price_display": "$5.00",
      "skill": "buyer-understanding",
      "description": "Identify red flags that should disqualify an opportunity"
    },
    {
      "name": "get_icp_profile",
      "tier": "signal",
      "price_cents": 500,
      "price_display": "$5.00",
      "skill": "buyer-understanding",
      "description": "Generate your Ideal Customer Profile definition"
    },
    {
      "name": "classify_opportunity",
      "tier": "intelligence",
      "price_cents": 1500,
      "price_display": "$15.00",
      "skill": "buyer-understanding",
      "description": "Classify a deal by buyer journey stage"
    },
    {
      "name": "batch_fit_score",
      "tier": "signal",
      "price_cents": 500,
      "price_display": "$5.00",
      "skill": "buyer-understanding",
      "description": "Score multiple companies against your ICP in one call"
    },
    {
      "name": "get_messaging_framework",
      "tier": "intelligence",
      "price_cents": 1500,
      "price_display": "$15.00",
      "skill": "tech-to-value-translation",
      "description": "Generate a messaging framework for a target persona"
    },
    {
      "name": "get_competitive_positioning",
      "tier": "intelligence",
      "price_cents": 1500,
      "price_display": "$15.00",
      "skill": "tech-to-value-translation",
      "description": "Competitive positioning analysis against a named competitor"
    },
    {
      "name": "get_account_plan",
      "tier": "strategy",
      "price_cents": 2500,
      "price_display": "$25.00",
      "skill": "buyer-journey-stages",
      "description": "Strategic account plan with champion identification"
    },
    {
      "name": "get_pre_brief",
      "tier": "intelligence",
      "price_cents": 1200,
      "price_display": "$12.00",
      "skill": "mutual-champion-selling",
      "description": "Pre-meeting intelligence brief for an upcoming call"
    },
    {
      "name": "get_evaluation_criteria",
      "tier": "strategy",
      "price_cents": 3900,
      "price_display": "$39.00",
      "skill": "buying-committee-navigation",
      "description": "Map the evaluation criteria for a buying committee"
    },
    {
      "name": "get_capability_profile",
      "tier": "intelligence",
      "price_cents": 1500,
      "price_display": "$15.00",
      "skill": "customer-value-realization",
      "description": "Generate a capability profile for buyer evaluation"
    },
    {
      "name": "discover_prospects",
      "tier": "intelligence",
      "price_cents": 1500,
      "price_display": "$15.00",
      "skill": "unknown",
      "description": "Discover prospect companies matching your ICP"
    },
    {
      "name": "get_sales_blueprint",
      "tier": "strategy",
      "price_cents": 2900,
      "price_display": "$29.00",
      "skill": "unknown",
      "description": "End-to-end sales blueprint for a target account"
    },
    {
      "name": "simulate_buyer_persona",
      "tier": "intelligence",
      "price_cents": 1500,
      "price_display": "$15.00",
      "skill": "pitch-practice",
      "description": "Simulate a buyer persona conversation for pitch practice"
    },
    {
      "name": "get_thesis_match",
      "tier": "strategy",
      "price_cents": 2900,
      "price_display": "$29.00",
      "skill": "investor-readiness",
      "description": "Match your company against VC investment theses"
    },
    {
      "name": "get_founder_wellness",
      "tier": "signal",
      "price_cents": 500,
      "price_display": "$5.00",
      "skill": "founder-ops",
      "description": "Assess founder burnout risk and wellness signals"
    },
    {
      "name": "get_syndication_status",
      "tier": "signal",
      "price_cents": 500,
      "price_display": "$5.00",
      "skill": "founder-ops",
      "description": "Check CRM sync and data syndication status"
    }
  ]
}
