{
  "openapi": "3.1.0",
  "info": {
    "title": "RankRush API",
    "version": "0.1.0",
    "description": "Programmatic access to RankRush AI-visibility, audit, keyword, blog, and Buzz capabilities. All ops are POST to a Supabase edge function under /functions/v1. Authenticate with an `rr_live_*` API key as a Bearer token (Settings \u2192 API Keys), plus the project anon key as the `apikey` header (the client transport sets this). Enforcement (tiers, limits) is 100% server-side; clients are thin wrappers.\n\n> **Integration status:** the MCP server (`@rankrush.ai/mcp`) and the CLI (`@rankrush.ai/cli`) are the live integration paths today. Direct REST at the base URL above is rolling out - this document is the machine-readable contract those clients are generated from.",
    "license": {
      "name": "MIT",
      "identifier": "MIT"
    }
  },
  "servers": [
    {
      "url": "https://api.rankrush.ai/v1",
      "description": "RankRush REST API"
    }
  ],
  "security": [
    {
      "RankRushApiKey": [],
      "SupabaseAnonKey": []
    }
  ],
  "tags": [
    {
      "name": "visibility",
      "description": "AI visibility + keywords"
    },
    {
      "name": "audit",
      "description": "Web audit + scan queue"
    },
    {
      "name": "blog",
      "description": "Blog content engine (Publish module)"
    },
    {
      "name": "buzz",
      "description": "Reddit/community engagement (Buzz module)"
    },
    {
      "name": "profiles",
      "description": "Business profiles"
    },
    {
      "name": "admin",
      "description": "Admin-role-gated operations"
    },
    {
      "name": "jwt-only",
      "description": "Not yet API-key reachable (jwt-only in the backend)"
    }
  ],
  "paths": {
    "/check-ai-visibility": {
      "post": {
        "operationId": "checkAiVisibility",
        "summary": "Run an AI-visibility analysis for a set of keywords",
        "tags": [
          "visibility"
        ],
        "x-rr-auth-level": "api-key",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CheckAiVisibilityRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Analysis result (fresh or from cache)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckAiVisibilityResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/generate-visibility-keywords": {
      "post": {
        "operationId": "generateVisibilityKeywords",
        "summary": "Generate/collect visibility keywords for a profile (growth + GSC)",
        "tags": [
          "visibility"
        ],
        "x-rr-auth-level": "api-key",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProfileIdCamelRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Keyword set with source breakdown",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenerateVisibilityKeywordsResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "description": "Per-profile or per-tier keyword cap reached",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CapError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/audit-enqueue": {
      "post": {
        "operationId": "auditEnqueue",
        "summary": "Enqueue a web audit run (bulk or single-node)",
        "tags": [
          "audit"
        ],
        "x-rr-auth-level": "api-key",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AuditEnqueueRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Audit run queued",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuditEnqueueResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/enqueue-scan": {
      "post": {
        "operationId": "enqueueScan",
        "summary": "Enqueue a scan (ai_visibility | web_audit | node_check)",
        "tags": [
          "audit"
        ],
        "x-rr-auth-level": "api-key",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EnqueueScanRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Scan queued",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnqueueScanResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/generate-blog-topics": {
      "post": {
        "operationId": "generateBlogTopics",
        "summary": "Enqueue blog-topic generation for a profile",
        "tags": [
          "blog"
        ],
        "x-rr-auth-level": "api-key",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GenerateBlogTopicsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Topic-generation job queued",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobQueuedResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/generate-blog-post": {
      "post": {
        "operationId": "generateBlogPost",
        "summary": "Atomically claim a topic for blog-post generation",
        "description": "Returns HTTP 200 with `{ok:false, code}` for expected business failures (topic_wrong_status, connection_missing, tier_too_low, monthly_cap_reached, topic_already_claimed).\n",
        "tags": [
          "blog"
        ],
        "x-rr-auth-level": "api-key",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GenerateBlogPostRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Claim result (ok:true) or expected business failure (ok:false)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenerateBlogPostResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/generate-content-strategy": {
      "post": {
        "operationId": "generateContentStrategy",
        "summary": "Generate a content strategy for a profile",
        "tags": [
          "blog"
        ],
        "x-rr-auth-level": "api-key",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProfileIdCamelRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Strategy text",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenerateContentStrategyResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/save-cms-connection": {
      "post": {
        "operationId": "saveCmsConnection",
        "summary": "Save + verify a WordPress CMS connection",
        "description": "Returns HTTP 200 with `{ok:false, code:\"connection_failed\"}` when the WordPress credential probe fails (nothing persisted).\n",
        "tags": [
          "blog"
        ],
        "x-rr-auth-level": "api-key",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SaveCmsConnectionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Verified + saved (ok:true) or connection failure (ok:false)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SaveCmsConnectionResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/buzz-brand-research": {
      "post": {
        "operationId": "buzzBrandResearch",
        "summary": "Run Buzz brand research (async by default, sync with wait:true)",
        "tags": [
          "buzz"
        ],
        "x-rr-auth-level": "api-key",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BuzzWaitRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Started (async) or full research result (wait:true)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BuzzBrandResearchResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/buzz-generate-drafts": {
      "post": {
        "operationId": "buzzGenerateDrafts",
        "summary": "Generate Buzz reply/post drafts (bulk or single engagement)",
        "tags": [
          "buzz"
        ],
        "x-rr-auth-level": "api-key",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BuzzGenerateDraftsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Draft(s) created (bulk counts or single draft)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BuzzGenerateDraftsResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/buzz-opportunity-search": {
      "post": {
        "operationId": "buzzOpportunitySearch",
        "summary": "Search Buzz engagement opportunities (async default, sync wait:true)",
        "tags": [
          "buzz"
        ],
        "x-rr-auth-level": "api-key",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BuzzWaitRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Started (async) or opportunity counts (wait:true)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BuzzOpportunitySearchResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/buzz-visibility-score": {
      "post": {
        "operationId": "buzzVisibilityScore",
        "summary": "Compute the Buzz visibility score for a profile",
        "tags": [
          "buzz"
        ],
        "x-rr-auth-level": "api-key",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProfileIdSnakeRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Buzz visibility score + engagement metrics",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BuzzVisibilityScoreResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/profiles-list": {
      "post": {
        "operationId": "profilesList",
        "summary": "List the account's business profiles (or fetch one by id)",
        "tags": [
          "profiles"
        ],
        "x-rr-auth-level": "api-key",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProfilesListRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Array of profiles (empty if none). When `id` is supplied, the array holds just that profile, or is empty if it isn't the caller's.\n",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Profile"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/keywords-list": {
      "post": {
        "operationId": "keywordsList",
        "summary": "List a profile's tracked AEO keywords",
        "tags": [
          "visibility"
        ],
        "x-rr-auth-level": "api-key",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KeywordsListRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The profile's tracked keywords (empty list if none)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KeywordsListResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/profile-update": {
      "post": {
        "operationId": "profileUpdate",
        "summary": "Update a profile's website URL and/or industry",
        "tags": [
          "profiles"
        ],
        "x-rr-auth-level": "api-key",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProfileUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated profile",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Profile"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/buzz-engagements-list": {
      "post": {
        "operationId": "buzzEngagementsList",
        "summary": "List Buzz (Reddit) engagements for a profile or the whole account",
        "tags": [
          "buzz"
        ],
        "x-rr-auth-level": "api-key",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BuzzEngagementsListRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Matching engagements (with optional per-subreddit totals)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BuzzEngagementsListResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/buzz-draft-approve": {
      "post": {
        "operationId": "buzzDraftApprove",
        "summary": "Approve (or schedule) a Buzz draft post",
        "tags": [
          "buzz"
        ],
        "x-rr-auth-level": "api-key",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BuzzDraftApproveRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated engagement",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BuzzEngagement"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "Draft not approvable \u2014 body carries `reason: invalid_status` (only draft/approved/scheduled rows may be approved or re-scheduled; posted/dismissed/new rows are rejected) or `reason: empty_draft` (no draft_content to publish).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/buzz-research-list": {
      "post": {
        "operationId": "buzzResearchList",
        "summary": "List a profile's high-relevance Buzz research mentions",
        "tags": [
          "buzz"
        ],
        "x-rr-auth-level": "api-key",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BuzzResearchListRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Brand mentions (reactive research rows; drafts and opportunity rows are excluded) at or above minRelevance, best-first. Unscored (null relevance) mentions are always included.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BuzzResearchListResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/buzz-profile-get": {
      "post": {
        "operationId": "buzzProfileGet",
        "summary": "Get a profile's Buzz research status",
        "tags": [
          "buzz"
        ],
        "x-rr-auth-level": "api-key",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProfileIdCamelRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The profile's Buzz research status (nulls if not set up)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BuzzProfileGetResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/audit-run-get": {
      "post": {
        "operationId": "auditRunGet",
        "summary": "Fetch an audit run (with optional per-node progress summary)",
        "tags": [
          "audit"
        ],
        "x-rr-auth-level": "api-key",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AuditRunGetRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The audit run, plus node summary when includeNodes is true",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuditRunGetResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/blog-topics-list": {
      "post": {
        "operationId": "blogTopicsList",
        "summary": "List a profile's planned blog topics",
        "tags": [
          "blog"
        ],
        "x-rr-auth-level": "api-key",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BlogTopicsListRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The profile's blog topics (empty list if none)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BlogTopicsListResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/nodes-list": {
      "post": {
        "operationId": "nodesList",
        "summary": "List a profile's node-progress rows (optionally filtered by status)",
        "tags": [
          "audit"
        ],
        "x-rr-auth-level": "api-key",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NodesListRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The profile's node-progress rows (empty list if none)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NodesListResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/node-complete": {
      "post": {
        "operationId": "nodeComplete",
        "summary": "Mark a node complete (manual lifecycle override)",
        "tags": [
          "audit"
        ],
        "x-rr-auth-level": "api-key",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NodeCompleteRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated node, with its prior status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NodeCompleteResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "RankRushApiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "An `rr_live_*` API key sent as a Bearer token."
      },
      "SupabaseAnonKey": {
        "type": "apiKey",
        "in": "header",
        "name": "apikey",
        "description": "The project anon/publishable key (set by the client transport)."
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Missing or invalid credentials",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Forbidden": {
        "description": "Profile ownership or admin-role check failed",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "Referenced resource not found",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "ValidationError": {
        "description": "Invalid request body",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ValidationErrorBody"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Monthly tier limit or daily cap exceeded",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/RateLimitError"
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "const": false
          },
          "error": {
            "type": "string"
          },
          "code": {
            "type": "string"
          }
        },
        "required": [
          "error"
        ]
      },
      "ValidationErrorBody": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "const": false
          },
          "error": {
            "type": "string",
            "example": "Invalid input"
          },
          "details": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "required": [
          "error"
        ]
      },
      "RateLimitError": {
        "type": "object",
        "description": "`code` is `limit_exceeded` (monthly tier limit) or `daily_cap_exceeded` / `daily_llm_gen_cap_exceeded` (daily breakers).\n",
        "properties": {
          "success": {
            "type": "boolean",
            "const": false
          },
          "error": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "tier": {
            "type": "string"
          },
          "upgrade_to": {
            "type": "string"
          },
          "limit": {
            "type": "integer"
          },
          "used": {
            "type": "integer"
          },
          "cap": {
            "type": "integer"
          }
        },
        "required": [
          "error",
          "code"
        ]
      },
      "CapError": {
        "type": "object",
        "description": "Per-profile (profile_keyword_limit) or per-tier (keyword_limit_exceeded) cap.",
        "properties": {
          "success": {
            "type": "boolean",
            "const": false
          },
          "code": {
            "type": "string"
          },
          "tier": {
            "type": "string"
          },
          "upgrade_to": {
            "type": "string"
          },
          "limit": {
            "type": "integer"
          },
          "used": {
            "type": "integer"
          }
        },
        "required": [
          "code"
        ]
      },
      "ProfileIdCamelRequest": {
        "type": "object",
        "properties": {
          "profileId": {
            "type": "string"
          }
        },
        "required": [
          "profileId"
        ]
      },
      "ProfileIdSnakeRequest": {
        "type": "object",
        "properties": {
          "profile_id": {
            "type": "string"
          }
        },
        "required": [
          "profile_id"
        ]
      },
      "BuzzWaitRequest": {
        "type": "object",
        "properties": {
          "profile_id": {
            "type": "string"
          },
          "wait": {
            "type": "boolean",
            "default": false,
            "description": "true runs inline and returns the full result; default runs in background."
          }
        },
        "required": [
          "profile_id"
        ]
      },
      "OkResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "const": true
          }
        },
        "required": [
          "success"
        ]
      },
      "Profile": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "business_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "website_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "industry": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "local_service",
              "b2b_saas",
              "ecommerce",
              null
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ProfilesListRequest": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Fetch just this profile (must belong to the caller). Omit to list all."
          }
        }
      },
      "ProfileUpdateRequest": {
        "type": "object",
        "description": "At least one of website_url or industry must be provided.",
        "properties": {
          "profileId": {
            "type": "string",
            "format": "uuid"
          },
          "website_url": {
            "type": "string",
            "minLength": 1
          },
          "industry": {
            "type": "string",
            "enum": [
              "local_service",
              "b2b_saas",
              "ecommerce"
            ]
          }
        },
        "required": [
          "profileId"
        ]
      },
      "KeywordsListRequest": {
        "type": "object",
        "properties": {
          "profileId": {
            "type": "string",
            "format": "uuid"
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 500,
            "default": 200
          }
        },
        "required": [
          "profileId"
        ]
      },
      "KeywordsListResponse": {
        "type": "object",
        "properties": {
          "profile_id": {
            "type": "string",
            "format": "uuid"
          },
          "keywords": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "count": {
            "type": "integer"
          }
        },
        "required": [
          "profile_id",
          "keywords",
          "count"
        ]
      },
      "CheckAiVisibilityRequest": {
        "type": "object",
        "properties": {
          "keywords": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 500
            },
            "minItems": 1,
            "maxItems": 200
          },
          "businessName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "businessUrl": {
            "type": "string",
            "format": "uri"
          },
          "profileId": {
            "type": "string",
            "format": "uuid"
          },
          "force_refresh": {
            "type": "boolean",
            "default": false
          },
          "llm": {
            "type": "string",
            "enum": [
              "chatgpt",
              "claude",
              "perplexity",
              "gemini"
            ],
            "description": "Single-LLM fan-out mode (skips rate-limit/cache/write) when present."
          },
          "run_id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "keywords",
          "businessName"
        ]
      },
      "CheckAiVisibilityResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "fromCache": {
            "type": "boolean"
          },
          "runId": {
            "type": "string"
          },
          "summary": {
            "type": "string"
          },
          "score": {
            "type": "number",
            "minimum": 0,
            "maximum": 100
          },
          "analyzedAt": {
            "type": "string",
            "format": "date-time"
          },
          "written": {
            "type": "integer"
          },
          "attempted": {
            "type": "integer"
          },
          "dropped": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "keyword": {
                  "type": "string"
                },
                "llm": {
                  "type": "string"
                },
                "reason": {
                  "type": "string"
                }
              }
            }
          }
        },
        "required": [
          "success",
          "runId"
        ]
      },
      "GenerateVisibilityKeywordsResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "keywords": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "keyword": {
                  "type": "string"
                },
                "source": {
                  "type": "string",
                  "enum": [
                    "growth",
                    "gsc"
                  ]
                }
              }
            }
          },
          "totalCount": {
            "type": "integer"
          },
          "sources": {
            "type": "object",
            "properties": {
              "growth": {
                "type": "integer"
              },
              "gsc": {
                "type": "integer"
              }
            }
          },
          "gscConnected": {
            "type": "boolean"
          },
          "gscLastSynced": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "success",
          "keywords"
        ]
      },
      "AuditEnqueueRequest": {
        "type": "object",
        "properties": {
          "profile_id": {
            "type": "string",
            "format": "uuid"
          },
          "mode": {
            "type": "string",
            "enum": [
              "bulk",
              "single"
            ],
            "default": "bulk"
          },
          "node_filter": {
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1,
              "maxLength": 80
            },
            "maxItems": 120,
            "description": "Required when mode=single."
          }
        },
        "required": [
          "profile_id"
        ]
      },
      "AuditEnqueueResponse": {
        "type": "object",
        "properties": {
          "auditRunId": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "const": "queued"
          },
          "enqueuedAt": {
            "type": "string",
            "format": "date-time"
          },
          "mode": {
            "type": "string",
            "enum": [
              "bulk",
              "single"
            ]
          }
        },
        "required": [
          "auditRunId",
          "status"
        ]
      },
      "AuditRunGetRequest": {
        "type": "object",
        "properties": {
          "runId": {
            "type": "string",
            "format": "uuid"
          },
          "includeNodes": {
            "type": "boolean",
            "default": false,
            "description": "When true, also returns the per-node progress summary."
          }
        },
        "required": [
          "runId"
        ]
      },
      "AuditRun": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "profile_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string"
          },
          "mode": {
            "type": "string"
          },
          "website_url": {
            "type": "string"
          },
          "industry": {
            "type": "string"
          },
          "overall_score": {
            "type": "integer"
          },
          "technical_score": {
            "type": "integer"
          },
          "content_score": {
            "type": "integer"
          },
          "authority_score": {
            "type": "integer"
          },
          "audit_results": {
            "description": "v1-compatible check array ([{passed, ...}]) or {} when unpopulated (jsonb)."
          },
          "error_message": {
            "type": [
              "string",
              "null"
            ]
          },
          "enqueued_at": {
            "type": "string",
            "format": "date-time"
          },
          "started_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "completed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "audited_at": {
            "type": "string",
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "status"
        ]
      },
      "NodeProgressSummary": {
        "type": "object",
        "properties": {
          "node_id": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "diagnosis": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "node_id",
          "status"
        ]
      },
      "AuditRunGetResponse": {
        "type": "object",
        "properties": {
          "run": {
            "$ref": "#/components/schemas/AuditRun"
          },
          "nodes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NodeProgressSummary"
            }
          },
          "node_counts": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            }
          }
        },
        "required": [
          "run"
        ]
      },
      "EnqueueScanRequest": {
        "type": "object",
        "properties": {
          "scan_type": {
            "type": "string",
            "enum": [
              "ai_visibility",
              "web_audit",
              "node_check"
            ]
          },
          "platform": {
            "type": "string",
            "enum": [
              "chatgpt",
              "claude",
              "perplexity",
              "gemini"
            ]
          },
          "profile_id": {
            "type": "string",
            "format": "uuid"
          },
          "website_url": {
            "type": "string",
            "maxLength": 500
          },
          "payload": {
            "type": "object",
            "additionalProperties": true,
            "default": {}
          },
          "priority": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100,
            "default": 10
          }
        },
        "required": [
          "scan_type",
          "profile_id"
        ]
      },
      "EnqueueScanResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "const": "queued"
          },
          "queue_id": {
            "type": "string"
          },
          "position": {
            "type": "integer"
          },
          "estimatedWait": {
            "type": "string"
          }
        },
        "required": [
          "status",
          "queue_id"
        ]
      },
      "NodesListRequest": {
        "type": "object",
        "properties": {
          "profileId": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "locked",
              "available",
              "in_progress",
              "complete",
              "pass",
              "fail",
              "manual",
              "skipped"
            ],
            "description": "Optional filter on node_progress.status."
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 500,
            "default": 500
          }
        },
        "required": [
          "profileId"
        ]
      },
      "NodeProgress": {
        "type": "object",
        "properties": {
          "node_id": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "diagnosis": {
            "type": [
              "string",
              "null"
            ]
          },
          "recommended_fixes": {
            "description": "Suggestion list or object (jsonb); shape varies by node. Null when unset."
          },
          "last_audit_run_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "node_id",
          "status"
        ]
      },
      "NodesListResponse": {
        "type": "object",
        "properties": {
          "profile_id": {
            "type": "string",
            "format": "uuid"
          },
          "nodes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NodeProgress"
            }
          },
          "count": {
            "type": "integer"
          }
        },
        "required": [
          "profile_id",
          "nodes",
          "count"
        ]
      },
      "NodeCompleteRequest": {
        "type": "object",
        "properties": {
          "profileId": {
            "type": "string",
            "format": "uuid"
          },
          "nodeId": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "profileId",
          "nodeId"
        ]
      },
      "NodeCompleteResponse": {
        "type": "object",
        "properties": {
          "node_id": {
            "type": "string"
          },
          "prior_status": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "last_audit_run_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          }
        },
        "required": [
          "node_id",
          "status"
        ]
      },
      "BlogTopicsListRequest": {
        "type": "object",
        "properties": {
          "profileId": {
            "type": "string",
            "format": "uuid"
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 500,
            "default": 200
          }
        },
        "required": [
          "profileId"
        ]
      },
      "BlogTopic": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "generation_stage": {
            "type": [
              "string",
              "null"
            ]
          },
          "scheduled_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          }
        },
        "required": [
          "id",
          "title"
        ]
      },
      "BlogTopicsListResponse": {
        "type": "object",
        "properties": {
          "profile_id": {
            "type": "string",
            "format": "uuid"
          },
          "topics": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BlogTopic"
            }
          },
          "count": {
            "type": "integer"
          }
        },
        "required": [
          "profile_id",
          "topics",
          "count"
        ]
      },
      "GenerateBlogTopicsRequest": {
        "type": "object",
        "properties": {
          "profileId": {
            "type": "string"
          },
          "days": {
            "type": "integer",
            "default": 30,
            "minimum": 1,
            "maximum": 180
          },
          "velocity": {
            "type": "integer",
            "minimum": 1,
            "maximum": 5
          }
        },
        "required": [
          "profileId"
        ]
      },
      "JobQueuedResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean",
            "const": true
          },
          "jobId": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "const": "queued"
          }
        },
        "required": [
          "ok",
          "jobId"
        ]
      },
      "GenerateBlogPostRequest": {
        "type": "object",
        "properties": {
          "profileId": {
            "type": "string",
            "format": "uuid"
          },
          "topicId": {
            "type": "string",
            "format": "uuid"
          },
          "dryRun": {
            "type": "boolean"
          }
        },
        "required": [
          "profileId",
          "topicId"
        ]
      },
      "GenerateBlogPostResponse": {
        "type": "object",
        "description": "ok:true \u2192 claim succeeded. ok:false + code \u2192 expected business failure (topic_wrong_status | connection_missing | tier_too_low | monthly_cap_reached | topic_already_claimed). dryRun returns a preview.\n",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "claimed": {
            "type": "boolean"
          },
          "topicId": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "error": {
            "type": "string"
          }
        },
        "required": [
          "ok"
        ]
      },
      "GenerateContentStrategyResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean",
            "const": true
          },
          "strategy": {
            "type": "string"
          }
        },
        "required": [
          "ok",
          "strategy"
        ]
      },
      "SaveCmsConnectionRequest": {
        "type": "object",
        "properties": {
          "profileId": {
            "type": "string",
            "format": "uuid"
          },
          "site_url": {
            "type": "string",
            "format": "uri"
          },
          "username": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "app_password": {
            "type": "string",
            "minLength": 1,
            "maxLength": 400
          }
        },
        "required": [
          "profileId",
          "site_url",
          "username",
          "app_password"
        ]
      },
      "SaveCmsConnectionResponse": {
        "type": "object",
        "description": "ok:true \u2192 verified+saved; ok:false + code:connection_failed \u2192 probe failed.",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "last_verified_at": {
            "type": "string",
            "format": "date-time"
          },
          "error": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "wp_error_code": {
            "type": "string"
          }
        },
        "required": [
          "ok"
        ]
      },
      "BuzzEngagementsListRequest": {
        "type": "object",
        "properties": {
          "profileId": {
            "type": "string",
            "format": "uuid",
            "description": "Scope to one profile (ownership-checked). Omit to list across the account."
          },
          "status": {
            "type": "string",
            "description": "Filter by engagement status (e.g. draft, approved, scheduled, posted, failed)."
          },
          "since": {
            "type": "string",
            "description": "Time window \u2014 a relative span (\"7d\", \"24h\") or an ISO 8601 timestamp; filters created_at."
          },
          "groupBy": {
            "type": "string",
            "description": "When \"subreddit\", include a per-subreddit total in the response."
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 500,
            "default": 200
          }
        }
      },
      "BuzzEngagement": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "profile_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string"
          },
          "post_type": {
            "type": [
              "string",
              "null"
            ]
          },
          "subreddit": {
            "type": [
              "string",
              "null"
            ]
          },
          "draft_content": {
            "type": [
              "string",
              "null"
            ]
          },
          "scheduled_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "posted_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "retry_count": {
            "type": "integer"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "profile_id",
          "status"
        ]
      },
      "BuzzEngagementsListResponse": {
        "type": "object",
        "properties": {
          "engagements": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BuzzEngagement"
            }
          },
          "total": {
            "type": "integer"
          },
          "by_subreddit": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            }
          }
        },
        "required": [
          "engagements",
          "total"
        ]
      },
      "BuzzDraftApproveRequest": {
        "type": "object",
        "properties": {
          "draftId": {
            "type": "string",
            "format": "uuid"
          },
          "scheduleAt": {
            "type": "string",
            "format": "date-time",
            "description": "ISO 8601. When present the draft is scheduled; otherwise it's approved."
          }
        },
        "required": [
          "draftId"
        ]
      },
      "BuzzResearchListRequest": {
        "type": "object",
        "properties": {
          "profileId": {
            "type": "string",
            "format": "uuid"
          },
          "minRelevance": {
            "type": "number",
            "minimum": 0,
            "maximum": 1,
            "default": 0.7,
            "description": "Only return mentions with relevance_score at or above this. Mentions with a null relevance_score (unclassified) are always included regardless of the threshold."
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 500,
            "default": 200
          }
        },
        "required": [
          "profileId"
        ]
      },
      "BuzzMention": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "post_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "post_title": {
            "type": [
              "string",
              "null"
            ]
          },
          "subreddit": {
            "type": [
              "string",
              "null"
            ]
          },
          "mention_type": {
            "type": [
              "string",
              "null"
            ]
          },
          "sentiment": {
            "type": [
              "string",
              "null"
            ]
          },
          "relevance_score": {
            "type": [
              "number",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id"
        ]
      },
      "BuzzResearchListResponse": {
        "type": "object",
        "properties": {
          "profile_id": {
            "type": "string",
            "format": "uuid"
          },
          "mentions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BuzzMention"
            }
          },
          "count": {
            "type": "integer"
          }
        },
        "required": [
          "profile_id",
          "mentions",
          "count"
        ]
      },
      "BuzzProfileGetResponse": {
        "type": "object",
        "properties": {
          "profile_id": {
            "type": "string",
            "format": "uuid"
          },
          "research_status": {
            "type": [
              "string",
              "null"
            ]
          },
          "last_research_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "required": [
          "profile_id"
        ]
      },
      "BuzzBrandResearchResponse": {
        "type": "object",
        "description": "Async default `{success,started}`; sync (wait:true) returns the full result.",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "started": {
            "type": "boolean"
          },
          "posts_processed": {
            "type": "integer"
          },
          "subreddits_found": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "research_summary": {
            "type": "object",
            "properties": {
              "total_mentions": {
                "type": "integer"
              },
              "sentiment_breakdown": {
                "type": "object",
                "properties": {
                  "positive": {
                    "type": "integer"
                  },
                  "neutral": {
                    "type": "integer"
                  },
                  "negative": {
                    "type": "integer"
                  }
                }
              },
              "top_subreddits": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "count": {
                      "type": "integer"
                    }
                  }
                }
              },
              "keyword_matches": {
                "type": "integer"
              }
            }
          }
        },
        "required": [
          "success"
        ]
      },
      "BuzzGenerateDraftsRequest": {
        "type": "object",
        "properties": {
          "profile_id": {
            "type": "string"
          },
          "engagement_id": {
            "type": "string",
            "description": "Single-engagement regeneration path."
          },
          "post_type": {
            "type": "string",
            "enum": [
              "comment",
              "post"
            ],
            "description": "Single path only."
          }
        },
        "required": [
          "profile_id"
        ]
      },
      "BuzzGenerateDraftsResponse": {
        "type": "object",
        "description": "Single-engagement returns draft_content; bulk returns counts.",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "draft_content": {
            "type": "string"
          },
          "post_type": {
            "type": "string",
            "enum": [
              "comment",
              "post"
            ]
          },
          "skipped": {
            "type": "boolean"
          },
          "reason": {
            "type": "string"
          },
          "drafts_created": {
            "type": "integer"
          },
          "comment_drafts": {
            "type": "integer"
          },
          "post_drafts": {
            "type": "integer"
          },
          "drafts_skipped": {
            "type": "integer"
          }
        },
        "required": [
          "success"
        ]
      },
      "BuzzOpportunitySearchResponse": {
        "type": "object",
        "description": "Async default `{success,started}`; sync (wait:true) returns counts.",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "started": {
            "type": "boolean"
          },
          "opportunities_found": {
            "type": "integer"
          },
          "posts_processed": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "success"
        ]
      },
      "BuzzVisibilityScoreResponse": {
        "type": "object",
        "properties": {
          "score": {
            "type": "number",
            "minimum": 0,
            "maximum": 100
          },
          "total_engagements": {
            "type": "integer"
          },
          "mentions": {
            "type": "integer"
          },
          "opportunities": {
            "type": "integer"
          },
          "posted": {
            "type": "integer"
          },
          "drafted": {
            "type": "integer"
          },
          "sentiment": {
            "type": "object",
            "properties": {
              "positive": {
                "type": "integer"
              },
              "negative": {
                "type": "integer"
              },
              "neutral": {
                "type": "integer"
              }
            }
          },
          "top_subreddits": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string"
                },
                "total": {
                  "type": "integer"
                },
                "posted": {
                  "type": "integer"
                },
                "avg_upvotes": {
                  "type": "number"
                }
              }
            }
          },
          "opportunity_rate": {
            "type": "number"
          },
          "engagement_metrics": {
            "type": "object",
            "properties": {
              "total_tracked": {
                "type": "integer"
              },
              "total_upvotes": {
                "type": "integer"
              },
              "avg_upvotes": {
                "type": "number"
              },
              "total_comments": {
                "type": "integer"
              },
              "avg_comments": {
                "type": "number"
              }
            }
          },
          "by_opportunity_type": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            }
          }
        },
        "required": [
          "score"
        ]
      },
      "DeleteAuditRunRequest": {
        "type": "object",
        "properties": {
          "runId": {
            "type": "string"
          }
        },
        "required": [
          "runId"
        ]
      },
      "DeleteAuditRunResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean",
            "const": true
          },
          "deleted": {
            "type": "object",
            "properties": {
              "audit_run": {
                "type": "string"
              },
              "website_url": {
                "type": "string"
              },
              "node_rows": {
                "type": "integer"
              }
            }
          }
        },
        "required": [
          "ok"
        ]
      },
      "CreateLeadAccountRequest": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "format": "email"
          },
          "business_name": {
            "type": "string"
          },
          "website_url": {
            "type": "string"
          },
          "industry": {
            "type": "string",
            "enum": [
              "local_service",
              "ecommerce",
              "b2b_saas"
            ]
          },
          "location": {
            "type": "string"
          },
          "redirect_to": {
            "type": "string",
            "default": "https://app.rankrush.ai"
          }
        },
        "required": [
          "email",
          "business_name",
          "website_url",
          "industry"
        ]
      },
      "CreateLeadAccountResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "const": true
          },
          "userId": {
            "type": "string"
          },
          "profileId": {
            "type": "string"
          },
          "runId": {
            "type": "string"
          },
          "confirmUrl": {
            "type": "string"
          },
          "scan": {
            "type": "object",
            "properties": {
              "keywords": {
                "type": "integer"
              },
              "written": {
                "type": "integer"
              },
              "error": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "summary": {
                "type": "string"
              }
            }
          }
        },
        "required": [
          "success",
          "userId",
          "profileId"
        ]
      },
      "SuggestCompetitorsRequest": {
        "type": "object",
        "properties": {
          "websiteUrl": {
            "type": "string",
            "format": "uri",
            "maxLength": 500
          },
          "industry": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "local_service",
              "b2b_saas",
              "ecommerce",
              null
            ]
          },
          "businessName": {
            "type": "string",
            "maxLength": 200
          },
          "specialty": {
            "type": "string",
            "maxLength": 500
          },
          "businessDescription": {
            "type": "string",
            "maxLength": 500
          },
          "primaryCountry": {
            "type": "string",
            "maxLength": 100
          },
          "additionalMarkets": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "maxItems": 5
          },
          "businessLanguage": {
            "type": "string",
            "maxLength": 10
          }
        },
        "required": [
          "websiteUrl"
        ]
      },
      "SuggestCompetitorsResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "category": {
            "type": "object",
            "properties": {
              "primary": {
                "type": "string"
              },
              "subcategory": {
                "type": "string"
              },
              "geography": {
                "type": "string"
              },
              "pricePoint": {
                "type": "string"
              },
              "businessModel": {
                "type": "string"
              }
            }
          },
          "competitors": {
            "type": "array",
            "maxItems": 10,
            "items": {
              "type": "object",
              "properties": {
                "domain": {
                  "type": "string"
                },
                "reason": {
                  "type": "string"
                },
                "confidence": {
                  "type": "string",
                  "enum": [
                    "high",
                    "medium",
                    "low"
                  ]
                }
              }
            }
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "success"
        ]
      },
      "GenerateNodeContentRequest": {
        "type": "object",
        "properties": {
          "nodeId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "nodeName": {
            "type": "string",
            "maxLength": 200
          },
          "taskId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "taskName": {
            "type": "string",
            "maxLength": 200
          },
          "promptTemplate": {
            "type": "string",
            "minLength": 1,
            "maxLength": 10000
          },
          "businessName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "industry": {
            "type": "string",
            "enum": [
              "local_service",
              "b2b_saas",
              "ecommerce"
            ]
          },
          "location": {
            "type": "string",
            "maxLength": 200
          },
          "specialty": {
            "type": "string",
            "maxLength": 200
          },
          "businessDescription": {
            "type": "string",
            "maxLength": 500
          },
          "websiteUrl": {
            "type": "string",
            "maxLength": 500
          },
          "ecommercePlatform": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "woocommerce",
              "shopify",
              "magento",
              "custom",
              null
            ]
          }
        },
        "required": [
          "nodeId",
          "taskId",
          "promptTemplate",
          "businessName",
          "industry"
        ]
      },
      "GenerateNodeContentResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "content": {
            "description": "JSON-parsed object if parseable, else raw string.",
            "oneOf": [
              {
                "type": "object",
                "additionalProperties": true
              },
              {
                "type": "string"
              }
            ]
          },
          "taskId": {
            "type": "string"
          },
          "nodeId": {
            "type": "string"
          },
          "generatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "success",
          "content"
        ]
      },
      "ExtractOfferingsRequest": {
        "type": "object",
        "properties": {
          "profileId": {
            "type": "string"
          },
          "force": {
            "type": "boolean",
            "description": "Re-extract even if confirmed offerings exist."
          }
        },
        "required": [
          "profileId"
        ]
      },
      "ExtractOfferingsResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "jobId": {
            "type": "string"
          },
          "profileId": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "const": "processing"
          },
          "skipped": {
            "type": "boolean"
          },
          "reason": {
            "type": "string"
          }
        },
        "required": [
          "success"
        ]
      },
      "GscSelectPropertyRequest": {
        "type": "object",
        "properties": {
          "profileId": {
            "type": "string"
          },
          "propertyUrl": {
            "type": "string"
          }
        },
        "required": [
          "profileId",
          "propertyUrl"
        ]
      },
      "GscFetchQueriesResponse": {
        "type": "object",
        "description": "success:false (200) when GSC not connected or token expired.",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "queryCount": {
            "type": "integer"
          },
          "queries": {
            "type": "array",
            "maxItems": 20,
            "items": {
              "type": "object",
              "properties": {
                "query": {
                  "type": "string"
                },
                "clicks": {
                  "type": "integer"
                },
                "impressions": {
                  "type": "integer"
                },
                "ctr": {
                  "type": "number"
                },
                "position": {
                  "type": "number"
                }
              }
            }
          },
          "error": {
            "type": "string"
          },
          "tokenExpired": {
            "type": "boolean"
          }
        },
        "required": [
          "success"
        ]
      },
      "BuzzExtractProfileResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "extracted": {
            "type": "object",
            "properties": {
              "brand_voice": {
                "type": "string"
              },
              "persona_description": {
                "type": "string"
              },
              "target_subreddits": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "auto_extracted_keywords": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "reddit_keywords": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "competitor_brands": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          }
        },
        "required": [
          "success",
          "extracted"
        ]
      },
      "VerifyBlogPostsRequest": {
        "type": "object",
        "description": "Single-topic mode when topicId present (needs profileId); empty {} = cron sweep (service-role only).",
        "properties": {
          "profileId": {
            "type": "string"
          },
          "topicId": {
            "type": "string"
          }
        }
      },
      "VerifyBlogPostsResponse": {
        "type": "object",
        "properties": {
          "checked": {
            "type": "integer"
          },
          "published": {
            "type": "integer"
          },
          "trashed": {
            "type": "integer"
          },
          "reverted": {
            "type": "integer"
          },
          "errors": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "checked"
        ]
      }
    }
  }
}
