{
  "openapi": "3.1.0",
  "info": {
    "title": "CommentHunter Agent API",
    "version": "2026-09-03",
    "description": "The same extraction capabilities used by CommentHunter's dashboard. Credit-based public URL extraction for comments, reviews, posts, and more.",
    "termsOfService": "https://commenthunter.click/terms",
    "contact": { "name": "CommentHunter", "url": "https://commenthunter.click/docs" },
    "license": { "name": "Proprietary", "url": "https://commenthunter.click/terms" }
  },
  "servers": [
    {
      "url": "https://jdstzpeukxcxxnodvess.supabase.co/functions/v1",
      "description": "Production Edge Functions"
    }
  ],
  "tags": [
    { "name": "extraction", "description": "Comment, review, and universal extractors" },
    { "name": "account", "description": "Credits, plans, and checkout" }
  ],
  "paths": {
    "/extract-comments": {
      "post": {
        "operationId": "extract_comments",
        "summary": "Extract comments",
        "description": "Extract comments and optional replies from public post URLs. Platform is inferred from the URL when omitted. Credits are deducted per exported item.",
        "tags": ["extraction"],
        "security": [{ "BearerAuth": [] }, { "AnonKey": [] }],
        "x-mcp-tool": "extract_comments",
        "x-tool-annotations": { "readOnlyHint": false, "destructiveHint": false, "openWorldHint": true },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/ExtractCommentsRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Extraction result or structured error in body",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ExtractCommentsResponse" }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/extract-reviews": {
      "post": {
        "operationId": "extract_reviews",
        "summary": "Extract reviews",
        "description": "Extract product or business reviews from Amazon, Yelp, Google Maps, Airbnb, Trustpilot, and similar listing URLs.",
        "tags": ["extraction"],
        "security": [{ "BearerAuth": [] }, { "AnonKey": [] }],
        "x-mcp-tool": "extract_reviews",
        "x-tool-annotations": { "readOnlyHint": false, "destructiveHint": false, "openWorldHint": true },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/ExtractReviewsRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Reviews array and credit usage",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ExtractReviewsResponse" }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/extract-universal": {
      "post": {
        "operationId": "extract_universal",
        "summary": "Universal extraction",
        "description": "Product-typed extraction: posts, followers, leads, transcription, OCR, likes, profiles, comments, or reviews.",
        "tags": ["extraction"],
        "security": [{ "BearerAuth": [] }, { "AnonKey": [] }],
        "x-mcp-tool": "extract_universal",
        "x-tool-annotations": { "readOnlyHint": false, "destructiveHint": false, "openWorldHint": true },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/ExtractUniversalRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Normalized items for the product type",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ExtractUniversalResponse" }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/extract-youtube-comments": {
      "post": {
        "operationId": "extract_youtube_comments",
        "summary": "Extract YouTube comments",
        "description": "YouTube-specific comment extraction. Prefer extract_comments with a youtube.com URL unless you need this dedicated function.",
        "tags": ["extraction"],
        "security": [{ "BearerAuth": [] }, { "AnonKey": [] }],
        "x-mcp-tool": "extract_youtube_comments",
        "x-tool-annotations": { "readOnlyHint": false, "destructiveHint": false, "openWorldHint": true },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": { "type": "string", "format": "uri" },
                  "limit": { "type": "integer", "minimum": 1, "maximum": 5000, "default": 500 }
                },
                "required": ["url"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "YouTube comments",
            "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true } } }
          }
        }
      }
    },
    "/check-subscription": {
      "post": {
        "operationId": "check_subscription",
        "summary": "Get usage and plan",
        "description": "Return the authenticated user's plan, credit balance, and Stripe subscription state.",
        "tags": ["account"],
        "security": [{ "BearerAuth": [] }, { "AnonKey": [] }],
        "x-mcp-tool": "check_subscription",
        "x-tool-annotations": { "readOnlyHint": true, "destructiveHint": false, "openWorldHint": false },
        "responses": {
          "200": {
            "description": "Plan and credits",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SubscriptionStatus" } } }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/create-checkout": {
      "post": {
        "operationId": "create_checkout",
        "summary": "Create Stripe checkout",
        "description": "Create a Stripe Checkout session. Confirm with the user before charging.",
        "tags": ["account"],
        "security": [{ "BearerAuth": [] }, { "AnonKey": [] }],
        "x-mcp-tool": "create_checkout",
        "x-tool-annotations": { "readOnlyHint": false, "destructiveHint": false, "openWorldHint": true },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "priceId": { "type": "string" },
                  "plan": { "type": "string" }
                },
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Checkout URL",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "url": { "type": "string", "format": "uri" }
                  }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "Supabase user JWT (preferred) or anon key",
        "description": "Authorization: Bearer <token>"
      },
      "AnonKey": {
        "type": "apiKey",
        "in": "header",
        "name": "apikey",
        "description": "Supabase anon/publishable key"
      }
    },
    "schemas": {
      "ExtractCommentsRequest": {
        "type": "object",
        "required": ["urls"],
        "properties": {
          "urls": {
            "type": "array",
            "minItems": 1,
            "maxItems": 50,
            "items": { "type": "string", "format": "uri" }
          },
          "platform": {
            "type": "string",
            "description": "Optional. Inferred from URL when omitted.",
            "enum": [
              "youtube", "tiktok", "instagram", "facebook", "twitter", "threads",
              "reddit", "linkedin", "producthunt", "disqus", "amazon", "trustpilot",
              "tripadvisor", "steam", "yelp", "airbnb", "google-business", "etsy",
              "aliexpress", "kickstarter", "twitch", "discord", "apple-store",
              "google-play", "chrome-webstore", "imdb", "walmart", "bestbuy",
              "flipkart", "vimeo"
            ]
          },
          "limit": { "type": "integer", "minimum": 1, "maximum": 5000, "default": 500 },
          "includeReplies": { "type": "boolean", "default": true },
          "exportLikesOnly": { "type": "boolean", "default": false },
          "exportJobId": { "type": "string", "format": "uuid" }
        },
        "additionalProperties": true
      },
      "ExtractedComment": {
        "type": "object",
        "properties": {
          "username": { "type": "string" },
          "text": { "type": "string" },
          "likes": { "type": "integer" },
          "timestamp": { "type": "string" },
          "replyTo": { "type": ["string", "null"] },
          "userId": { "type": "string" },
          "profileUrl": { "type": "string" },
          "commentUrl": { "type": "string" },
          "platform": { "type": "string" }
        },
        "additionalProperties": true
      },
      "ExtractCommentsResponse": {
        "type": "object",
        "properties": {
          "comments": { "type": "array", "items": { "$ref": "#/components/schemas/ExtractedComment" } },
          "results": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
          "topLevelCount": { "type": "integer" },
          "repliesCount": { "type": "integer" },
          "exportedCount": { "type": "integer" },
          "creditsUsed": { "type": "integer" },
          "partial": { "type": "boolean" },
          "partialReason": { "type": "string" },
          "continuation": { "type": "object", "additionalProperties": true },
          "errorCode": {
            "type": "string",
            "enum": ["INVALID_URL", "PLATFORM_NOT_SUPPORTED", "RATE_LIMIT", "EXTRACTION_FAILED", "PRIVATE_OR_UNAVAILABLE", "API_ERROR"]
          },
          "errorMessage": { "type": "string" }
        }
      },
      "ExtractReviewsRequest": {
        "type": "object",
        "required": ["url", "platform"],
        "properties": {
          "url": { "type": "string", "format": "uri" },
          "platform": {
            "type": "string",
            "enum": ["amazon", "yelp", "airbnb", "booking", "google_maps", "tripadvisor", "trustpilot", "producthunt"]
          },
          "maxItems": { "type": "integer", "minimum": 1, "maximum": 5000, "default": 200 }
        }
      },
      "ReviewRow": {
        "type": "object",
        "properties": {
          "reviewId": { "type": "string" },
          "rating": { "type": ["number", "null"] },
          "title": { "type": "string" },
          "body": { "type": "string" },
          "author": { "type": "string" },
          "date": { "type": "string" },
          "sourceUrl": { "type": "string" }
        },
        "additionalProperties": true
      },
      "ExtractReviewsResponse": {
        "type": "object",
        "properties": {
          "reviews": { "type": "array", "items": { "$ref": "#/components/schemas/ReviewRow" } },
          "creditsUsed": { "type": "integer" },
          "error": { "type": "string" }
        },
        "additionalProperties": true
      },
      "ExtractUniversalRequest": {
        "type": "object",
        "required": ["url", "platform", "productType"],
        "properties": {
          "url": { "type": "string" },
          "platform": { "type": "string" },
          "productType": {
            "type": "string",
            "enum": ["comments", "reviews", "posts", "followers", "leads", "profiles", "transcription", "ocr", "likes"]
          },
          "maxItems": { "type": "integer", "minimum": 1, "maximum": 5000, "default": 100 },
          "dateFrom": { "type": "string" },
          "dateTo": { "type": "string" }
        }
      },
      "ExtractUniversalResponse": {
        "type": "object",
        "additionalProperties": true
      },
      "SubscriptionStatus": {
        "type": "object",
        "additionalProperties": true
      },
      "ErrorEnvelope": {
        "type": "object",
        "properties": {
          "errorCode": { "type": "string" },
          "errorMessage": { "type": "string" },
          "error": { "type": "string" }
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Missing or invalid token",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorEnvelope" } } }
      },
      "RateLimited": {
        "description": "Rate limit exceeded",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorEnvelope" } } }
      }
    }
  }
}
