{
  "openapi": "3.0.1",
  "info": {
    "title": "GovDeals Scraper — Government Surplus Auction Lots",
    "description": "Government-surplus auction lots from GovDeals: title, seller agency, category, current bid, bid count, bid increment, buyer's premium, buy-now price, closing time, quantity, condition, VIN, meter, city/state and photos. Paste a GovDeals URL, or filter by state, category, keyword or seller.",
    "version": "0.1",
    "x-build-id": "BLz5DDY5gLrTGauat"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/scrapersdelight~govdeals-auction-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-scrapersdelight-govdeals-auction-scraper",
        "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/scrapersdelight~govdeals-auction-scraper/runs": {
      "post": {
        "operationId": "runs-sync-scrapersdelight-govdeals-auction-scraper",
        "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/scrapersdelight~govdeals-auction-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-scrapersdelight-govdeals-auction-scraper",
        "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": [
          "searchType"
        ],
        "properties": {
          "startUrls": {
            "title": "Paste GovDeals URLs (search results or single lots)",
            "type": "array",
            "description": "The fastest way in: go to govdeals.com, apply whatever filters you like, then copy the URL out of your address bar and paste it here. Search pages (https://www.govdeals.com/search?kWord=forklift), category, state and seller searches, and single lot pages (https://www.govdeals.com/asset/13230/21430) all work, and you can mix them in one list. If this is not empty it WINS and the picker below is ignored. Read from the URL: keyword, category, state, seller account and sale type. Not read: the URL's own price and sort parameters — set those with Minimum/Maximum bid and Sort, which apply to every scope in the run. Leave empty to use the picker below.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "searchType": {
            "title": "…or pick a source",
            "enum": [
              "all",
              "state",
              "category",
              "keyword",
              "seller",
              "lotUrls"
            ],
            "type": "string",
            "description": "Used only when 'Paste GovDeals URLs' above is empty. 'All open lots' walks GovDeals' whole live catalogue (26,193 open lots measured 2026-08-12; every run logs the live count). 'By state' runs one server-side query per state. 'By category' expands a GovDeals category (code or name) to every child code, which matters because a lot only carries its own leaf code. 'By keyword' runs the site's own search. 'By seller' takes GovDeals account ids. 'Specific lot URLs' resolves lots you paste into the Lot URLs field.",
            "default": "all"
          },
          "states": {
            "title": "States (source = By state)",
            "type": "array",
            "description": "Two-letter codes or full names — \"TX\", \"FL\", \"California\", \"ON\". GovDeals filters state SERVER-SIDE but accepts only one state per query, so each entry costs one extra request per page of results. Canadian provinces work too (GovDeals Canada lots share the catalogue). Ignored unless the source above is 'By state'.",
            "default": [
              "TX"
            ],
            "items": {
              "type": "string"
            }
          },
          "categories": {
            "title": "Categories (source = By category)",
            "type": "array",
            "description": "GovDeals category codes or names, e.g. \"36\" or \"Heavy Equipment and Construction\", \"Material Handling Equipment\", \"Jewelry\", \"Buses\". Names are matched case-insensitively against GovDeals' live category menu and EXPANDED to every child code — measured: \"Material Handling Equipment\" + 36 resolves to 39 codes. Filtering on a family code alone silently misses almost everything (code 206 \"Clothing, Jewelry, and Accessories\" returns 85 lots; its child 56 \"Jewelry\" returns 1,096). If a name matches nothing the run logs it and skips it. Ignored unless the source above is 'By category'.",
            "default": [
              "Heavy Equipment and Construction"
            ],
            "items": {
              "type": "string"
            }
          },
          "keywords": {
            "title": "Keywords (source = By keyword)",
            "type": "array",
            "description": "Typed exactly as you would into the GovDeals search box, e.g. \"forklift\", \"dump truck\", \"generator\". Each term is walked page by page until the lot cap is hit, so two terms take roughly twice as long as one. Ignored unless the source above is 'By keyword'.",
            "default": [
              "forklift"
            ],
            "items": {
              "type": "string"
            }
          },
          "sellerAccountIds": {
            "title": "Seller account ids (source = By seller)",
            "type": "array",
            "description": "Numeric GovDeals account ids — the second number in a lot URL (https://www.govdeals.com/asset/<assetId>/<accountId>) and the account_id field in this Actor's own output. All ids ride in ONE server-side query, so ten sellers cost the same as one. Ignored unless the source above is 'By seller'.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "lotUrls": {
            "title": "Lot URLs (source = Specific lot URLs)",
            "type": "array",
            "description": "Full GovDeals lot URLs, e.g. https://www.govdeals.com/asset/13230/21430 . The legacy ?itemid=…&acctid=… form and a bare \"assetId/accountId\" pair are accepted too. Each lot is resolved straight off the asset endpoint — one request per lot, no search walk, live bid included — which makes this the cheapest way to re-price a watchlist. You can also just paste these into 'Paste GovDeals URLs' at the top and ignore the picker entirely.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "sellerType": {
            "title": "Seller type",
            "enum": [
              "any",
              "1",
              "2"
            ],
            "type": "string",
            "description": "GovDeals lists both public agencies and the commercial remarketers that resell for them. Filtered SERVER-SIDE, so narrowing here costs you nothing and does not slow the run down.",
            "default": "any"
          },
          "saleType": {
            "title": "Sale type",
            "enum": [
              "any",
              "3",
              "4",
              "5",
              "1"
            ],
            "type": "string",
            "description": "Most GovDeals lots are timed online auctions; the rest are fixed-price or offer formats. Filtered SERVER-SIDE. Note that buy_now_price is only ever set on Buy Now / strike-price lots — measured at 6% of a default 200-lot run and 20.5% of another, purely because of the sale-format mix in the scope.",
            "default": "any"
          },
          "timeWindow": {
            "title": "Time window",
            "enum": [
              "any",
              "closingToday",
              "newListings"
            ],
            "type": "string",
            "description": "Narrow to lots closing today (bargain-hunting / sniping) or to lots listed since the last sweep (new-inventory monitoring). Filtered SERVER-SIDE. Leave on 'Any time' for a scheduled monitor — Monitor mode below already tracks what is new, and stacking both narrows you twice.",
            "default": "any"
          },
          "minBid": {
            "title": "Minimum current bid (USD)",
            "minimum": 0,
            "type": "integer",
            "description": "Drop lots whose current bid is below this. Applied client-side AFTER the search, so it does not reduce what the Actor fetches — it keeps your dataset clean, and rows it removes are never charged to you. Lots with no bid yet are always kept, because a $0 lot is the one you wanted to see."
          },
          "maxBid": {
            "title": "Maximum current bid (USD)",
            "minimum": 0,
            "type": "integer",
            "description": "Drop lots whose current bid is above this. Applied client-side AFTER the search. Lots with no bid yet are always kept. Rows removed here are never charged to you."
          },
          "includeClosedLots": {
            "title": "Include lots whose bidding has already closed",
            "type": "boolean",
            "description": "OFF (default) drops lots whose closing time has passed BEFORE they are enriched, so you never pay for a lot you cannot bid on. This matters more than it sounds: GovDeals keeps just-closed lots in its open search index for a while AND stops serving their detail record, and on a real run at 23:00:18Z all 50 closing-soonest rows had closed at 23:00:00Z. Turn ON to build a sold-comps history — but expect null quantity/condition/gallery on those rows, because GovDeals no longer publishes them.",
            "default": false
          },
          "sortBy": {
            "title": "Sort",
            "enum": [
              "closing",
              "newest",
              "bidHigh",
              "bidLow",
              "bestMatch"
            ],
            "type": "string",
            "description": "Server-side sort. 'Closing soonest' (the default) is what you want for sniping and for a monitor; 'Newest listings' for fresh-inventory sweeps; 'Highest bid' to skim the big-ticket lots first. This decides WHICH lots a capped run gets, so it matters most when Max lots is small relative to the scope.",
            "default": "closing"
          },
          "fetchDetails": {
            "title": "Open each lot for full detail + live bid",
            "type": "boolean",
            "description": "ON (default): two extra requests per lot add quantity, condition, VIN, meter reading, seller contact, inspection/payment/pickup terms and the FULL photo gallery, plus the live bid box — bid increment, buy-now price, BUYER'S PREMIUM %, view/visitor/watcher counts and reserve state. Measured on 200 open lots: 200/200 enriched. OFF: search rows only — 1,000 lots in 29 seconds and 12 HTTP calls instead of ~103 calls for 50, and you still get title, category, current bid, bid count, closing time, seller, location and one photo. The price per lot is the SAME either way, so this buys you speed, not money.",
            "default": true
          },
          "maxLots": {
            "title": "Max lots per run",
            "minimum": 0,
            "type": "integer",
            "description": "Hard cap on lots returned this run — and therefore your cost cap, since you are billed per lot returned. Duplicates and lots removed by the closed/bid filters are dropped before billing and never count against it. Set 0 for no cap; the full live catalogue was 26,193 lots on 2026-08-12, which at $0.003/lot is about $79.",
            "default": 50
          },
          "monitorMode": {
            "title": "Monitor mode — only lots you have not seen before",
            "type": "boolean",
            "description": "Remembers every lot id it has already returned FOR THIS EXACT SCOPE in a named key-value store, so a scheduled run outputs — and bills — only genuinely new listings. Verified: run 1 returned 12 new of 12, run 2 returned 0 new of 12, and a different keyword got its own independent seen-set. Ended lots age out of the memory a day after they close. This is the one mode where a zero-row run is legitimate and does not throw.",
            "default": false
          },
          "alertOnNewLot": {
            "title": "Alert on new lot",
            "type": "boolean",
            "description": "Send a webhook / Slack / email alert for every newly seen lot. Used only when Monitor mode is on AND at least one destination below is set; otherwise it does nothing.",
            "default": true
          },
          "alertOnBidChange": {
            "title": "Alert when a watched lot's bid moves",
            "type": "boolean",
            "description": "Alert when the current bid changes on a lot listed in Watchlist lot ids. Used only when Monitor mode is on. Needs Open each lot ON to see a live bid.",
            "default": false
          },
          "watchlistLotIds": {
            "title": "Watchlist lot ids",
            "type": "array",
            "description": "Lot ids in this Actor's own \"<assetId>-<accountId>\" form, e.g. \"13230-21430\" — it is the lot_id field of any row this Actor has already returned. Used only by 'Alert when a watched lot's bid moves'.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "webhookUrl": {
            "title": "Webhook URL",
            "type": "string",
            "description": "Optional. Every alert is POSTed here as JSON — wire it into Zapier, Make, n8n, Google Sheets or your own endpoint. A failed POST is logged as a warning and never fails the run."
          },
          "slackWebhookUrl": {
            "title": "Slack incoming-webhook URL",
            "type": "string",
            "description": "Optional. Alerts are posted as a Slack card with the lot photo, current bid, location, seller and closing time."
          },
          "emailRecipients": {
            "title": "Email recipients",
            "type": "array",
            "description": "Optional. Email addresses to send the new-lot digest to (sent through the apify/send-mail Actor, which runs on your account).",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "proxyConfiguration": {
            "title": "Proxy",
            "type": "object",
            "description": "GovDeals is NOT walled for this route. Measured THROUGH the Apify proxy: 20 contiguous search pages on plain Apify DATACENTER returned 20/20, and 20 live bid boxes returned 20/20 — so the default is the cheap datacenter rung and residential bandwidth is not needed. Turning residential on here will cost you more and measurably buy you nothing.",
            "default": {
              "useApifyProxy": true
            }
          },
          "requestConcurrency": {
            "title": "Request concurrency",
            "minimum": 1,
            "maximum": 5,
            "type": "integer",
            "description": "Parallel requests for the detail and bid-box fetches. Kept low on purpose to stay polite to GovDeals, whose robots.txt asks for a 5-second crawl delay; values above 5 are clamped to 5.",
            "default": 4
          },
          "diagnose": {
            "title": "Diagnostic mode",
            "type": "boolean",
            "description": "Fetch two pages plus one lot, dump the raw GovDeals JSON to the key-value store (DEBUG_SEARCH_ROWS / DEBUG_DETAIL / DEBUG_BIDBOX), report whether pagination overlapped, then exit WITHOUT writing dataset rows — so it never bills you. Use this first if a run looks wrong, and paste the output into an issue.",
            "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}