{
  "openapi": "3.0.1",
  "info": {
    "title": "UK Public Sector Tenders — Find a Tender & Contracts Finder",
    "description": "UK public-sector tenders and contract awards from BOTH official portals — Find a Tender (above threshold) and Contracts Finder (sub threshold) — in one deduplicated feed. Filter by CPV, value, keyword, region, deadline. Buyer email, phone, address. First 25 records per run FREE, then $0.003/result.",
    "version": "0.1",
    "x-build-id": "5sm59LZ6OaE14dxXG"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/fetchsmith~uk-find-a-tender-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-fetchsmith-uk-find-a-tender-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/fetchsmith~uk-find-a-tender-scraper/runs": {
      "post": {
        "operationId": "runs-sync-fetchsmith-uk-find-a-tender-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/fetchsmith~uk-find-a-tender-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-fetchsmith-uk-find-a-tender-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",
        "properties": {
          "sources": {
            "title": "Portals",
            "type": "array",
            "description": "Which official UK procurement portals to search. 'cf' = Contracts Finder (sub-threshold contracts, the high-volume feed: ~18 tender-stage and 100+ award notices a day). 'fts' = Find a Tender (above-threshold notices only, a thin feed of ~7-8 tender-stage notices a day). Both are searched by default and merged into one deduplicated result set with a 'source' field on every row.",
            "items": {
              "type": "string",
              "enum": [
                "fts",
                "cf"
              ],
              "enumTitles": [
                "Find a Tender (above threshold)",
                "Contracts Finder (sub threshold)"
              ]
            },
            "default": [
              "fts",
              "cf"
            ]
          },
          "stages": {
            "title": "Stages",
            "type": "array",
            "description": "Which notice stages to return. 'tender' = live/closed opportunities to bid on (the default, and what most buyers want). 'award' = contract award notices, including the winning supplier. 'planning' = early pipeline notices. 'contract' = the contract was signed. 'implementation' = performance/delivery-stage updates on an already-awarded contract. Leave as ['tender'] unless you want awards.",
            "items": {
              "type": "string",
              "enum": [
                "planning",
                "tender",
                "award",
                "contract",
                "implementation"
              ],
              "enumTitles": [
                "Planning (pipeline)",
                "Tender (opportunities)",
                "Award (winners)",
                "Contract (signed)",
                "Implementation (delivery updates)"
              ]
            },
            "default": [
              "tender"
            ]
          },
          "updatedWithinDays": {
            "title": "Updated within (days)",
            "minimum": 1,
            "maximum": 365,
            "type": "integer",
            "description": "Only return notices published or updated in the last N days. Notices come back newest first.",
            "default": 7
          },
          "dateFrom": {
            "title": "Published/updated from (absolute date)",
            "type": "string",
            "description": "Optional absolute start of the date window, e.g. 2026-08-01 (or a full ISO datetime). Setting either this or 'dateTo' OVERRIDES 'Updated within (days)'. Enforced server-side by both portals, so it is a real filter and does not waste results."
          },
          "dateTo": {
            "title": "Published/updated to (absolute date)",
            "type": "string",
            "description": "Optional absolute end of the date window, e.g. 2026-08-31 (or a full ISO datetime). Defaults to the run start time. Note a bare date means midnight, so 2026-08-31 excludes the 31st itself — use 2026-09-01 to include it."
          },
          "cpvCodes": {
            "title": "CPV codes",
            "type": "array",
            "description": "Common Procurement Vocabulary codes to filter by, always exactly 8 digits, e.g. 72000000 (IT services), 45000000 (construction), 80000000 (education). A code matches its whole CPV subtree and nothing outside it: 72000000 matches every 72xxxxxx code, 72267000 also matches its children 72267100/72267200, and 80000000 matches 80xxxxxx only — never 85xxxxxx health. Matched against every CPV on the notice (headline plus all lot and item codes), not just the headline one, so a notice qualifies if any one of its codes is in the subtree. A value that is not 8 digits is excluded from matching (never widens or narrows the filter unexpectedly) and logs a warning naming it -- a numeric value with the wrong digit count is not simply ignored, it is deliberately kept out because it could otherwise collapse into a real, much wider CPV prefix by accident. Leave empty for all.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "searchQuery": {
            "title": "Search text",
            "type": "string",
            "description": "Free-text filter. Every word must appear somewhere in the title, description, buyer name, CPV description or lot titles (case-insensitive, Unicode-normalized so accented words match regardless of composed/decomposed input form). E.g. \"software\" or \"nhs cleaning\"."
          },
          "keywordsAny": {
            "title": "Any of these phrases",
            "type": "array",
            "description": "OR-matched alternative to 'Search text': a notice matches if it contains ANY of these phrases (each phrase can be multiple words, matched as a whole substring) in its title, description, buyer name, CPV description or lot titles. Use this to cover several unrelated opportunity types in one run, e.g. [\"software\", \"IT support\", \"cyber\"] — 'Search text' can only express AND-of-words within a single phrase, so it can't do this. Combine both if you want ANY-of-these-phrases AND all-of-those-words at once.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "regions": {
            "title": "Delivery region contains",
            "type": "array",
            "description": "OR-matched filter on where the contract is delivered, e.g. [\"London\", \"Scotland\", \"North West\"]. Matches against the notice's own delivery region/location text (case-insensitive substring). Leave empty for all regions. Notices with no delivery-region data are excluded when this is set.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "buyerName": {
            "title": "Buyer name contains",
            "type": "string",
            "description": "Case-insensitive substring match against the buying authority's name only, e.g. 'NHS', 'Ministry of Defence', 'Kent County Council'. Narrower than 'Search text', which also matches the title, description, CPV description and lot titles — so use this when you want a buyer's own notices and not every notice that merely mentions them."
          },
          "minValueGbp": {
            "title": "Minimum contract value (GBP)",
            "type": "integer",
            "description": "Only return notices whose published contract value is at least this much. Notices without a published value are excluded when this is set."
          },
          "maxValueGbp": {
            "title": "Maximum contract value (GBP)",
            "type": "integer",
            "description": "Only return notices whose published contract value is at most this much. Notices without a published value are excluded when this is set."
          },
          "openOnly": {
            "title": "Only still-open tenders",
            "type": "boolean",
            "description": "Only return notices whose submission deadline is still in the future. Use with stages = ['tender'] — award notices have no future deadline and will all be filtered out.",
            "default": false
          },
          "maxResults": {
            "title": "Max results",
            "minimum": 1,
            "maximum": 5000,
            "type": "integer",
            "description": "Stop after this many notices.",
            "default": 100
          },
          "maxPagesScanned": {
            "title": "Max API pages to scan",
            "minimum": 1,
            "maximum": 500,
            "type": "integer",
            "description": "Safety cap on how many 100-notice API pages to read while looking for matches. Raise it if you use a narrow filter over a long date range.",
            "default": 50
          },
          "includeRawOcds": {
            "title": "Include raw OCDS release",
            "type": "boolean",
            "description": "Attach the complete, unmodified OCDS 1.1 release JSON for each notice as a 'rawOcds' field, in addition to the normalized fields. Off by default — turn it on if your pipeline wants the full original government data (nested parties, all documents, amendment history) rather than just the flattened columns.",
            "default": false
          },
          "watchLabel": {
            "title": "Watch mode: label",
            "type": "string",
            "description": "Set a name (e.g. \"my-cpv-watch\") to turn this run into an alert: the FIRST run with a given label + filter combination records every currently-matching notice and returns nothing (you pay nothing). Every run after that returns and charges only for notices NOT already delivered under that label — ideal for a scheduled run that should only tell you what's new. Leave empty for a normal one-off search."
          },
          "webhookUrl": {
            "title": "Webhook URL (notify on completion)",
            "type": "string",
            "description": "Optional. An http(s) URL to POST a small JSON summary to when the run finishes — notices pushed, releases scanned, how many were filtered out, pages scanned, the watch-label new count if Watch label is set, and the run's dataset ID so you can fetch the results. A convenience for callers who want a completion ping without setting up an Apify platform webhook (which needs separate Console/API configuration per Task, not per run). Best-effort: a failed or slow webhook is logged as a warning and never fails the run or affects charging — it fires after every notice has already been pushed and charged. Leave empty to skip."
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}