{
  "openapi": "3.1.0",
  "info": {
    "title": "OpenRevenue API",
    "version": "1.0.0",
    "description": "Account and project analytics REST API. Authenticate with an account API key (Bearer openrevenue_…). Keys may be read-only or read+write. Hosted MCP lives at https://api.openrevenue.com/mcp.",
    "contact": {
      "name": "OpenRevenue",
      "url": "https://www.openrevenue.com"
    },
    "license": {
      "name": "Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://api.openrevenue.com",
      "description": "Production"
    }
  ],
  "tags": [
    { "name": "Account", "description": "List and manage projects" },
    { "name": "Analytics", "description": "Read project analytics" },
    { "name": "Visitors", "description": "Visitor profiles" },
    { "name": "Performance", "description": "Core Web Vitals" },
    { "name": "Funnels", "description": "Funnel definitions and reports" }
  ],
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "openrevenue_…",
        "description": "Account API key from Account → API. Use a read-only key for analytics; write is required to create or delete projects."
      }
    },
    "parameters": {
      "Domain": {
        "name": "domain",
        "in": "path",
        "required": true,
        "schema": { "type": "string", "example": "example.com" },
        "description": "Project domain"
      },
      "Period": {
        "name": "period",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": ["24h", "7d", "30d", "90d", "12m", "this_month", "this_week"],
          "default": "30d"
        }
      },
      "Limit": {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 10 }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": { "type": "string" }
        },
        "required": ["error"]
      },
      "Project": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "name": { "type": "string" },
          "domain": { "type": "string" },
          "timeZone": { "type": "string" },
          "createdAt": { "type": "string", "format": "date-time" },
          "accessRole": { "type": "string", "enum": ["owner", "admin", "member"] },
          "icon": { "type": ["string", "null"] }
        }
      }
    }
  },
  "security": [{ "BearerAuth": [] }],
  "paths": {
    "/api/v1/projects": {
      "get": {
        "tags": ["Account"],
        "summary": "List projects",
        "operationId": "listProjects",
        "responses": {
          "200": {
            "description": "Projects the key can access",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "projects": {
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/Project" }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          }
        }
      },
      "post": {
        "tags": ["Account"],
        "summary": "Create project",
        "operationId": "createProject",
        "description": "Requires a write-scoped API key.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["name", "domain"],
                "properties": {
                  "name": { "type": "string", "maxLength": 80 },
                  "domain": { "type": "string", "example": "example.com" },
                  "timeZone": { "type": "string", "example": "America/New_York" }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Project" } }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          },
          "403": {
            "description": "API key is read-only",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          }
        }
      }
    },
    "/api/v1/projects/{domain}": {
      "get": {
        "tags": ["Account"],
        "summary": "Get project",
        "operationId": "getProject",
        "description": "Returns project details including timezone, public stats flag, brand color, and install status.",
        "parameters": [{ "$ref": "#/components/parameters/Domain" }],
        "responses": {
          "200": {
            "description": "Project details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": { "type": "string" },
                    "name": { "type": "string" },
                    "domain": { "type": "string" },
                    "timeZone": { "type": "string" },
                    "publicStatsEnabled": { "type": "boolean" },
                    "brandColor": { "type": ["string", "null"] },
                    "icon": { "type": ["string", "null"] },
                    "installationSeenAt": { "type": ["string", "null"], "format": "date-time" },
                    "createdAt": { "type": "string", "format": "date-time" },
                    "isOwner": { "type": "boolean" }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          }
        }
      },
      "patch": {
        "tags": ["Account"],
        "summary": "Update project",
        "operationId": "updateProject",
        "description": "Requires a write-scoped API key. Only the project owner can update name, timeZone, or publicStatsEnabled.",
        "parameters": [{ "$ref": "#/components/parameters/Domain" }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": { "type": "string", "maxLength": 80 },
                  "timeZone": { "type": "string", "example": "America/New_York" },
                  "publicStatsEnabled": { "type": "boolean" }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated project",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": { "type": "string" },
                    "name": { "type": "string" },
                    "domain": { "type": "string" },
                    "timeZone": { "type": "string" },
                    "publicStatsEnabled": { "type": "boolean" },
                    "installationSeenAt": { "type": ["string", "null"], "format": "date-time" }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          },
          "403": {
            "description": "API key is read-only",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          },
          "404": {
            "description": "Not found (or not owner)",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          },
          "429": {
            "description": "Too many requests",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          }
        }
      },
      "delete": {
        "tags": ["Account"],
        "summary": "Delete project",
        "operationId": "deleteProject",
        "description": "Requires a write-scoped API key and {\"confirm\":true} in the JSON body.",
        "parameters": [{ "$ref": "#/components/parameters/Domain" }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["confirm"],
                "properties": {
                  "confirm": { "type": "boolean", "const": true }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Deleted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": { "ok": { "type": "boolean" } }
                }
              }
            }
          },
          "400": {
            "description": "Missing confirm:true",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          },
          "403": {
            "description": "API key is read-only",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          }
        }
      }
    },
    "/api/v1/projects/{domain}/stats": {
      "get": {
        "tags": ["Analytics"],
        "summary": "Headline stats",
        "operationId": "getProjectStats",
        "parameters": [
          { "$ref": "#/components/parameters/Domain" },
          { "$ref": "#/components/parameters/Period" }
        ],
        "responses": {
          "200": { "description": "Aggregate stats for the period" },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          }
        }
      }
    },
    "/api/v1/projects/{domain}/timeseries": {
      "get": {
        "tags": ["Analytics"],
        "summary": "Timeseries",
        "operationId": "getProjectTimeseries",
        "parameters": [
          { "$ref": "#/components/parameters/Domain" },
          { "$ref": "#/components/parameters/Period" }
        ],
        "responses": {
          "200": { "description": "Time-bucketed metrics" },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          }
        }
      }
    },
    "/api/v1/projects/{domain}/pages": {
      "get": {
        "tags": ["Analytics"],
        "summary": "Top pages",
        "operationId": "getProjectPages",
        "parameters": [
          { "$ref": "#/components/parameters/Domain" },
          { "$ref": "#/components/parameters/Period" },
          { "$ref": "#/components/parameters/Limit" }
        ],
        "responses": {
          "200": { "description": "Top pages" },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          }
        }
      }
    },
    "/api/v1/projects/{domain}/referrers": {
      "get": {
        "tags": ["Analytics"],
        "summary": "Top referrers",
        "operationId": "getProjectReferrers",
        "parameters": [
          { "$ref": "#/components/parameters/Domain" },
          { "$ref": "#/components/parameters/Period" },
          { "$ref": "#/components/parameters/Limit" }
        ],
        "responses": {
          "200": { "description": "Top referrers" },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          }
        }
      }
    },
    "/api/v1/projects/{domain}/countries": {
      "get": {
        "tags": ["Analytics"],
        "summary": "Visitors by country",
        "operationId": "getProjectCountries",
        "parameters": [
          { "$ref": "#/components/parameters/Domain" },
          { "$ref": "#/components/parameters/Period" },
          { "$ref": "#/components/parameters/Limit" }
        ],
        "responses": {
          "200": { "description": "Country breakdown" },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          }
        }
      }
    },
    "/api/v1/projects/{domain}/cities": {
      "get": {
        "tags": ["Analytics"],
        "summary": "Visitors by city",
        "operationId": "getProjectCities",
        "parameters": [
          { "$ref": "#/components/parameters/Domain" },
          { "$ref": "#/components/parameters/Period" },
          { "$ref": "#/components/parameters/Limit" }
        ],
        "responses": {
          "200": { "description": "City breakdown" },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          }
        }
      }
    },
    "/api/v1/projects/{domain}/devices": {
      "get": {
        "tags": ["Analytics"],
        "summary": "Device breakdown",
        "operationId": "getProjectDevices",
        "parameters": [
          { "$ref": "#/components/parameters/Domain" },
          { "$ref": "#/components/parameters/Period" }
        ],
        "responses": {
          "200": { "description": "Devices / browsers / OS" },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          }
        }
      }
    },
    "/api/v1/projects/{domain}/browsers": {
      "get": {
        "tags": ["Analytics"],
        "summary": "Browsers",
        "operationId": "getProjectBrowsers",
        "parameters": [
          { "$ref": "#/components/parameters/Domain" },
          { "$ref": "#/components/parameters/Period" },
          { "$ref": "#/components/parameters/Limit" }
        ],
        "responses": {
          "200": { "description": "Browser breakdown" },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          }
        }
      }
    },
    "/api/v1/projects/{domain}/os": {
      "get": {
        "tags": ["Analytics"],
        "summary": "Operating systems",
        "operationId": "getProjectOs",
        "parameters": [
          { "$ref": "#/components/parameters/Domain" },
          { "$ref": "#/components/parameters/Period" },
          { "$ref": "#/components/parameters/Limit" }
        ],
        "responses": {
          "200": { "description": "OS breakdown" },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          }
        }
      }
    },
    "/api/v1/projects/{domain}/events": {
      "get": {
        "tags": ["Analytics"],
        "summary": "Custom events",
        "operationId": "getProjectEvents",
        "description": "Custom event names ranked by count. Works with an API key (ClickHouse-backed).",
        "parameters": [
          { "$ref": "#/components/parameters/Domain" },
          { "$ref": "#/components/parameters/Period" },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 20 }
          }
        ],
        "responses": {
          "200": { "description": "Custom events ranked by count" },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          }
        }
      }
    },
    "/api/v1/projects/{domain}/goals": {
      "get": {
        "tags": ["Analytics"],
        "summary": "Goals with stats",
        "operationId": "getProjectGoals",
        "description": "Prefer a session Bearer token. API keys may receive an empty goals list because the underlying action is session-only.",
        "parameters": [
          { "$ref": "#/components/parameters/Domain" },
          {
            "name": "period",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": ["today", "7d", "30d", "6m", "12m"],
              "default": "30d"
            }
          }
        ],
        "responses": {
          "200": { "description": "Goals with current stats for the period" },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          }
        }
      }
    },
    "/api/v1/projects/{domain}/bots": {
      "get": {
        "tags": ["Analytics"],
        "summary": "Bot traffic",
        "operationId": "getProjectBots",
        "description": "Prefer a session Bearer token. API keys may receive empty bot traffic because the underlying action is session-only.",
        "parameters": [
          { "$ref": "#/components/parameters/Domain" },
          {
            "name": "period",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": ["today", "7d", "30d", "6m", "12m"],
              "default": "7d"
            }
          },
          {
            "name": "filter",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": ["all", "ai_answer", "indexing", "training", "other"],
              "default": "all"
            }
          }
        ],
        "responses": {
          "200": { "description": "Bot traffic totals, series, and top bots/pages" },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          }
        }
      }
    },
    "/api/v1/projects/{domain}/install/verify": {
      "post": {
        "tags": ["Account"],
        "summary": "Verify tracker install",
        "operationId": "verifyProjectInstall",
        "description": "Requires a write-scoped API key or session. Checks whether the project has received tracker events.",
        "parameters": [{ "$ref": "#/components/parameters/Domain" }],
        "responses": {
          "200": {
            "description": "Install check result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "verified": { "type": "boolean" },
                    "installationSeenAt": { "type": ["string", "null"], "format": "date-time" }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          },
          "403": {
            "description": "API key is read-only",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          },
          "429": {
            "description": "Too many requests",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          }
        }
      }
    },
    "/api/v1/projects/{domain}/export": {
      "get": {
        "tags": ["Analytics"],
        "summary": "Export CSV",
        "operationId": "exportProjectCsv",
        "description": "Downloads analytics as text/csv (overview, pages, referrers, countries, browsers, OS). Works with an API key.",
        "parameters": [
          { "$ref": "#/components/parameters/Domain" },
          { "$ref": "#/components/parameters/Period" },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": { "type": "integer", "minimum": 1, "maximum": 500, "default": 100 }
          }
        ],
        "responses": {
          "200": {
            "description": "CSV download",
            "content": {
              "text/csv": {
                "schema": { "type": "string", "format": "binary" }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          },
          "429": {
            "description": "Too many requests",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          }
        }
      }
    },
    "/api/v1/projects/{domain}/visitors": {
      "get": {
        "tags": ["Visitors"],
        "summary": "List visitors",
        "operationId": "listVisitors",
        "parameters": [
          { "$ref": "#/components/parameters/Domain" },
          { "$ref": "#/components/parameters/Period" },
          { "$ref": "#/components/parameters/Limit" }
        ],
        "responses": {
          "200": { "description": "Recent visitors" },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          }
        }
      }
    },
    "/api/v1/projects/{domain}/visitors/{visitorId}": {
      "get": {
        "tags": ["Visitors"],
        "summary": "Visitor detail",
        "operationId": "getVisitor",
        "parameters": [
          { "$ref": "#/components/parameters/Domain" },
          {
            "name": "visitorId",
            "in": "path",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": { "description": "Visitor profile" },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          }
        }
      }
    },
    "/api/v1/projects/{domain}/performance": {
      "get": {
        "tags": ["Performance"],
        "summary": "Core Web Vitals",
        "operationId": "getPerformance",
        "parameters": [
          { "$ref": "#/components/parameters/Domain" },
          { "$ref": "#/components/parameters/Period" }
        ],
        "responses": {
          "200": { "description": "Performance averages" },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          }
        }
      }
    },
    "/api/v1/projects/{domain}/funnels": {
      "get": {
        "tags": ["Funnels"],
        "summary": "List funnels",
        "operationId": "listFunnels",
        "parameters": [{ "$ref": "#/components/parameters/Domain" }],
        "responses": {
          "200": { "description": "Funnel definitions" },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          }
        }
      }
    },
    "/mcp": {
      "post": {
        "tags": ["Account"],
        "summary": "Hosted MCP (Model Context Protocol)",
        "operationId": "mcp",
        "description": "Streamable HTTP MCP endpoint. Authenticate with the same Bearer API key, or OAuth. See https://www.openrevenue.com/docs/api/mcp.",
        "responses": {
          "200": { "description": "MCP JSON-RPC response" },
          "401": {
            "description": "Unauthorized — WWW-Authenticate includes resource_metadata"
          }
        }
      }
    }
  }
}
