{
  "openapi": "3.0.1",
  "info": {
    "title": "Cusp: Google Trends Spike & Trend Detector (Any Dataset)",
    "description": "Find which Google Trends keywords are really taking off, which prices just dropped, and which scrapers silently broke. Point Cusp at any dataset with a date and a number; every finding is computed from your data with the evidence attached. No AI.",
    "version": "0.1",
    "x-build-id": "wLr9kbWDTi5VDuOBk"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/aidaabassilova~cusp/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-aidaabassilova-cusp",
        "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/aidaabassilova~cusp/runs": {
      "post": {
        "operationId": "runs-sync-aidaabassilova-cusp",
        "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/aidaabassilova~cusp/run-sync": {
      "post": {
        "operationId": "run-sync-aidaabassilova-cusp",
        "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",
        "properties": {
          "datasets": {
            "title": "Datasets to analyze",
            "type": "array",
            "description": "One or more datasets, e.g. the output of a price scraper, Google Trends Scraper or a reviews scraper. Several datasets are read one after another as one table — pick the datasets of several runs to build a history."
          },
          "datasetId": {
            "title": "Dataset from an integration",
            "type": "string",
            "description": "For automation: when Cusp runs after your scraper via Integrations, set this to {{resource.defaultDatasetId}} and it analyzes that run's dataset. For manual runs use \"Datasets to analyze\" above."
          },
          "data": {
            "title": "…or paste the data",
            "type": "array",
            "description": "Your own rows, for trying Cusp or for small one-off checks. Objects like {\"date\": \"2026-09-01\", \"value\": 12}, [date, value] pairs, or plain numbers. Ignored when you also pick a dataset — so the example rows here never mix into your data."
          },
          "historyKey": {
            "title": "Remember history between runs (monitoring)",
            "type": "string",
            "description": "Give the history a name, e.g. \"kaspi-prices\", and Cusp stores every run's new points in your account and analyzes the whole history each time. Use it when Cusp runs after each scraper run (schedule or integration), where every run brings only the latest snapshot. Only points newer than what is stored are added, and datasets already added are skipped, so retries never double-count."
          },
          "dateField": {
            "title": "Date field",
            "type": "string",
            "description": "Field with the date or time of each item. ISO dates, Unix timestamps (seconds or ms) and date-times all work. Use dots for nested fields, e.g. \"meta.scrapedAt\".",
            "default": "date"
          },
          "valueField": {
            "title": "Value field",
            "type": "string",
            "description": "Field with the number to analyze, e.g. \"price\", \"rating\", \"reviewsCount\". Formatted strings such as \"1,299.00\" or \"12 990 ₸\" are read correctly. Array items are addressed by index: \"value.0\". Ignored when Aggregation is \"count\".",
            "default": "value"
          },
          "groupBy": {
            "title": "One series per…",
            "type": "string",
            "description": "Analyze a separate series for each distinct value of this field — e.g. \"productId\", \"url\", \"searchTerm\", \"placeId\". Leave empty to analyze everything as one series."
          },
          "unwindField": {
            "title": "Nested list field",
            "type": "string",
            "description": "When each item holds its history in a list, name that list here and every element becomes a row (with the parent's fields still available for grouping). For Google Trends Scraper output use \"interestOverTime_timelineData\" with Date field \"time\", Value field \"value.0\" and One series per \"searchTerm\"."
          },
          "dateSource": {
            "title": "Where dates come from",
            "enum": [
              "field",
              "datasetCreatedAt",
              "order"
            ],
            "type": "string",
            "description": "\"field\": read the Date field. \"datasetCreatedAt\": use each dataset's creation time — perfect when every dataset is one snapshot (one scheduled run of a scraper that has no date in its items). \"order\": no dates, use the order of items.",
            "default": "field"
          },
          "interval": {
            "title": "Group rows by",
            "enum": [
              "none",
              "hour",
              "day",
              "week",
              "month"
            ],
            "type": "string",
            "description": "Bucket rows into hours, days, weeks or months before analysis. \"none\" keeps each timestamp as its own point. Use \"day\" or \"week\" with Aggregation \"count\" to turn a list of reviews or mentions into a volume per day or week.",
            "default": "none"
          },
          "aggregation": {
            "title": "Combine rows in the same bucket with",
            "enum": [
              "last",
              "first",
              "sum",
              "mean",
              "min",
              "max",
              "count"
            ],
            "type": "string",
            "description": "How to combine several rows that fall into the same bucket. \"count\" counts rows (reviews per day, mentions per week) and needs no Value field. Empty buckets count as 0 only for \"sum\" and \"count\"; for levels like prices they stay missing — never invented.",
            "default": "last"
          },
          "endDate": {
            "title": "Series end date",
            "type": "string",
            "description": "Optional, for \"sum\" / \"count\": extend the series with empty (0) buckets up to this date, so that \"no new reviews for 5 days\" becomes visible. Usually today's date, e.g. 2026-09-28."
          },
          "sensitivity": {
            "title": "Sensitivity",
            "enum": [
              "low",
              "medium",
              "high"
            ],
            "type": "string",
            "description": "\"low\" reports only large, unmistakable changes. \"high\" also reports smaller ones. \"medium\" is a balanced default.",
            "default": "medium"
          },
          "minSeverity": {
            "title": "Report only observations at least this important",
            "enum": [
              "low",
              "medium",
              "high"
            ],
            "type": "string",
            "description": "For monitoring and alerts: \"medium\" hides minor findings, \"high\" keeps only the big ones. Leave empty to report everything.",
            "default": "low"
          },
          "baselineWindow": {
            "title": "Baseline window",
            "minimum": 3,
            "maximum": 1000,
            "type": "integer",
            "description": "How many previous points form the 'normal' level a new point is compared against (median). 14 means: compare to the median of the last 14 points.",
            "default": 14
          },
          "recentPoints": {
            "title": "Look for spikes, drops and records in the last … points",
            "minimum": 0,
            "type": "integer",
            "description": "Only the most recent points are checked for spikes, drops and new records, so you hear about what is happening now. 0 = scan the whole history.",
            "default": 7
          },
          "trendWindow": {
            "title": "Trend window",
            "minimum": 5,
            "maximum": 1000,
            "type": "integer",
            "description": "How many of the latest points the statistical trend test (Mann–Kendall) looks at.",
            "default": 30
          },
          "shiftWindow": {
            "title": "Level-shift window",
            "minimum": 3,
            "maximum": 1000,
            "type": "integer",
            "description": "How many of the latest points must hold a new level to report it as a \"new normal\" (a step change, not a one-off spike).",
            "default": 5
          },
          "minPoints": {
            "title": "Minimum points per series",
            "minimum": 3,
            "maximum": 10000,
            "type": "integer",
            "description": "Series with fewer usable points are not analyzed at all (and not charged) — Cusp reports nothing rather than guessing.",
            "default": 8
          },
          "valueLabel": {
            "title": "Name of the value in explanations",
            "type": "string",
            "description": "E.g. \"Price\" → \"Price fell 19% below the 14-day median…\". Defaults to the Value field name."
          },
          "skipPartialRows": {
            "title": "Skip unfinished periods",
            "type": "boolean",
            "description": "Skip rows marked isPartial: true — Google Trends marks the current, unfinished week this way, and it would always look like a drop.",
            "default": true
          },
          "includeQuietSeries": {
            "title": "Add a row for series with nothing to report",
            "type": "boolean",
            "description": "Adds a \"no_change\" or \"insufficient_data\" row for each such series, so every series appears in the output. Turn off to get only real observations. Note: every analyzed series is billed once, whether or not it has findings.",
            "default": true
          },
          "maxSeries": {
            "title": "Max series",
            "minimum": 1,
            "maximum": 100000,
            "type": "integer",
            "description": "Safety limit on how many series (groups) are analyzed in one run.",
            "default": 5000
          },
          "maxItems": {
            "title": "Max items to read",
            "minimum": 1,
            "maximum": 500000,
            "type": "integer",
            "description": "Safety limit on how many dataset items are read in total. Up to 500,000 items fit in the default 256 MB of memory; for more, split the run or raise the run's memory.",
            "default": 200000
          }
        }
      },
      "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
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "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
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}