{
  "openapi": "3.0.1",
  "info": {
    "title": "Unified Scraper Adapter: Douyin, RedNote, TikTok, Trends, Ozon",
    "description": "Runs a proven Store scraper under a money cap and returns one consistent format for Douyin, RedNote, TikTok, Google Trends, Wildberries, Ozon and Chewy, with field coverage, null vs zero and cost reports.",
    "version": "0.7",
    "x-build-id": "oDdEW2suHHTUALgir"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/sergeyfaraday~unified-scraper-adapter/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-sergeyfaraday-unified-scraper-adapter",
        "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/sergeyfaraday~unified-scraper-adapter/runs": {
      "post": {
        "operationId": "runs-sync-sergeyfaraday-unified-scraper-adapter",
        "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/sergeyfaraday~unified-scraper-adapter/run-sync": {
      "post": {
        "operationId": "run-sync-sergeyfaraday-unified-scraper-adapter",
        "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": [
          "module"
        ],
        "properties": {
          "module": {
            "title": "Module",
            "enum": [
              "douyin_search",
              "douyin_refresh",
              "xhs_search",
              "xhs_refresh",
              "douyin_index",
              "tiktok_search",
              "tiktok_refresh",
              "tiktok_sound",
              "tiktok_trends",
              "google_trends",
              "wb_products",
              "ozon_products",
              "ozon_reviews",
              "ozon_rank",
              "chewy_products",
              "chewy_details",
              "tiktok_explore",
              "douyin_hashtags",
              "xhs_explore",
              "google_trends_apify",
              "google_trends_scrapesage",
              "tiktok_refresh_clockworks",
              "xhs_channels",
              "chewy_reviews",
              "douyin_search_zen",
              "douyin_refresh_zen",
              "tiktok_search_apidojo"
            ],
            "type": "string",
            "description": "What to collect. Search, refresh-by-ID and discovery are separate modules; a missing mode is never replaced by another."
          },
          "queries": {
            "title": "Queries",
            "type": "array",
            "description": "Keywords (search modules, index series). RU, EN and ZH variants are separate queries; the collector returns raw matches.",
            "items": {
              "type": "string"
            }
          },
          "queryVariants": {
            "title": "Query profile variants",
            "type": "array",
            "description": "Search profile as [{\"text\": \"...\", \"lang\": \"ru|en|zh\", \"kind\": \"original|translit|synonym\"}]. Texts are added to queries; lang/kind are copied into sampling.queryVariant of matching rows."
          },
          "excludeTerms": {
            "title": "Exclusion terms",
            "type": "array",
            "description": "Whole-word (substring for Chinese) exclusions applied to title/text/name/hashtags of returned posts and products. Excluded objects are listed in the MANIFEST with the term, never silently lost.",
            "items": {
              "type": "string"
            }
          },
          "ids": {
            "title": "IDs / URLs to refresh",
            "type": "array",
            "description": "Stable ids or URLs for refresh modules (aweme ids, XHS note ids, TikTok URLs, Ozon SKUs, Chewy product URLs, WB nmIds). Ids that do not come back are reported as object_state rows.",
            "items": {
              "type": "string"
            }
          },
          "hashtags": {
            "title": "Hashtags (TikTok)",
            "type": "array",
            "description": "tiktok_search only: hashtag feeds.",
            "items": {
              "type": "string"
            }
          },
          "startUrls": {
            "title": "Start URLs (WB categories)",
            "type": "array",
            "description": "wb_products only: category or search URLs.",
            "items": {
              "type": "string"
            }
          },
          "maxResultsPerQuery": {
            "title": "Max results per query",
            "minimum": 1,
            "type": "integer",
            "description": "Per-keyword limit sent upstream. Yield below it is reported as upstream/platform limit, never as market coverage."
          },
          "sort": {
            "title": "Sort",
            "type": "string",
            "description": "Upstream sort value (douyin: general|most_liked|latest; xhs: general|popularity_descending|time_descending; tiktok: MOST_RELEVANT|MOST_LIKED|LATEST; wb: popular|newly|rate...; ozon: score|new|rating...). Echoed in every row."
          },
          "timeWindow": {
            "title": "Time window",
            "type": "string",
            "description": "douyin: unlimited|one_day|one_week|half_year; xhs: all|1d|1w|6mo; tiktok: ALL_TIME|PAST_24_HOURS|PAST_WEEK|PAST_MONTH|LAST_3_MONTHS|LAST_6_MONTHS."
          },
          "noteType": {
            "title": "XHS note type",
            "type": "string",
            "description": "xhs_search: all|video|image|live."
          },
          "topUpFromOtherSorts": {
            "title": "XHS: merge sort orders",
            "type": "boolean",
            "description": "Off by default: merging sort orders and time ranges changes what the search sample means. When on, it is recorded in sampling.",
            "default": false
          },
          "categories": {
            "title": "Categories or feeds",
            "type": "array",
            "description": "tiktok_explore: food, animals, daily_life, beauty_care, ... ; douyin_hashtags: food, knowledge, game, cartoon, music; xhs_channels: recommend, food, fashion, cosmetics, travel, fitness, household, career, love, movie_tv, gaming, video.",
            "items": {
              "type": "string"
            }
          },
          "region": {
            "title": "Region (TikTok)",
            "type": "string",
            "description": "Request region for TikTok (proxy country / Creative Center country). Request region is not audience country."
          },
          "period": {
            "title": "TikTok trends period (days)",
            "type": "string",
            "description": "7, 30 or 120."
          },
          "industryId": {
            "title": "TikTok trends industry id",
            "type": "string",
            "description": "Creative Center industry id; empty = all."
          },
          "geo": {
            "title": "Google Trends geo",
            "type": "string",
            "description": "ISO country code, default US. Use RU for the transfer check."
          },
          "timeRange": {
            "title": "Google Trends time range",
            "type": "string",
            "description": "e.g. \"today 5-y\" (weekly, about 4+ years), \"today 3-m\" (daily tail)."
          },
          "customTimeRange": {
            "title": "Google Trends custom range",
            "type": "string",
            "description": "\"YYYY-MM-DD YYYY-MM-DD\"; takes precedence over time range."
          },
          "timeRanges": {
            "title": "Google Trends windows",
            "type": "array",
            "description": "Several windows for one task, e.g. [\"today 5-y\", \"today 3-m\", \"now 7-d\"]: about 4 years weekly plus a daily and an hourly tail. Each window keeps its own native points; with rescale they are also chained onto the longest window.",
            "items": {
              "type": "string"
            }
          },
          "anchorTerm": {
            "title": "Google Trends anchor term",
            "type": "string",
            "description": "Comparison mode: queries are sent in groups of up to 4 together with this anchor term (one Google request per group), so terms from different groups can be put on one scale through the anchor. No commas inside terms. Groups are cut in list order, up to 4 terms each. Keep terms of similar volume next to each other, because Google scales a group to its highest point and a very large term rounds small ones to 0. Add new terms at the end: full groups keep their series keys. Inside a group the order does not matter."
          },
          "rescale": {
            "title": "Google Trends rescaling",
            "enum": [
              "auto",
              "overlap",
              "anchor",
              "none"
            ],
            "type": "string",
            "description": "auto: overlap when a term has 2+ windows, anchor when anchorTerm is set. Adds rescaled_series_point rows (history=derived, algorithm id + version + fit quality); native points are never changed.",
            "default": "auto"
          },
          "category": {
            "title": "Google Trends category",
            "type": "string",
            "description": "Category id, empty = all."
          },
          "searchType": {
            "title": "Google Trends search type",
            "enum": [
              "web",
              "images",
              "news",
              "youtube",
              "shopping"
            ],
            "type": "string",
            "description": "Web search uses search terms; other types are sent as explore URLs with gprop. Topic ids (/m/..., /g/...) can be passed as queries.",
            "default": "web"
          },
          "timeRangeDays": {
            "title": "Douyin Index days",
            "minimum": 7,
            "maximum": 365,
            "type": "integer",
            "description": "Daily points requested (upstream claim 7-365; real depth reported per keyword)."
          },
          "indexPlatform": {
            "title": "Douyin Index platform",
            "type": "string",
            "description": "douyin or toutiao. Different indices are never merged."
          },
          "includeRelated": {
            "title": "Include related words",
            "type": "boolean",
            "description": "Douyin Index: related-word rows (last full week).",
            "default": false
          },
          "maxRelated": {
            "title": "Max related words",
            "minimum": 1,
            "type": "integer",
            "description": "Douyin Index: related-word rows per keyword (default 20)."
          },
          "deliveryCity": {
            "title": "WB delivery city",
            "type": "string",
            "description": "Fixed delivery region for WB prices and stock (default moscow)."
          },
          "deliveryCities": {
            "title": "Ozon delivery cities",
            "type": "array",
            "description": "Ozon: fixed delivery city (first one is recorded as region).",
            "items": {
              "type": "string"
            }
          },
          "includeReviews": {
            "title": "Include reviews",
            "type": "boolean",
            "description": "Reviews are off by default (cost).",
            "default": false
          },
          "maxReviewsPerProduct": {
            "title": "Max reviews per product",
            "minimum": 1,
            "type": "integer",
            "description": "Initial load suggestion: 100 per SKU; incremental runs use reviewsSince."
          },
          "reviewsSince": {
            "title": "Reviews since (ISO date)",
            "type": "string",
            "description": "Drop reviews published before this moment (incremental collection). ISO 8601 with a zone (2026-10-01T00:00:00Z) or a bare date, read as UTC midnight; a review exactly at the boundary is kept. Any other format fails the run at the start."
          },
          "controlQuery": {
            "title": "Control query",
            "type": "string",
            "description": "A query you know has results, sent in the same upstream run. It proves the source was working, so an empty answer for your other queries counts as a proven empty result. Refused on wb_products, ozon_products and ozon_rank: they start one upstream run per query."
          },
          "language": {
            "title": "Language",
            "type": "string",
            "description": "Language of the source where the underlying actor lets you choose, for example ru. Recorded in the manifest and on rows where the source states no language of its own."
          },
          "market": {
            "title": "Market",
            "type": "string",
            "description": "Market label, for example RU. Recorded in the manifest and on rows where the source states no market of its own. To change where data comes from, use region, geo or city where the module has them."
          },
          "windowTimezone": {
            "title": "Window timezone",
            "type": "string",
            "description": "Timezone of the date window you requested, for example Asia/Shanghai. Recorded in the manifest; the underlying actors apply their own timezone."
          },
          "purgeUpstreamDataset": {
            "title": "Delete upstream dataset after reading",
            "type": "boolean",
            "description": "Delete the raw dataset of the underlying run once it is read completely, if your data retention rules require it.",
            "default": false
          },
          "upstreamMaxTotalChargeUsd": {
            "title": "Upstream money cap (USD)",
            "minimum": 0.01,
            "type": "number",
            "description": "maxTotalChargeUsd passed to the upstream run. A per-run cap does not limit the sum of many runs: keep your daily or monthly budget separately.",
            "default": 1
          },
          "upstreamBuild": {
            "title": "Upstream build",
            "type": "string",
            "description": "Pin a build number (e.g. 0.0.125) for reproducible runs. Default: the module's pinned value (\"latest\" until acceptance fixes a number)."
          },
          "upstreamRunId": {
            "title": "Attach to upstream run",
            "type": "string",
            "description": "Read an existing upstream run instead of starting one (after an adapter timeout the MANIFEST names it). No new paid start, and one upstream run per adapter run. A run started outside this actor is readable only when it is open by id; otherwise pass the two storage fields below. See the Permissions section of the README."
          },
          "upstreamDatasetId": {
            "title": "Attach: upstream dataset",
            "type": "string",
            "description": "Dataset of the upstream run. Declares READ on that dataset for this run, so rows can be delivered even when the run itself cannot be read; the status of the run then stays UNKNOWN and the result is partial. Measured under a limited run token on 2026-11-03 on one account: the grant reads the dataset and the store, the run stays 403. Run with checkPermissionsOnly first. Opening the run and its storages by id is the other measured route."
          },
          "upstreamKeyValueStoreId": {
            "title": "Attach: upstream key-value store",
            "type": "string",
            "description": "Default key-value store of the upstream run. Declares READ on it for this run, so the settings the run really used are read from its INPUT record instead of being assumed. Measured under a limited run token on 2026-11-03 on one account. Run with checkPermissionsOnly first."
          },
          "staleIsPartial": {
            "title": "Attach: old run = partial",
            "type": "boolean",
            "description": "An attached run older than 24 hours is a stale answer: rows carry data.stale, the source carries stale and the result is partial with UPSTREAM_RUN_OLD. Switch off to keep the marks and a note and let the source stay ok. observedAt always stays the time the upstream measured.",
            "default": true
          },
          "checkPermissionsOnly": {
            "title": "Only check permissions",
            "type": "boolean",
            "description": "Make each read of the scenario once (attach: run, its INPUT, dataset, key-value store; start: upstream actor lookup), start nothing and report every outcome in applied.permissions. applied.expected, expectedStatus and expectedCodes say what the same input will do without this flag, and an input it would refuse is reported here. The source is ok when the scenario can work, failed otherwise. Run it before an expensive collection.",
            "default": false
          },
          "upstreamActorId": {
            "title": "Upstream actor override",
            "type": "string",
            "description": "Use another actor with a compatible output (fallback). Mapping coverage in the manifest shows whether it fits."
          },
          "upstreamMemoryMbytes": {
            "title": "Upstream memory (MB)",
            "type": "integer",
            "description": "Override upstream memory."
          },
          "upstreamTimeoutSecs": {
            "title": "Upstream timeout (s)",
            "type": "integer",
            "description": "Override upstream timeout."
          },
          "upstreamMaxItems": {
            "title": "Upstream maxItems",
            "type": "integer",
            "description": "Pay-per-result cap on billed dataset items (does not guarantee the number of rows)."
          },
          "upstreamInputOverride": {
            "title": "Upstream input override",
            "type": "object",
            "description": "Raw fields merged into the upstream input last. Recorded in the manifest."
          },
          "echoUpstreamInput": {
            "title": "Echo upstream input in manifest",
            "type": "boolean",
            "description": "Store the exact upstream input (applied filters) in the manifest.",
            "default": true
          },
          "snapshotId": {
            "title": "Snapshot ID",
            "type": "string",
            "description": "Your id for this snapshot, one per task of one actor. Rows get recordKey = platform:type:id:snapshotId, so a repeat with the same snapshotId gives the same keys, and a new id gives a new observation. A repeat reads the source again: compare provenance.contentChecksum to see whether the values moved. Default: <actor>.<runId>."
          },
          "queryId": {
            "title": "Query profile ID",
            "type": "string",
            "description": "Your search profile id, copied into provenance.queryId."
          },
          "queryVersion": {
            "title": "Query profile version",
            "type": "string",
            "description": "Search profile version, copied into provenance.queryVersion."
          },
          "panelId": {
            "title": "Panel ID",
            "type": "string",
            "description": "Fixed panel id for refresh runs, copied into provenance.panelId."
          },
          "panelVersion": {
            "title": "Panel version",
            "type": "string",
            "description": "Panel composition version; a new composition must get a new version."
          },
          "maxItems": {
            "title": "Max records",
            "minimum": 1,
            "type": "integer",
            "description": "Hard cap on dataset rows for this run. Separate from the run money cap (maxTotalChargeUsd), which is set on the run itself."
          },
          "maxRunSeconds": {
            "title": "Soft time budget (s)",
            "minimum": 30,
            "type": "integer",
            "description": "Stop starting new units this many seconds after the run started and finish with a partial manifest. The budget belongs to the run: a restart does not renew it, and the time between workers counts."
          },
          "keepRaw": {
            "title": "Keep raw upstream item",
            "type": "boolean",
            "description": "Store the raw upstream item in `raw`. Off by default. provenance.rawChecksum is present on rows built from a raw item; it is null on a state row with no answer behind it and on derived rows.",
            "default": false
          },
          "failOnPartial": {
            "title": "Fail run on partial",
            "type": "boolean",
            "description": "By default a partial result finishes as SUCCEEDED with status=partial in the MANIFEST record. Failed and blocked always finish as FAILED.",
            "default": false
          },
          "proxyConfiguration": {
            "title": "Proxy",
            "type": "object",
            "description": "Proxy for upstream requests. Not used by the adapter itself (upstream actors manage their own proxies).",
            "default": {
              "useApifyProxy": false
            }
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}