{
  "openapi": "3.1.0",
  "info": {
    "title": "Sales as Code API",
    "version": "1.0.0",
    "summary": "Read and write the account's sales data, and run the same tools the scheduled agents run.",
    "description": "Sales as Code runs a portfolio of scheduled AI-agent products, one per\nrevenue-org role. This API exposes the tools those agents call, so an\nexternal agent can do the same work without driving the web UI.\n\nTwo transports, one registry of tools:\n\n- **REST.** `POST /api/v1/tools/{name}` with a JSON body matching that\n  tool's schema. One operation per tool below.\n- **MCP.** `POST /api/v1/mcp`, JSON-RPC 2.0, for clients that speak the\n  Model Context Protocol (`initialize`, `tools/list`, `tools/call`).\n\nAuthenticate with `Authorization: Bearer <key>`. Keys are issued in the\nproduct at https://salesascode.com/settings/api-keys, and carry scopes. OAuth 2.1 with PKCE is\nalso supported for clients that register.\n\nWrites are draft-first everywhere the product sends something on a\nperson's behalf: a tool stages a draft for approval, it does not send.",
    "contact": {
      "name": "Sales as Code",
      "url": "https://salesascode.com/contact"
    },
    "termsOfService": "https://salesascode.com/terms",
    "license": {
      "name": "Proprietary",
      "url": "https://salesascode.com/terms"
    }
  },
  "servers": [
    {
      "url": "https://salesascode.com",
      "description": "Production"
    }
  ],
  "tags": [
    {
      "name": "Tools",
      "description": "One operation per registered tool. Same handlers the MCP endpoint dispatches to."
    },
    {
      "name": "MCP",
      "description": "JSON-RPC 2.0 transport for Model Context Protocol clients."
    },
    {
      "name": "OAuth",
      "description": "Authorization code + PKCE, for clients that cannot ship a static key."
    },
    {
      "name": "Public",
      "description": "No authentication."
    }
  ],
  "externalDocs": {
    "description": "API and MCP reference",
    "url": "https://salesascode.com/docs/api"
  },
  "paths": {
    "/api/v1/tools/log_capture": {
      "post": {
        "operationId": "log_capture",
        "summary": "Log a capture (free-form note or transcript) into the brain",
        "description": "Log a capture (free-form note or transcript) into the brain. Optionally attach to an account or prospect.\n\nRequires the `capture.write` scope on the API key.\nRequires at least one active paid entitlement on the account.",
        "tags": [
          "Tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "source",
                  "text"
                ],
                "properties": {
                  "source": {
                    "type": "string",
                    "description": "Where this capture came from (e.g. \"scheduled\")."
                  },
                  "text": {
                    "type": "string",
                    "description": "The capture content."
                  },
                  "account_id": {
                    "type": "string",
                    "description": "Optional account to attach the capture to."
                  },
                  "prospect_id": {
                    "type": "string",
                    "description": "Optional prospect to attach the capture to."
                  },
                  "tags": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Optional tags."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The tool ran. The body is that tool's result object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "The request body was not valid JSON, or an argument failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No Bearer token, or the token is unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key does not hold the required scope. The account holds no active paid entitlement.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No tool by that name.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Per-key rate limit exceeded. Retry after the window.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The tool handler failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-required-scope": "capture.write",
        "x-requires-entitlement": true
      }
    },
    "/api/v1/tools/set_meddpicc": {
      "post": {
        "operationId": "set_meddpicc",
        "summary": "Set MEDDPICC evidence on an opportunity (by opp id)",
        "description": "Set MEDDPICC evidence on an opportunity (by opp id). Pass any of the eight dimensions as short text; provided dimensions are merged onto the existing record, others are left untouched. Feeds the curiosity engine's gap detection.\n\nRequires the `meddpicc.write` scope on the API key.\nRequires at least one active paid entitlement on the account.",
        "tags": [
          "Tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "opp_id"
                ],
                "properties": {
                  "opp_id": {
                    "type": "string",
                    "description": "The opportunity id (matches an opp nested in an account record)."
                  },
                  "metrics": {
                    "type": "string",
                    "description": "The quantified business outcome (Metrics)."
                  },
                  "economic_buyer": {
                    "type": "string",
                    "description": "Who controls the budget and what they need to sign (Economic Buyer)."
                  },
                  "decision_criteria": {
                    "type": "string",
                    "description": "The yardstick the buyer judges options against (Decision Criteria)."
                  },
                  "decision_process": {
                    "type": "string",
                    "description": "The steps/gates to a signature (Decision Process)."
                  },
                  "identify_pain": {
                    "type": "string",
                    "description": "The cost of inaction / pain (Implications)."
                  },
                  "champion": {
                    "type": "string",
                    "description": "Who sells for you internally (Champion)."
                  },
                  "competition": {
                    "type": "string",
                    "description": "Alternatives in play, incl. do-nothing (Competition)."
                  },
                  "paper_process": {
                    "type": "string",
                    "description": "Procurement / legal / security path (Paper Process)."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The tool ran. The body is that tool's result object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "The request body was not valid JSON, or an argument failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No Bearer token, or the token is unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key does not hold the required scope. The account holds no active paid entitlement.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No tool by that name.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Per-key rate limit exceeded. Retry after the window.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The tool handler failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-required-scope": "meddpicc.write",
        "x-requires-entitlement": true
      }
    },
    "/api/v1/tools/update_prospect": {
      "post": {
        "operationId": "update_prospect",
        "summary": "Create or update a prospect record",
        "description": "Create or update a prospect record. Omit `id` to create a new prospect.\n\nRequires the `prospect.write` scope on the API key.\nRequires at least one active paid entitlement on the account.",
        "tags": [
          "Tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "Prospect id (omit to create)."
                  },
                  "name": {
                    "type": "string"
                  },
                  "title": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string"
                  },
                  "account_id": {
                    "type": "string"
                  },
                  "notes": {
                    "type": "string"
                  },
                  "fields": {
                    "type": "object",
                    "description": "Arbitrary additional fields."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The tool ran. The body is that tool's result object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "The request body was not valid JSON, or an argument failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No Bearer token, or the token is unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key does not hold the required scope. The account holds no active paid entitlement.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No tool by that name.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Per-key rate limit exceeded. Retry after the window.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The tool handler failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-required-scope": "prospect.write",
        "x-requires-entitlement": true
      }
    },
    "/api/v1/tools/add_to_plan": {
      "post": {
        "operationId": "add_to_plan",
        "summary": "Append content to a named section of an account plan (creates the plan if it does not exist).",
        "description": "Append content to a named section of an account plan (creates the plan if it does not exist).\n\nRequires the `plan.write` scope on the API key.\nRequires at least one active paid entitlement on the account.",
        "tags": [
          "Tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "account_id",
                  "section",
                  "content"
                ],
                "properties": {
                  "account_id": {
                    "type": "string"
                  },
                  "section": {
                    "type": "string",
                    "description": "Section name (e.g. \"next_steps\", \"risks\", \"champion_notes\")."
                  },
                  "content": {
                    "type": "string",
                    "description": "Markdown-friendly content to append."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The tool ran. The body is that tool's result object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "The request body was not valid JSON, or an argument failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No Bearer token, or the token is unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key does not hold the required scope. The account holds no active paid entitlement.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No tool by that name.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Per-key rate limit exceeded. Retry after the window.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The tool handler failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-required-scope": "plan.write",
        "x-requires-entitlement": true
      }
    },
    "/api/v1/tools/mark_meeting_outcome": {
      "post": {
        "operationId": "mark_meeting_outcome",
        "summary": "Record the outcome of a meeting",
        "description": "Record the outcome of a meeting. Creates the meeting record if `meeting_id` is omitted.\n\nRequires the `meeting.write` scope on the API key.\nRequires at least one active paid entitlement on the account.",
        "tags": [
          "Tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "outcome"
                ],
                "properties": {
                  "meeting_id": {
                    "type": "string",
                    "description": "Meeting id (omit to create)."
                  },
                  "account_id": {
                    "type": "string"
                  },
                  "outcome": {
                    "type": "string",
                    "description": "\"advance\" | \"stall\" | \"lost\" | free-form summary."
                  },
                  "notes": {
                    "type": "string"
                  },
                  "next_step": {
                    "type": "string"
                  },
                  "occurred_at": {
                    "type": "string",
                    "description": "ISO timestamp; defaults to now."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The tool ran. The body is that tool's result object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "The request body was not valid JSON, or an argument failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No Bearer token, or the token is unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key does not hold the required scope. The account holds no active paid entitlement.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No tool by that name.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Per-key rate limit exceeded. Retry after the window.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The tool handler failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-required-scope": "meeting.write",
        "x-requires-entitlement": true
      }
    },
    "/api/v1/tools/read_account": {
      "post": {
        "operationId": "read_account",
        "summary": "Read an account record",
        "description": "Read an account record. Optionally include the plan, recent meetings, or recent captures attached to it.\n\nRequires the `account.read` scope on the API key.\nRequires at least one active paid entitlement on the account.",
        "tags": [
          "Tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "id"
                ],
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "include": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "plan",
                        "meetings",
                        "captures"
                      ]
                    },
                    "description": "Which related collections to include."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The tool ran. The body is that tool's result object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "The request body was not valid JSON, or an argument failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No Bearer token, or the token is unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key does not hold the required scope. The account holds no active paid entitlement.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No tool by that name.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Per-key rate limit exceeded. Retry after the window.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The tool handler failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-required-scope": "account.read",
        "x-requires-entitlement": true
      }
    },
    "/api/v1/tools/pull_brief": {
      "post": {
        "operationId": "pull_brief",
        "summary": "Pull a structured summary of recent activity (captures, meetings, open plan sections) for the user — the API counterpart of the Morning Brief.",
        "description": "Pull a structured summary of recent activity (captures, meetings, open plan sections) for the user — the API counterpart of the Morning Brief.\n\nRequires the `brief.read` scope on the API key.\nRequires at least one active paid entitlement on the account.",
        "tags": [
          "Tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "scope": {
                    "type": "string",
                    "enum": [
                      "today",
                      "week"
                    ],
                    "description": "Default \"today\"."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The tool ran. The body is that tool's result object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "The request body was not valid JSON, or an argument failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No Bearer token, or the token is unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key does not hold the required scope. The account holds no active paid entitlement.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No tool by that name.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Per-key rate limit exceeded. Retry after the window.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The tool handler failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-required-scope": "brief.read",
        "x-requires-entitlement": true
      }
    },
    "/api/v1/tools/gtm_score": {
      "post": {
        "operationId": "gtm_score",
        "summary": "Score a subject with the shared scoring substrate",
        "description": "Score a subject with the shared scoring substrate. `role` is one of: awareness, deal-risk, deal-risk-team, technical-risk, health, ecosystem-fit, efficiency. Returns a 0-100 value, a band, and the top drivers. Deterministic, no AI.\n\nRequires the `account.read` scope on the API key.\nRequires at least one active paid entitlement on the account.",
        "tags": [
          "Tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "role",
                  "signals"
                ],
                "properties": {
                  "role": {
                    "type": "string",
                    "description": "The weight profile: awareness | deal-risk | deal-risk-team | technical-risk | health | ecosystem-fit | efficiency."
                  },
                  "signals": {
                    "type": "array",
                    "description": "Signals, each { key, value (0..1), at? (ISO) }.",
                    "items": {
                      "type": "object",
                      "properties": {
                        "key": {
                          "type": "string"
                        },
                        "value": {
                          "type": "number"
                        },
                        "at": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The tool ran. The body is that tool's result object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "The request body was not valid JSON, or an argument failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No Bearer token, or the token is unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key does not hold the required scope. The account holds no active paid entitlement.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No tool by that name.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Per-key rate limit exceeded. Retry after the window.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The tool handler failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-required-scope": "account.read",
        "x-requires-entitlement": true
      }
    },
    "/api/v1/tools/gtm_enrich": {
      "post": {
        "operationId": "gtm_enrich",
        "summary": "Run the enrichment waterfall (Apollo, ZoomInfo, Cognism, Clay) for one contact over the configured providers, cheapest-first, MX-validating emails",
        "description": "Run the enrichment waterfall (Apollo, ZoomInfo, Cognism, Clay) for one contact over the configured providers, cheapest-first, MX-validating emails. Optionally persist the filled facts to a panel record.\n\nRequires the `prospect.write` scope on the API key.\nRequires at least one active paid entitlement on the account.",
        "tags": [
          "Tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "contact"
                ],
                "properties": {
                  "contact": {
                    "type": "object",
                    "description": "Known contact facts: fullName, firstName, lastName, domain, company, linkedin, known."
                  },
                  "wanted": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Fields to fill: email, phone, title, seniority, company, linkedin, employeeCount, industry."
                  },
                  "persist_entity": {
                    "type": "string",
                    "description": "Optional entity to write facts to (prospect, account, target_account)."
                  },
                  "persist_id": {
                    "type": "string",
                    "description": "Optional record id to write the facts onto."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The tool ran. The body is that tool's result object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "The request body was not valid JSON, or an argument failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No Bearer token, or the token is unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key does not hold the required scope. The account holds no active paid entitlement.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No tool by that name.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Per-key rate limit exceeded. Retry after the window.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The tool handler failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-required-scope": "prospect.write",
        "x-requires-entitlement": true
      }
    },
    "/api/v1/tools/gtm_build_tam": {
      "post": {
        "operationId": "gtm_build_tam",
        "summary": "Materialize a target account list",
        "description": "Materialize a target account list. Upserts each account as a target_account record tagged with the list name, ready for the enrichment waterfall and scoring.\n\nRequires the `prospect.write` scope on the API key.\nRequires at least one active paid entitlement on the account.",
        "tags": [
          "Tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "list_name",
                  "accounts"
                ],
                "properties": {
                  "list_name": {
                    "type": "string"
                  },
                  "accounts": {
                    "type": "array",
                    "items": {
                      "type": "object"
                    },
                    "description": "Each account: { domain, name, industry, employeeCount, ... }."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The tool ran. The body is that tool's result object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "The request body was not valid JSON, or an argument failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No Bearer token, or the token is unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key does not hold the required scope. The account holds no active paid entitlement.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No tool by that name.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Per-key rate limit exceeded. Retry after the window.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The tool handler failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-required-scope": "prospect.write",
        "x-requires-entitlement": true
      }
    },
    "/api/v1/tools/gtm_crm_write": {
      "post": {
        "operationId": "gtm_crm_write",
        "summary": "Write structured facts onto a record (prospect, account, target_account, opp, contact)",
        "description": "Write structured facts onto a record (prospect, account, target_account, opp, contact). Merges into the existing payload. Omit id to create a new record.\n\nRequires the `prospect.write` scope on the API key.\nRequires at least one active paid entitlement on the account.",
        "tags": [
          "Tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "entity",
                  "facts"
                ],
                "properties": {
                  "entity": {
                    "type": "string",
                    "description": "prospect | account | target_account | opp | contact."
                  },
                  "id": {
                    "type": "string",
                    "description": "Record id (omit to create)."
                  },
                  "facts": {
                    "type": "object",
                    "description": "Fields to merge onto the record."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The tool ran. The body is that tool's result object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "The request body was not valid JSON, or an argument failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No Bearer token, or the token is unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key does not hold the required scope. The account holds no active paid entitlement.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No tool by that name.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Per-key rate limit exceeded. Retry after the window.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The tool handler failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-required-scope": "prospect.write",
        "x-requires-entitlement": true
      }
    },
    "/api/v1/tools/gtm_signal_query": {
      "post": {
        "operationId": "gtm_signal_query",
        "summary": "Read the stored signals and any recorded scores for an account, so an agent can see the current state before acting.",
        "description": "Read the stored signals and any recorded scores for an account, so an agent can see the current state before acting.\n\nRequires the `account.read` scope on the API key.\nRequires at least one active paid entitlement on the account.",
        "tags": [
          "Tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "account_id"
                ],
                "properties": {
                  "account_id": {
                    "type": "string"
                  },
                  "limit": {
                    "type": "number",
                    "description": "Max signals to return (default 50)."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The tool ran. The body is that tool's result object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "The request body was not valid JSON, or an argument failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No Bearer token, or the token is unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key does not hold the required scope. The account holds no active paid entitlement.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No tool by that name.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Per-key rate limit exceeded. Retry after the window.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The tool handler failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-required-scope": "account.read",
        "x-requires-entitlement": true
      }
    },
    "/api/v1/tools/gtm_run_play": {
      "post": {
        "operationId": "gtm_run_play",
        "summary": "Run a composite play end to end for one contact: enrich (waterfall) → score (shared substrate) → draft a deterministic outreach",
        "description": "Run a composite play end to end for one contact: enrich (waterfall) → score (shared substrate) → draft a deterministic outreach. Chains gtm_enrich + gtm_score + a draft. Returns { enrichment, score, draft }. The draft is text for a human to review and send, never auto-sent; a missing fact becomes a marked placeholder, never fabricated.\n\nRequires the `prospect.write` scope on the API key.\nRequires at least one active paid entitlement on the account.",
        "tags": [
          "Tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "contact"
                ],
                "properties": {
                  "contact": {
                    "type": "object",
                    "description": "Known contact facts: fullName, firstName, lastName, domain, company, linkedin, known."
                  },
                  "wanted": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Fields to fill (default email, phone, title, ...)."
                  },
                  "role": {
                    "type": "string",
                    "description": "Scoring profile: awareness | deal-risk | health | ... (optional; omit to skip scoring)."
                  },
                  "signals": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "key": {
                          "type": "string"
                        },
                        "value": {
                          "type": "number"
                        },
                        "at": {
                          "type": "string"
                        }
                      }
                    },
                    "description": "Signals to score (0..1). Optional."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The tool ran. The body is that tool's result object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "The request body was not valid JSON, or an argument failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No Bearer token, or the token is unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key does not hold the required scope. The account holds no active paid entitlement.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No tool by that name.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Per-key rate limit exceeded. Retry after the window.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The tool handler failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-required-scope": "prospect.write",
        "x-requires-entitlement": true
      }
    },
    "/api/v1/tools/verify_session": {
      "post": {
        "operationId": "verify_session",
        "summary": "Verify the licensed Sales as Code session",
        "description": "Verify the licensed Sales as Code session. Returns the account, plan, and entitled plugins. Every skill calls this first and stops if it errors.\n\nRequires no scope beyond a valid, non-revoked key: the account is acting on its own data.\nCallable before the account has bought anything (onboarding and licensing).",
        "tags": [
          "Tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {}
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The tool ran. The body is that tool's result object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "The request body was not valid JSON, or an argument failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No Bearer token, or the token is unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No tool by that name.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Per-key rate limit exceeded. Retry after the window.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The tool handler failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-requires-entitlement": false
      }
    },
    "/api/v1/tools/check_entitlement": {
      "post": {
        "operationId": "check_entitlement",
        "summary": "Check whether this account is licensed for a named plugin",
        "description": "Check whether this account is licensed for a named plugin. Call after verify_session; stop and tell the user to connect their Sales as Code account if not entitled.\n\nRequires no scope beyond a valid, non-revoked key: the account is acting on its own data.\nCallable before the account has bought anything (onboarding and licensing).",
        "tags": [
          "Tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "plugin"
                ],
                "properties": {
                  "plugin": {
                    "type": "string",
                    "description": "Plugin slug, e.g. \"gtm-engine\"."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The tool ran. The body is that tool's result object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "The request body was not valid JSON, or an argument failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No Bearer token, or the token is unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No tool by that name.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Per-key rate limit exceeded. Retry after the window.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The tool handler failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-requires-entitlement": false
      }
    },
    "/api/v1/tools/start_run": {
      "post": {
        "operationId": "start_run",
        "summary": "Declare that a skill run has started, so the dashboard can show it live",
        "description": "Declare that a skill run has started, so the dashboard can show it live. Returns a run_ref (server-generated unless you supply one): pass it to run_heartbeat while working, to emit_telemetry as run_id when done, and to sync_brain as run_ref so brain syncs correlate to this run. Optional — a skill that only calls emit_telemetry at the end still records fine. A started run with no heartbeat for 30 minutes is flagged stale.\n\nRequires no scope beyond a valid, non-revoked key: the account is acting on its own data.\nRequires at least one active paid entitlement on the account.",
        "tags": [
          "Tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "plugin",
                  "skill"
                ],
                "properties": {
                  "plugin": {
                    "type": "string"
                  },
                  "skill": {
                    "type": "string"
                  },
                  "run_ref": {
                    "type": "string",
                    "description": "Optional client-supplied correlation id; generated when omitted. Use a fresh value per run."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The tool ran. The body is that tool's result object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "The request body was not valid JSON, or an argument failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No Bearer token, or the token is unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The account holds no active paid entitlement.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No tool by that name.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Per-key rate limit exceeded. Retry after the window.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The tool handler failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-requires-entitlement": true
      }
    },
    "/api/v1/tools/run_heartbeat": {
      "post": {
        "operationId": "run_heartbeat",
        "summary": "Signal that a started run is still working",
        "description": "Signal that a started run is still working. Send at most one every 60s (only needed for runs longer than a few minutes) — a running run silent for 30 minutes is flagged stale. Returns running:false when there is no matching running run (already finalized or swept), which is safe to ignore.\n\nRequires no scope beyond a valid, non-revoked key: the account is acting on its own data.\nRequires at least one active paid entitlement on the account.",
        "tags": [
          "Tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "run_ref"
                ],
                "properties": {
                  "run_ref": {
                    "type": "string",
                    "description": "The run_ref from start_run."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The tool ran. The body is that tool's result object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "The request body was not valid JSON, or an argument failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No Bearer token, or the token is unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The account holds no active paid entitlement.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No tool by that name.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Per-key rate limit exceeded. Retry after the window.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The tool handler failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-requires-entitlement": true
      }
    },
    "/api/v1/tools/emit_telemetry": {
      "post": {
        "operationId": "emit_telemetry",
        "summary": "Record a plugin run event (metadata only — counts, outcome, duration, optional error taxonomy)",
        "description": "Record a plugin run event (metadata only — counts, outcome, duration, optional error taxonomy). Call at the end of every skill so the dashboard can roll up what ran. When run_id matches a run declared via start_run, this settles that run (running → ok/error) instead of recording a second one.\n\nRequires no scope beyond a valid, non-revoked key: the account is acting on its own data.\nRequires at least one active paid entitlement on the account.",
        "tags": [
          "Tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "plugin",
                  "skill"
                ],
                "properties": {
                  "plugin": {
                    "type": "string"
                  },
                  "skill": {
                    "type": "string"
                  },
                  "run_id": {
                    "type": "string",
                    "description": "Run correlation id — pass the run_ref from start_run to settle the declared run."
                  },
                  "counts": {
                    "type": "object",
                    "description": "The skill's counts line as an object."
                  },
                  "outcome": {
                    "type": "string",
                    "description": "\"ok\" | \"setup\" | \"skipped\" | \"error\" | free-form."
                  },
                  "duration_ms": {
                    "type": "number"
                  },
                  "error_code": {
                    "type": "string",
                    "enum": [
                      "auth",
                      "entitlement",
                      "rate_limit",
                      "provider",
                      "skill_logic",
                      "unknown"
                    ],
                    "description": "Optional error category when the run failed (auth | entitlement | rate_limit | provider | skill_logic | unknown)."
                  },
                  "error_detail": {
                    "type": "string",
                    "description": "Optional human-readable error detail (max 2000 chars)."
                  },
                  "account_ref": {
                    "type": "string",
                    "description": "Optional account label this run worked (a domain or account name, e.g. \"acme.com\"). Metadata only — a free-text label, never CRM records or contact PII. Max 200 chars. Lets the rollup filter runs by account and flag when teammates work the same account. Pass it where the skill knows the account; omit it otherwise."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The tool ran. The body is that tool's result object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "The request body was not valid JSON, or an argument failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No Bearer token, or the token is unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The account holds no active paid entitlement.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No tool by that name.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Per-key rate limit exceeded. Retry after the window.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The tool handler failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-requires-entitlement": true
      }
    },
    "/api/v1/tools/sync_brain": {
      "post": {
        "operationId": "sync_brain",
        "summary": "Push brain state for a scope (signal-weights, icp-registry, decision-log, funnel-brain, review summaries, content calendar, ...) so the dashboard can roll it up",
        "description": "Push brain state for a scope (signal-weights, icp-registry, decision-log, funnel-brain, review summaries, content calendar, ...) so the dashboard can roll it up. Send metadata and brain state only — never raw third-party contact PII unless the user has explicitly opted in.\n\nRequires no scope beyond a valid, non-revoked key: the account is acting on its own data.\nRequires at least one active paid entitlement on the account.",
        "tags": [
          "Tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "scope",
                  "payload"
                ],
                "properties": {
                  "scope": {
                    "type": "string",
                    "description": "Brain scope, e.g. \"signal-weights\"."
                  },
                  "plugin": {
                    "type": "string",
                    "description": "Optional source plugin slug."
                  },
                  "payload": {
                    "type": "object",
                    "description": "The brain state for this scope."
                  },
                  "run_ref": {
                    "type": "string",
                    "description": "Optional run correlation id (the run_ref from start_run / the run_id you pass to emit_telemetry) so this sync is attributed to that exact run."
                  },
                  "account_ref": {
                    "type": "string",
                    "description": "Optional account label this brain state is about (a domain or account name). Metadata only — a free-text label, never CRM records or contact PII. Max 200 chars."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The tool ran. The body is that tool's result object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "The request body was not valid JSON, or an argument failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No Bearer token, or the token is unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The account holds no active paid entitlement.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No tool by that name.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Per-key rate limit exceeded. Retry after the window.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The tool handler failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-requires-entitlement": true
      }
    },
    "/api/v1/tools/pull_config": {
      "post": {
        "operationId": "pull_config",
        "summary": "Pull current account config and feature flags",
        "description": "Pull current account config and feature flags. Optional; call at setup or run start. Returns the plan and entitled plugins so a skill can adapt.\n\nRequires no scope beyond a valid, non-revoked key: the account is acting on its own data.\nCallable before the account has bought anything (onboarding and licensing).",
        "tags": [
          "Tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "plugin": {
                    "type": "string",
                    "description": "Optional plugin slug to scope the config."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The tool ran. The body is that tool's result object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "The request body was not valid JSON, or an argument failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No Bearer token, or the token is unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No tool by that name.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Per-key rate limit exceeded. Retry after the window.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The tool handler failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-requires-entitlement": false
      }
    },
    "/api/v1/tools/connect_integration": {
      "post": {
        "operationId": "connect_integration",
        "summary": "Write back an OAuth token a connector obtained for one of the content-engine channels (linkedin, linkedin_company, youtube, reddit, google_drive)",
        "description": "Write back an OAuth token a connector obtained for one of the content-engine channels (linkedin, linkedin_company, youtube, reddit, google_drive). Stores it (encrypted) in the control plane so server-side publish/ingest can run. Channel auto-publish then works without the first-party connector flag.\n\nRequires no scope beyond a valid, non-revoked key: the account is acting on its own data.\nRequires at least one active paid entitlement on the account.",
        "tags": [
          "Tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "provider",
                  "access_token"
                ],
                "properties": {
                  "provider": {
                    "type": "string",
                    "enum": [
                      "linkedin",
                      "linkedin_company",
                      "youtube",
                      "reddit",
                      "google_drive"
                    ],
                    "description": "Content-engine channel provider id."
                  },
                  "access_token": {
                    "type": "string",
                    "description": "OAuth access token."
                  },
                  "refresh_token": {
                    "type": "string",
                    "description": "OAuth refresh token, if the provider issues one."
                  },
                  "expires_at": {
                    "type": "number",
                    "description": "Token expiry as epoch milliseconds (preferred)."
                  },
                  "expires_in": {
                    "type": "number",
                    "description": "Token lifetime in seconds from now (used if expires_at absent)."
                  },
                  "scopes": {
                    "type": "string",
                    "description": "Space-joined granted scopes."
                  },
                  "account_ref": {
                    "type": "string",
                    "description": "Provider account ref (e.g. member/org URN, channel id)."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The tool ran. The body is that tool's result object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "The request body was not valid JSON, or an argument failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No Bearer token, or the token is unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The account holds no active paid entitlement.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No tool by that name.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Per-key rate limit exceeded. Retry after the window.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The tool handler failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-requires-entitlement": true
      }
    },
    "/api/v1/tools/studio_list_drafts": {
      "post": {
        "operationId": "studio_list_drafts",
        "summary": "List the content studio draft queue for this account, newest first",
        "description": "List the content studio draft queue for this account, newest first. Optional status filter (draft, needs_approval, approved, scheduled, published, failed). Use to review what the engine drafted before approving.\n\nRequires no scope beyond a valid, non-revoked key: the account is acting on its own data.\nRequires at least one active paid entitlement on the account.",
        "tags": [
          "Tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "description": "Optional status filter."
                  },
                  "limit": {
                    "type": "number",
                    "description": "Max rows (1–200, default 50)."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The tool ran. The body is that tool's result object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "The request body was not valid JSON, or an argument failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No Bearer token, or the token is unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The account holds no active paid entitlement.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No tool by that name.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Per-key rate limit exceeded. Retry after the window.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The tool handler failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-requires-entitlement": true
      }
    },
    "/api/v1/tools/studio_review_draft": {
      "post": {
        "operationId": "studio_review_draft",
        "summary": "Approve, schedule, or hold a content studio draft",
        "description": "Approve, schedule, or hold a content studio draft. Setting status to \"approved\" or \"scheduled\" hands the draft to the publisher (auto-publish on automated channels after the compliance gate). Cannot mark \"published\" — only the publisher does that. The account acts on its own drafts.\n\nRequires no scope beyond a valid, non-revoked key: the account is acting on its own data.\nRequires at least one active paid entitlement on the account.",
        "tags": [
          "Tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "id",
                  "status"
                ],
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "Draft id from studio_list_drafts."
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "approved",
                      "scheduled",
                      "needs_approval",
                      "draft",
                      "failed"
                    ],
                    "description": "New status."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The tool ran. The body is that tool's result object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "The request body was not valid JSON, or an argument failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No Bearer token, or the token is unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The account holds no active paid entitlement.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No tool by that name.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Per-key rate limit exceeded. Retry after the window.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The tool handler failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-requires-entitlement": true
      }
    },
    "/api/v1/tools/team_rollup": {
      "post": {
        "operationId": "team_rollup",
        "summary": "Team-wide run rollup for a team OWNER (leadercron): per-member runs/actions/rank, per-plugin totals, week-over-week, and outcome counts across the team, inside a trailing window (default 30 days)",
        "description": "Team-wide run rollup for a team OWNER (leadercron): per-member runs/actions/rank, per-plugin totals, week-over-week, and outcome counts across the team, inside a trailing window (default 30 days). Metadata only. Errors if the acting account does not own a team.\n\nRequires no scope beyond a valid, non-revoked key: the account is acting on its own data.\nRequires at least one active paid entitlement on the account.",
        "tags": [
          "Tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "period_days": {
                    "type": "number",
                    "description": "Trailing window in days (1–90, default 30)."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The tool ran. The body is that tool's result object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "The request body was not valid JSON, or an argument failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No Bearer token, or the token is unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The account holds no active paid entitlement.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No tool by that name.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Per-key rate limit exceeded. Retry after the window.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The tool handler failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-requires-entitlement": true
      }
    },
    "/api/v1/tools/team_member_summary": {
      "post": {
        "operationId": "team_member_summary",
        "summary": "One member's run summary for a team OWNER (leadercron 1:1 prep): per-plugin run counts and the most recent runs (plugin, skill, status, outcome counts, account label) inside the window",
        "description": "One member's run summary for a team OWNER (leadercron 1:1 prep): per-plugin run counts and the most recent runs (plugin, skill, status, outcome counts, account label) inside the window. Metadata only — no email bodies, no CRM records, no brain payloads. Errors unless the acting account owns a team the member belongs to.\n\nRequires no scope beyond a valid, non-revoked key: the account is acting on its own data.\nRequires at least one active paid entitlement on the account.",
        "tags": [
          "Tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "member_email"
                ],
                "properties": {
                  "member_email": {
                    "type": "string",
                    "description": "The member's account email (from team_rollup)."
                  },
                  "period_days": {
                    "type": "number",
                    "description": "Trailing window in days (1–90, default 30)."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The tool ran. The body is that tool's result object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "The request body was not valid JSON, or an argument failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No Bearer token, or the token is unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The account holds no active paid entitlement.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No tool by that name.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Per-key rate limit exceeded. Retry after the window.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The tool handler failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-requires-entitlement": true
      }
    },
    "/api/v1/tools/answer_about_account": {
      "post": {
        "operationId": "answer_about_account",
        "summary": "Answer a question about one account from what this organization has established, with the facts it rests on and who established each",
        "description": "Answer a question about one account from what this organization has established, with the facts it rests on and who established each. Returns an honest \"nothing recorded\" rather than a guess when the org knows nothing.\n\nRequires the `account.read` scope on the API key.\nRequires at least one active paid entitlement on the account.",
        "tags": [
          "Tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "accountId",
                  "question"
                ],
                "properties": {
                  "accountId": {
                    "type": "string"
                  },
                  "question": {
                    "type": "string",
                    "description": "What you want to know about this account."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The tool ran. The body is that tool's result object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "The request body was not valid JSON, or an argument failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No Bearer token, or the token is unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key does not hold the required scope. The account holds no active paid entitlement.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No tool by that name.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Per-key rate limit exceeded. Retry after the window.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The tool handler failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-required-scope": "account.read",
        "x-requires-entitlement": true
      }
    },
    "/api/v1/tools/answer_across_org": {
      "post": {
        "operationId": "answer_across_org",
        "summary": "Answer a question across every account the calling seat may see, using hybrid retrieval over the organization fact store",
        "description": "Answer a question across every account the calling seat may see, using hybrid retrieval over the organization fact store. This is the question a table export cannot answer.\n\nRequires the `account.read` scope on the API key.\nRequires at least one active paid entitlement on the account.",
        "tags": [
          "Tools"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "question"
                ],
                "properties": {
                  "question": {
                    "type": "string",
                    "description": "What you want to know across the book."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The tool ran. The body is that tool's result object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "The request body was not valid JSON, or an argument failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No Bearer token, or the token is unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key does not hold the required scope. The account holds no active paid entitlement.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No tool by that name.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Per-key rate limit exceeded. Retry after the window.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The tool handler failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-required-scope": "account.read",
        "x-requires-entitlement": true
      }
    },
    "/api/v1/mcp": {
      "get": {
        "operationId": "mcp_describe",
        "summary": "Describe the MCP endpoint.",
        "description": "Server identity and the list of supported JSON-RPC methods. No authentication.",
        "tags": [
          "MCP"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Endpoint description.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "mcp_rpc",
        "summary": "Call an MCP JSON-RPC method.",
        "description": "Supports `initialize`, `tools/list` and `tools/call`. `tools/call`\ndispatches to the same handlers the REST operations above use, so\nscope and entitlement rules are identical.",
        "tags": [
          "MCP"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "jsonrpc",
                  "method"
                ],
                "properties": {
                  "jsonrpc": {
                    "type": "string",
                    "const": "2.0"
                  },
                  "id": {
                    "type": [
                      "string",
                      "number",
                      "null"
                    ]
                  },
                  "method": {
                    "type": "string",
                    "enum": [
                      "initialize",
                      "tools/list",
                      "tools/call"
                    ]
                  },
                  "params": {
                    "type": "object"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A JSON-RPC response. Tool-level failures arrive here as an `error` member, not as an HTTP status.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "No Bearer token, or the token is unknown or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/oauth/authorize": {
      "get": {
        "operationId": "oauth_authorize",
        "summary": "Start the authorization code flow.",
        "description": "Validates the request, requires a logged-in session, and renders a consent screen. Returns HTML, not JSON.",
        "tags": [
          "OAuth"
        ],
        "security": [],
        "parameters": [
          {
            "name": "client_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "redirect_uri",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "response_type",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "const": "code"
            }
          },
          {
            "name": "code_challenge",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "code_challenge_method",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "const": "S256"
            }
          },
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Space-separated scopes."
            }
          },
          {
            "name": "state",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Consent screen (HTML)."
          },
          "302": {
            "description": "Redirect to /login, or back to redirect_uri with a code or an error."
          },
          "400": {
            "description": "Invalid authorization request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/oauth/token": {
      "post": {
        "operationId": "oauth_token",
        "summary": "Exchange an authorization code for an access token.",
        "description": "PKCE authorization_code grant. The access token is a managed API\nkey, so it revokes, audits and rate-limits like a hand-issued one.\nNo refresh tokens: the token does not expire and is revoked from\nthe API keys page.",
        "tags": [
          "OAuth"
        ],
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "grant_type",
                  "code",
                  "redirect_uri",
                  "client_id",
                  "code_verifier"
                ],
                "properties": {
                  "grant_type": {
                    "type": "string",
                    "const": "authorization_code"
                  },
                  "code": {
                    "type": "string"
                  },
                  "redirect_uri": {
                    "type": "string",
                    "format": "uri"
                  },
                  "client_id": {
                    "type": "string"
                  },
                  "code_verifier": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Access token.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "access_token": {
                      "type": "string"
                    },
                    "token_type": {
                      "type": "string",
                      "const": "Bearer"
                    },
                    "scope": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid grant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/versions/{product}": {
      "get": {
        "operationId": "product_version",
        "summary": "Read a product's hosted version manifest.",
        "description": "Public and cacheable. What each product's update checker reads.",
        "tags": [
          "Public"
        ],
        "security": [],
        "parameters": [
          {
            "name": "product",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Product slug, e.g. `salescron`."
          }
        ],
        "responses": {
          "200": {
            "description": "Version manifest.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "404": {
            "description": "No manifest for that product.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "An API key issued at https://salesascode.com/settings/api-keys, sent as\n`Authorization: Bearer <key>`. Keys carry scopes; a tool that\ndeclares one rejects a key without it with 403 `scope_required`.\n\nScopes: `capture.write`, `prospect.write`, `plan.write`, `meeting.write`, `account.read`, `brief.read`, `usage.write`, `meddpicc.write`."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string",
                "description": "Stable machine-readable code. Match on this, not on the message.",
                "examples": [
                  "missing_bearer",
                  "invalid_key",
                  "scope_required",
                  "unknown_tool"
                ]
              },
              "message": {
                "type": "string",
                "description": "Human-readable explanation."
              },
              "hint": {
                "type": "string",
                "description": "What to do about it, when there is a useful answer."
              }
            }
          }
        }
      }
    }
  },
  "security": [
    {
      "bearerAuth": []
    }
  ]
}