{
  "openapi": "3.0.1",
  "info": {
    "title": "Google Reviews Monitor - $1.00/1k, AI Reply Drafts",
    "description": "Watch Google reviews for every location you own. Each branch is its own Google Business profile. One bad branch is easy to miss. It checks them all and returns only what changed: new reviews and rating drops. Sends to Slack, Discord or a webhook. $0.015 per location checked, $0.001 per new review.",
    "version": "0.1",
    "x-build-id": "IgjxvOopSIxDfrnrY"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/dami_studio~google-reviews-monitor/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-dami_studio-google-reviews-monitor",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/acts/dami_studio~google-reviews-monitor/runs": {
      "post": {
        "operationId": "runs-sync-dami_studio-google-reviews-monitor",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor and returns information about the initiated run in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/runsResponseSchema"
                }
              }
            }
          }
        }
      }
    },
    "/acts/dami_studio~google-reviews-monitor/run-sync": {
      "post": {
        "operationId": "run-sync-dami_studio-google-reviews-monitor",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "inputSchema": {
        "type": "object",
        "required": [
          "locations"
        ],
        "properties": {
          "locations": {
            "title": "Client locations to monitor",
            "type": "array",
            "description": "One entry per Google Business location. clientName is your label (e.g. the client/branch name); googleMapsUrl is the public Google Maps URL of the business. Tip: open the place on Google Maps and copy the URL from the address bar."
          },
          "maxReviewsPerRun": {
            "title": "Max reviews to load per location",
            "minimum": 1,
            "maximum": 1000,
            "type": "integer",
            "description": "How many of the newest reviews to load per location each run. Higher = more thorough but slower and more expensive (each extra page of reviews is another scroll over the proxy). 10 is plenty for a scheduled monitor that only needs the latest deltas; raise it for a first-run backfill.",
            "default": 10
          },
          "onlyNewSinceLastRun": {
            "title": "Only return new/changed since last run",
            "type": "boolean",
            "description": "Core monitor behavior: each scheduled run emits only NEW or CHANGED reviews (deltas), not a full re-dump. Persisted between runs via the Key-Value Store.",
            "default": true
          },
          "alertOnNewReviews": {
            "title": "Alert on new reviews",
            "type": "boolean",
            "description": "Include locations with any new review in the notification/report signal.",
            "default": true
          },
          "alertOnNegativeReviews": {
            "title": "Alert on negative reviews",
            "type": "boolean",
            "description": "Flag new reviews at or below the negative rating threshold.",
            "default": true
          },
          "negativeRatingThreshold": {
            "title": "Negative rating threshold (stars)",
            "minimum": 1,
            "maximum": 5,
            "type": "integer",
            "description": "Reviews with a star rating at or below this value are treated as negative.",
            "default": 3
          },
          "trackOwnerReplies": {
            "title": "Track owner replies",
            "type": "boolean",
            "description": "Detect when the business owner replies to a review (review changes from unanswered to answered).",
            "default": true
          },
          "detectRatingDrops": {
            "title": "Detect overall rating drops",
            "type": "boolean",
            "description": "Compare each location's overall star rating against the previous run and flag drops.",
            "default": true
          },
          "generateAiSummary": {
            "title": "Generate AI summary per location",
            "type": "boolean",
            "description": "Produce a short, action-ready briefing per location from the NEW reviews (e.g. '2 urgent reviews need replies; main complaint: wait times'). Uses an LLM if a key is configured, otherwise a free rule-based summary.",
            "default": true
          },
          "generateReplyDrafts": {
            "title": "Generate reply drafts for urgent reviews",
            "type": "boolean",
            "description": "Draft a professional public reply for each urgent (negative + unanswered) review. Capped per run to control cost.",
            "default": false
          },
          "aiModel": {
            "title": "AI model",
            "enum": [
              "gpt-4o-mini",
              "gpt-4.1-mini",
              "gpt-4o",
              "claude-haiku-4-5",
              "claude-sonnet-4-6"
            ],
            "type": "string",
            "description": "Model used for AI summaries/reply drafts (only when an API key is configured). GPT models need an OpenAI key; Claude models need an Anthropic key.",
            "default": "gpt-4o-mini"
          },
          "anthropicApiKey": {
            "title": "Anthropic (Claude) API key (optional)",
            "type": "string",
            "description": "Optional. Bring your own Anthropic key to enable AI summaries/reply drafts with Claude. If left blank, the actor uses the ANTHROPIC_API_KEY environment secret (if the owner set one), then OpenAI, then a free rule-based summary."
          },
          "openaiApiKey": {
            "title": "OpenAI API key (optional)",
            "type": "string",
            "description": "Optional. Bring your own OpenAI key to use GPT models instead of Claude. Used only if no Anthropic key is configured."
          },
          "weeklyReport": {
            "title": "Generate rolled-up HTML report",
            "type": "boolean",
            "description": "Render a single multi-location HTML report to the Key-Value Store and link it from each dataset record.",
            "default": true
          },
          "webhookUrl": {
            "title": "Webhook URL (optional)",
            "type": "string",
            "description": "Optional. Receive a compact summary when there are changes. Auto-formats for Slack and Discord incoming webhooks; otherwise sends a generic JSON payload (works with Zapier/Make/n8n and email-via-webhook).",
            "default": ""
          },
          "proxyConfiguration": {
            "title": "Proxy configuration",
            "type": "object",
            "description": "Apify Proxy settings. Defaults to DATACENTER proxy, which is fast and cheap and works for most locations. If a location gets blocked (reviews feed fails to load), switch this to RESIDENTIAL — it is more resilient to Google's anti-bot but costs significantly more per run, so only use it where you actually need it.",
            "default": {
              "useApifyProxy": true
            }
          }
        }
      },
      "runsResponseSchema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "actId": {
                "type": "string"
              },
              "userId": {
                "type": "string"
              },
              "startedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "finishedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "status": {
                "type": "string",
                "example": "READY"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "origin": {
                    "type": "string",
                    "example": "API"
                  },
                  "userAgent": {
                    "type": "string"
                  }
                }
              },
              "stats": {
                "type": "object",
                "properties": {
                  "inputBodyLen": {
                    "type": "integer",
                    "example": 2000
                  },
                  "rebootCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "restartCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "resurrectCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "computeUnits": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "options": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string",
                    "example": "latest"
                  },
                  "timeoutSecs": {
                    "type": "integer",
                    "example": 300
                  },
                  "memoryMbytes": {
                    "type": "integer",
                    "example": 1024
                  },
                  "diskMbytes": {
                    "type": "integer",
                    "example": 2048
                  }
                }
              },
              "buildId": {
                "type": "string"
              },
              "defaultKeyValueStoreId": {
                "type": "string"
              },
              "defaultDatasetId": {
                "type": "string"
              },
              "defaultRequestQueueId": {
                "type": "string"
              },
              "buildNumber": {
                "type": "string",
                "example": "1.0.0"
              },
              "containerUrl": {
                "type": "string"
              },
              "usage": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "integer",
                    "example": 1
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "usageTotalUsd": {
                "type": "number",
                "example": 0.00005
              },
              "usageUsd": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "number",
                    "example": 0.00005
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}