{
  "openapi": "3.0.1",
  "info": {
    "title": "Lazada Singapore Geo-Price Scraper",
    "description": "Landed cost for Lazada Singapore: the auto-applied voucher price, shipping fee, guaranteed delivery date and stock. Every page is fetched through a real Singapore mobile line and every row carries the IP it came from. Run-over-run change detection is free.",
    "version": "0.1",
    "x-build-id": "mvvGjy9MFsCwQVtRb"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/xavierfok~lazada-sg-geoprice/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-xavierfok-lazada-sg-geoprice",
        "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/xavierfok~lazada-sg-geoprice/runs": {
      "post": {
        "operationId": "runs-sync-xavierfok-lazada-sg-geoprice",
        "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/xavierfok~lazada-sg-geoprice/run-sync": {
      "post": {
        "operationId": "run-sync-xavierfok-lazada-sg-geoprice",
        "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": {
          "searchTerms": {
            "title": "Search terms",
            "type": "array",
            "description": "One Lazada SG search keyword per line, e.g. 'wireless earbuds'.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "categoryUrls": {
            "title": "Category / search URLs (optional)",
            "type": "array",
            "description": "Full lazada.sg listing URLs to scrape instead of / in addition to searchTerms.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "maxProductsPerTerm": {
            "title": "Max products per term",
            "minimum": 1,
            "maximum": 200,
            "type": "integer",
            "description": "Maximum number of products to return per search term or category URL (1-200).",
            "default": 40
          },
          "sortBy": {
            "title": "Sort",
            "enum": [
              "relevance",
              "price_asc",
              "price_desc",
              "sold",
              "rating"
            ],
            "type": "string",
            "description": "How Lazada should sort the listing before scraping.",
            "default": "relevance"
          },
          "maxRetriesPerPage": {
            "title": "Max retries per page on block",
            "minimum": 0,
            "maximum": 6,
            "type": "integer",
            "description": "How many times to retry a page (on a fresh SG mobile IP) if Lazada blocks the first attempt.",
            "default": 3
          },
          "productUrls": {
            "title": "Product URLs (track a known SKU list)",
            "type": "array",
            "description": "Full lazada.sg product page URLs to fetch detail data for directly, with no search. Use this to monitor a fixed list of SKUs - price, shipping fee, delivery date and stock - without paying for listing pages.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "maxConcurrency": {
            "title": "Max concurrent pages",
            "minimum": 1,
            "maximum": 10,
            "type": "integer",
            "description": "How many product pages to load at once. Automatically capped at the number of Singapore mobile lines available so two pages never share one IP.",
            "default": 4
          },
          "maxPages": {
            "title": "Max listing pages per term",
            "minimum": 1,
            "maximum": 10,
            "type": "integer",
            "description": "How many listing pages (80 products each) to walk per search term. Raise this to collect more than 80 products for a term.",
            "default": 1
          },
          "enrichProductDetails": {
            "title": "Enrich with product details (shipping fee, delivery date, seller trust, GTIN)",
            "type": "boolean",
            "description": "Open each product page from a real Singapore mobile IP to capture shipping fee, guaranteed delivery date, seller ratings, barcode/GTIN and variants. Slower, and billed per detail record.",
            "default": false
          },
          "maxDetailsPerTerm": {
            "title": "Max enriched products per term",
            "minimum": 1,
            "maximum": 50,
            "type": "integer",
            "description": "How many products per search term to enrich with full product-detail data.",
            "default": 5
          },
          "includeListingMeta": {
            "title": "Include listing metadata record",
            "type": "boolean",
            "description": "Emit one extra record per term with the total result count and the brand, service and shipped-from facets Lazada shows for that keyword.",
            "default": true
          },
          "captureScreenshot": {
            "title": "Attach proof screenshot",
            "type": "boolean",
            "description": "Save a PNG of the Singapore mobile results grid for each keyword, as a shareable artifact. OFF by default: every product row already carries egress_ip and egress_geo proving Singapore egress, so the image adds no analytical value while costing storage plus up to ~20s of compute per keyword waiting for the grid and its thumbnails to render. Turn it on when you need the visual proof itself.",
            "default": false
          },
          "detectChanges": {
            "title": "Detect changes since the last run",
            "type": "boolean",
            "description": "Compare this run against the previous run of the same search term and emit 'change' records: price_drop / price_rise, voucher_price_drop / voucher_price_rise, out_of_stock / back_in_stock, new_listing and delisted - each with before, after, delta and delta_pct. The first run of a term only stores a baseline and reports nothing. Change records are FREE: they are derived from data you already paid for.",
            "default": false
          },
          "changeStateStore": {
            "title": "Named store holding the change baseline",
            "type": "string",
            "description": "Name of the key-value store that keeps the previous run's baseline. Use a different name to track the same keywords as independent series. Only used when 'Detect changes since the last run' is on.",
            "default": "lazada-sg-state"
          },
          "reportResultChurn": {
            "title": "Also report products entering/leaving the results",
            "type": "boolean",
            "description": "Add 'entered_results' and 'left_results' change records. OFF by default on purpose: Lazada rotates and personalises search results, so two runs of the same keyword minutes apart can share only about half their results - in one measured pair, 22 of 40. Those rows would bury the price and stock moves that are reliable. Turn this on when you fixed the item set yourself via 'productUrls', where absence really does mean the product went away.",
            "default": 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
                  }
                }
              },
              "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}