{
  "openapi": "3.0.1",
  "info": {
    "title": "Shopify Price Tracker | $0.80/1K | Exact Variants",
    "description": "Shopify price tracker for exact sizes, colors and SKUs. Compare competitor prices and stock in the same market and currency. Keep price history, detect sales and restocks, and monitor product, collection or catalog URLs. From $0.80/1K product-check units on paid Apify plans.",
    "version": "0.2",
    "x-build-id": "UoQ7tqltdNYCR6UXG"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/x_guru~shopify-price-stock-monitor/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-x_guru-shopify-price-stock-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/x_guru~shopify-price-stock-monitor/runs": {
      "post": {
        "operationId": "runs-sync-x_guru-shopify-price-stock-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/x_guru~shopify-price-stock-monitor/run-sync": {
      "post": {
        "operationId": "run-sync-x_guru-shopify-price-stock-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",
        "properties": {
          "urls": {
            "title": "Shopify URLs",
            "maxItems": 100,
            "type": "array",
            "description": "<p>Paste <b>one public Shopify link per entry</b>. Start with one product to check compatibility and cost.</p>\n<p><b>Choose your scope:</b><br><code>/products/shoe?variant=123</code> — one exact variant.<br><code>/products/shoe</code> — all variants of that product.<br><code>/collections/shoes</code> — that category.<br><code>https://store.example</code> — the whole public catalog.</p>\n<p>Replace the example domain, handle and IDs with real values. Complete <code>?option_values=10,20</code> links also work when Shopify confirms their mapping.</p>\n<p>For SKU/size filters, use the optional section below. Filtered collection and subscription <code>selling_plan</code> links are rejected with an explanation. Maximum 100 links; whole catalogs can exceed Free limits.</p>",
            "items": {
              "type": "string"
            }
          },
          "country": {
            "title": "Market country (optional)",
            "pattern": "^[A-Z]{2}$",
            "type": "string",
            "description": "<p>Enter the country where you want to compare offers: <code>US</code>, <code>GB</code>, <code>DE</code> or <code>CA</code>. Use two uppercase letters.</p>\n<p>Leave empty to use the market returned by the store. A requested country must be confirmed by Shopify; a different country fails the check.</p>\n<p>Applies to every link. An Advanced target can override it. Use the <b>same country and currency</b> when comparing competitors.</p>"
          },
          "language": {
            "title": "Storefront language (optional)",
            "pattern": "^[A-Z]{2}(?:_[A-Z]{2})?$",
            "type": "string",
            "description": "<p>Optional storefront language: <code>EN</code>, <code>FR</code>, or another Shopify language code in uppercase.</p>\n<p>For localized links such as <code>/fr-fr/products/shoe</code>, explicitly set country or language. The path alone does not verify the market.</p>\n<p>Use the language in which the store exposes the exact option names/values you select. Applies to all links unless an Advanced target overrides it.</p>"
          },
          "expectedCurrency": {
            "title": "Expected currency (optional)",
            "pattern": "^[A-Z]{3}$",
            "type": "string",
            "description": "<p>Enter the currency you expect: <code>USD</code>, <code>GBP</code>, <code>EUR</code> or <code>CAD</code>. Use three uppercase letters.</p>\n<p>If the returned currency differs, the check fails and previous history is preserved. This field does <b>not</b> convert prices or switch markets; set <b>Market country</b> for that.</p>\n<p>Leave empty if you only need the returned currency. Applies to every link unless an Advanced target overrides it.</p>"
          },
          "mode": {
            "title": "What do you want to do?",
            "enum": [
              "monitor",
              "snapshot",
              "preview"
            ],
            "type": "string",
            "description": "<p><b>Track price and stock changes:</b> save the first successful check as a baseline. Repeat runs compare with the last successful check. Save a Task and schedule it.</p>\n<p><b>Export / discover variants:</b> return current variants without changing monitor history. To find IDs, use a plain product link, clear SKU/options selectors, and choose <b>One row per variant</b> under Results.</p>\n<p>Discovery is billed as a normal check. Copy the desired variant URL into a monitor Task afterward.</p>\n<p><b>Preview watchlist:</b> validate and show parsed URLs, exact selectors and requested markets without source requests, product/catalog charges or history writes. Variant existence and actual cost remain unverified; the Apify start fee still applies.</p>",
            "default": "monitor"
          },
          "outputMode": {
            "title": "Which results should be returned?",
            "enum": [
              "changesOnly",
              "all"
            ],
            "type": "string",
            "description": "<p><b>Changes only:</b> later monitor runs return changes, source health and check receipts. The first run also shows current variants by default. No price change means no price-alert row.</p>\n<p><b>All observations and changes:</b> include current selected variants on every successful monitor check.</p>\n<p>Export/discovery mode always returns current variants. Quiet checks still scan the source and are billed. Notifications require a separate workflow.</p>",
            "default": "changesOnly"
          },
          "watchlistCsv": {
            "title": "Import a CSV watchlist (optional)",
            "maxLength": 131072,
            "type": "string",
            "description": "<p><b>Paste CSV exported from Excel or Google Sheets.</b> Clear Shopify URLs and Advanced targets first. Up to 100 rows / 128 KiB; comma, semicolon, or tab delimiter.</p>\n<p><code>url,variantId,country,expectedCurrency,option:Size</code><br><code>https://example.com/products/shirt,123456,US,USD,M</code></p>\n<p>Required column: <code>url</code>. Optional: <code>targetId</code>, <code>variantId</code>, <code>sku</code>, <code>country</code>, <code>language</code>, <code>expectedCurrency</code>, <code>productId</code>, <code>comparisonGroup</code>, <code>role</code>, and <code>option:NAME</code> or <code>options</code> JSON.</p>\n<p>Format IDs and SKUs as text to preserve digits and leading zeros. Select <b>Preview watchlist</b> to check the parsed selections without requests to stores or history changes. Preview still has the Apify start fee.</p>"
          },
          "skus": {
            "title": "Exact SKUs (optional)",
            "maxItems": 1000,
            "uniqueItems": true,
            "type": "array",
            "description": "<p>Paste the merchant’s <b>exact SKU</b>, one per entry. Leave empty if the URL already selects the variant you need.</p>\n<p>Any listed SKU can match. Size/color options and a URL variant are additional restrictions; all must agree.</p>\n<p>Applies to every link unless an Advanced target overrides it. Different stores may use different SKUs. A complete no-match result includes reviewable variant links; the Actor does not guess a replacement.</p>",
            "items": {
              "type": "string"
            }
          },
          "options": {
            "title": "Exact size, color or pack (optional JSON)",
            "maxProperties": 3,
            "type": "object",
            "description": "<p>Enter the store’s exact option names and values, for example:<br><code>{\"Size\":\"M\",\"Color\":\"Black\"}</code></p>\n<p>For several sizes:<br><code>{\"Size\":[\"M\",\"L\"]}</code><br>This matches M or L. With a Color field too, the color must also match.</p>\n<p>Applies to every link unless an Advanced target overrides it. Leave empty for no extra option restriction. Choose <b>Export / discover variants</b> to see actual option names, SKUs and links.</p>",
            "additionalProperties": true
          },
          "observationLayout": {
            "title": "Variant export format",
            "enum": [
              "product",
              "variant"
            ],
            "type": "string",
            "description": "<p><b>Compact products:</b> group exact variants under their product. Recommended for catalogs and lower row counts. A single selected product variant stays a flat row.</p>\n<p><b>One row per variant:</b> easier to read/export as CSV and to discover exact SKU/options/URLs. Large flat exports can use more check units.</p>\n<p>Both formats retain exact variant prices and stock. Change events always stay flat.</p>",
            "default": "product"
          },
          "emitInitialSnapshot": {
            "title": "Show current variants on the first check",
            "type": "boolean",
            "description": "<p>Keep enabled to see current selected variants on the <b>first successful monitor check</b>. The Actor saves a baseline without calling existing products “new”.</p>\n<p>Disable for a quiet first baseline. Later output follows your chosen results mode. The first check is billed either way.</p>",
            "default": true
          },
          "minimumPriceChangePercent": {
            "title": "Price change alert threshold (%)",
            "pattern": "^(?:100(?:\\.0{1,4})?|[0-9]{1,2}(?:\\.[0-9]{1,4})?)$",
            "type": "string",
            "description": "<p>Enter <code>0</code> for every price move, <code>1</code> for 1%, or <code>0.5</code> for 0.5%. Do not type the % sign.</p>\n<p>Small moves accumulate from the last price alert. A threshold reduces noise; successful quiet checks still save observed history.</p>\n<p>Sold-out and restock events do not depend on this price threshold.</p>",
            "default": "0"
          },
          "emitNewLowAlerts": {
            "title": "Alert on a new observed 30-day low",
            "type": "boolean",
            "description": "<p>Enable a separate alert when the price falls below previously retained samples from the last 30 days.</p>\n<p>This is an <b>observed low</b>, not proof of the lowest price at every moment. Sample count and retained history determine coverage.</p>",
            "default": false
          },
          "includeMetadataChanges": {
            "title": "Alert on labels, SKU or URL changes",
            "type": "boolean",
            "description": "<p>Enable alerts for changes to labels, SKU, selected options or product URL. Off by default to reduce cosmetic noise.</p>\n<p>Known product IDs continue to be tracked when the merchant renames a handle.</p>",
            "default": false
          },
          "removalConfirmations": {
            "title": "Successful absence checks before a disappearance alert",
            "minimum": 2,
            "maximum": 5,
            "type": "integer",
            "description": "<p>Require <b>2–5 consecutive successful absence checks</b> before reporting disappearance. Default: 2.</p>\n<p>Failed or incomplete checks do not count. Leaving a collection, losing a variant, and becoming unavailable in a verified market have separate events.</p>",
            "default": 2
          },
          "includeBackordersInComparison": {
            "title": "Include backorders in best-price ranking",
            "type": "boolean",
            "description": "<p>Enable if backorder offers should participate in best-price ranking. Off by default because a purchasable backorder is not necessarily ready to ship.</p>\n<p>Backorders remain visible in the offers either way. This setting affects reviewed competitor groups.</p>",
            "default": false
          },
          "emitMatchCandidates": {
            "title": "Suggest equivalent variants for review",
            "type": "boolean",
            "description": "<p>Find possible cross-store matches sharing a valid GTIN barcode in the same verified country/currency.</p>\n<p>Suggestions include exact variants and copyable comparison targets. <b>Review model, pack quantity and purchase terms first.</b> Candidates are never automatically ranked.</p>",
            "default": false
          },
          "maxMatchCandidates": {
            "title": "Maximum match suggestions",
            "minimum": 1,
            "maximum": 1000,
            "type": "integer",
            "description": "<p>Maximum barcode-match suggestions to return. Default: 100.</p>\n<p>Only verified sources and checksum-valid barcodes are considered. Suggestion rows are separate from the product/change-row limit.</p>",
            "default": 100
          },
          "monitorId": {
            "title": "Separate watchlist ID (optional)",
            "pattern": "^[A-Za-z0-9_-]{1,80}$",
            "type": "string",
            "description": "<p><b>For saved Tasks, leave empty:</b> each Task keeps its own history automatically.</p>\n<p>For API/ad hoc checks, reuse a stable name such as <code>competitor-watch</code>. Give independent clients/watchlists different names.</p>\n<p>Changing this ID starts a separate history. Keep the same Task or ID for repeat checks.</p>"
          },
          "historyLimit": {
            "title": "Price history samples per variant",
            "minimum": 2,
            "maximum": 365,
            "type": "integer",
            "description": "<p>Number of successful observations retained <b>per variant</b>. Default: 90; allowed: 2–365.</p>\n<p>This is samples, not days: 90 daily checks span about 90 days; 90 hourly checks span under 4 days.</p>\n<p>30-day lows/highs use only retained samples. Inspect the sample count before interpreting them.</p>",
            "default": 90
          },
          "targets": {
            "title": "Advanced targets: exact variants and competitor groups",
            "maxItems": 100,
            "type": "array",
            "description": "<p>Use this JSON list for <b>different selections per store</b> or competitor comparisons. <b>Clear Shopify URLs first.</b></p>\n<p>Each entry needs <code>url</code>. Optional fields: <code>targetId</code>, <code>variantIds</code>, <code>skus</code>, <code>options</code>, <code>country</code>, <code>language</code> and <code>expectedCurrency</code>.</p>\n<p>For comparison, give equivalent offers the same <code>comparisonGroup</code> and select exactly one variant per target. Mark at most one offer <code>role: \"own\"</code>. README has a full copyable example.</p>"
          },
          "maxOutputRows": {
            "title": "Maximum product and change rows",
            "minimum": 1,
            "maximum": 200000,
            "type": "integer",
            "description": "<p>Maximum product/variant observations and change rows for the run. Default: 50,000.</p>\n<p>A target that would exceed the limit is reported partial; its previous history is preserved. Source statuses and comparison rows are additional.</p>",
            "default": 50000
          },
          "advanced": {
            "title": "Coverage and request limits (optional JSON)",
            "type": "object",
            "description": "<p><b>Leave empty for normal use.</b> Adjust coverage/request limits only when needed. Example:<br><code>{\"maxProducts\":500,\"maxRequests\":200,\"maxRunSeconds\":300}</code></p>\n<p>Paid defaults: 5,000 products and 50,000 variants per target; 1,000 requests and 900 seconds per run.</p>\n<p><b>Free ceilings:</b> 100 check units/run; 100 products and 3,000 variants/target; 1,000 variants/product; 80 requests and 180 seconds/run. Input cannot raise these ceilings.</p>\n<p>Incomplete checks preserve history. Set spending limits separately in Apify run options. A larger input limit does not provide more credits or memory.</p>",
            "additionalProperties": 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
                  },
                  "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}