{
  "openapi": "3.0.1",
  "info": {
    "title": "Restaurant Menu Item-Price History",
    "description": "Track restaurant menu item prices over time. Records each dish's price from public schema.org menu data into an append-only price-history ledger, and computes a menu-price inflation index — the price history a one-shot scraper can't reconstruct.",
    "version": "0.1",
    "x-build-id": "5ndYbHGTByLUq4bkb"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/coily_ackee~menu-price-history/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-coily_ackee-menu-price-history",
        "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/coily_ackee~menu-price-history/runs": {
      "post": {
        "operationId": "runs-sync-coily_ackee-menu-price-history",
        "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/coily_ackee~menu-price-history/run-sync": {
      "post": {
        "operationId": "run-sync-coily_ackee-menu-price-history",
        "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": {
          "source": {
            "title": "Source adapter",
            "enum": [
              "jsonld",
              "fixture"
            ],
            "type": "string",
            "description": "Which extractor to run. 'jsonld' = read schema.org Menu JSON-LD from each restaurant's own public menu page (the real source). 'fixture' = NO NETWORK (canned payloads, for a safe offline test).",
            "default": "jsonld"
          },
          "seeds": {
            "title": "Restaurant seed list",
            "type": "array",
            "description": "List of restaurants to track. Each entry: { restaurant_id, url (public menu page with schema.org Menu JSON-LD), cuisine?, city? }. Replace these examples with your own. Use tolerant public menu pages only; no login, no PII.",
            "default": [
              {
                "restaurant_id": "los-tacos-no1-nyc",
                "url": "https://www.lostacos1.com/menus/",
                "cuisine": "Mexican",
                "city": "New York"
              },
              {
                "restaurant_id": "tableau-french-quarter-nola",
                "url": "https://www.tableaufrenchquarter.com/menu/dinner-menu/",
                "cuisine": "Creole-French",
                "city": "New Orleans"
              },
              {
                "restaurant_id": "residents-dc",
                "url": "https://www.residentsdc.com/menu/dinner-menu/",
                "cuisine": "New American",
                "city": "Washington, DC"
              },
              {
                "restaurant_id": "coral-tree-cafe-brentwood",
                "url": "https://www.coraltreecafe.com/menu/",
                "cuisine": "American",
                "city": "Brentwood, CA"
              }
            ]
          },
          "ledgerPath": {
            "title": "History ledger path",
            "type": "string",
            "description": "Path to the append-only JSONL history ledger. NEVER deleted; re-runs are idempotent. On Apify this is a per-run working file (the container FS is wiped between runs); the ledger is durably persisted across runs via the named key-value store below.",
            "default": "./data/price-history.jsonl"
          },
          "ledgerStoreName": {
            "title": "History store name (persists across runs)",
            "type": "string",
            "description": "Name of the NAMED Apify key-value store that durably holds the accumulated history ledger across runs. On Apify the container filesystem is wiped between runs, so the ledger is hydrated from this named store at run start and saved back after append (a named store persists across runs; the default store does not reliably). The accumulating history is the product's value. Ignored when run locally.",
            "default": "n1-price-history"
          },
          "requestDelayMs": {
            "title": "Delay between restaurants (ms)",
            "minimum": 0,
            "type": "integer",
            "description": "Politeness delay between HTTP requests. Ignored for the offline fixture source.",
            "default": 2000
          },
          "userAgent": {
            "title": "User-Agent",
            "type": "string",
            "description": "A normal, descriptive User-Agent. No spoofing of a real browser identity."
          },
          "maxRestaurantsPerRun": {
            "title": "Max restaurants per run",
            "minimum": 1,
            "type": "integer",
            "description": "Hard cap on seed entries processed per run.",
            "default": 25
          },
          "pushToDataset": {
            "title": "Push rows to Apify dataset",
            "type": "boolean",
            "description": "Default ON. Extracted per-item price observations are written to the Actor dataset (this is what pay-per-result bills on). Turn OFF to run without producing dataset output.",
            "default": true
          },
          "emitQueries": {
            "title": "Emit history/index queries",
            "type": "boolean",
            "description": "Default ON. The run also computes a menu-price index and a sample price history and saves them to the key-value store.",
            "default": true
          },
          "allowZeroPrice": {
            "title": "Allow $0 (free) prices",
            "type": "boolean",
            "description": "Default OFF. When OFF, a price of 0 (including a non-numeric value like 'free' that would strip to empty) is REJECTED so it never enters the never-delete ledger as a false $0.00 / -100% drop. Turn ON only when the source genuinely lists free items.",
            "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}