{
  "openapi": "3.0.1",
  "info": {
    "title": "UK Tenders Monitor - Contracts Finder & Find a Tender Alerts",
    "description": "Monitor new UK public-sector tenders from the official Contracts Finder and Find a Tender APIs. Filter by keyword, CPV code, value, region and buyer, get only new notices on a schedule, and alert Slack or Discord for $0.004/notice.",
    "version": "0.1",
    "x-build-id": "Femq41GsO1gweJCF7"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/lukehunter~uk-tenders-monitor/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-lukehunter-uk-tenders-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/lukehunter~uk-tenders-monitor/runs": {
      "post": {
        "operationId": "runs-sync-lukehunter-uk-tenders-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/lukehunter~uk-tenders-monitor/run-sync": {
      "post": {
        "operationId": "run-sync-lukehunter-uk-tenders-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": {
          "keywords": {
            "title": "Keywords",
            "type": "array",
            "description": "Keep notices whose title or description contains at least one of these words or phrases, case-insensitive. Example: [\"software\", \"cloud hosting\", \"cyber security\"]. Leave empty to keep every notice that passes the other filters.",
            "items": {
              "type": "string"
            }
          },
          "cpvCodes": {
            "title": "CPV codes (prefix match)",
            "type": "array",
            "description": "Keep notices with at least one CPV code starting with these digits. 2 to 8 digits, optional check digit, e.g. 72 (all IT services), 72200000-7 or 45 (construction). An invalid code stops the run with an error. Leave empty for any category.",
            "items": {
              "type": "string"
            }
          },
          "minValue": {
            "title": "Minimum value (GBP)",
            "minimum": 0,
            "type": "integer",
            "description": "Keep notices whose published value reaches at least this many pounds, e.g. 100000. Notices that publish no value, or one in another currency, are left out while this or Maximum value is set. Leave empty for no lower bound."
          },
          "maxValue": {
            "title": "Maximum value (GBP)",
            "minimum": 0,
            "type": "integer",
            "description": "Keep notices whose published value starts at or below this many pounds, e.g. 1000000. Notices that publish no value, or one in another currency, are left out while this or Minimum value is set. Leave empty for no upper bound."
          },
          "regions": {
            "title": "Regions / locations",
            "type": "array",
            "description": "Keep notices whose buyer address or delivery location contains one of these texts, case-insensitive. Example: [\"London\", \"Yorkshire\", \"Scotland\"]. Buyers publish regions in different forms (a name or a NUTS code such as UKI), so try both. Leave empty for the whole UK.",
            "items": {
              "type": "string"
            }
          },
          "buyerContains": {
            "title": "Buyer name contains",
            "type": "string",
            "description": "Keep notices whose buyer (the public body that issued it) has this text in its name, case-insensitive. Example: NHS, Ministry of Defence, Transport for London. Leave empty for any buyer."
          },
          "noticeTypes": {
            "title": "Notice types",
            "type": "array",
            "description": "Which notices to return, e.g. [\"tender\", \"award\"]. tender = live opportunities you can bid for (alias opportunity); award = awarded contracts; planning = prior information and pipeline notices. Default is tender only.",
            "items": {
              "type": "string",
              "enum": [
                "tender",
                "opportunity",
                "award",
                "planning",
                "prior-information"
              ]
            },
            "default": [
              "tender"
            ]
          },
          "sources": {
            "title": "Sources",
            "type": "array",
            "description": "Which official register to read, e.g. [\"contracts-finder\"]. contracts-finder covers England and UK-wide notices; find-a-tender covers higher-value procurement under the Procurement Act. Default reads both and removes duplicates.",
            "items": {
              "type": "string",
              "enum": [
                "contracts-finder",
                "find-a-tender"
              ]
            },
            "default": [
              "contracts-finder",
              "find-a-tender"
            ]
          },
          "publishedWithinDays": {
            "title": "Published within days",
            "minimum": 1,
            "maximum": 90,
            "type": "integer",
            "description": "Only notices published in the last N days, 1 to 90, e.g. 7 for the last week. Ignored when Published from is set. Longer windows read more pages from the APIs and take longer.",
            "default": 7
          },
          "publishedFrom": {
            "title": "Published from (optional date range)",
            "type": "string",
            "description": "First day of an explicit range, written YYYY-MM-DD, e.g. 2026-09-01. Use with Published to (defaults to today). The range may not exceed 90 days; a longer one stops the run with an error. Overrides Published within days."
          },
          "publishedTo": {
            "title": "Published to (optional date range)",
            "type": "string",
            "description": "Last day of an explicit range, written YYYY-MM-DD, e.g. 2026-09-30. Needs Published from. Leave empty to run up to today. The whole range may not exceed 90 days."
          },
          "maxItems": {
            "title": "Maximum notices",
            "minimum": 1,
            "maximum": 1000,
            "type": "integer",
            "description": "Hard cap on delivered notices, newest first, 1 to 1000, e.g. 50. At $0.004 per delivered notice this caps the result charge for the run (50 notices = $0.20). Notices beyond the cap are not charged.",
            "default": 50
          },
          "onlyNewSinceLastRun": {
            "title": "Alerts: only new since last run",
            "type": "boolean",
            "description": "Deliver and charge only notices not delivered before for this same set of filters, e.g. on a daily Schedule. The first run creates the baseline and delivers what currently matches. Pair with a Discord, Slack or Telegram destination below.",
            "default": false
          },
          "stateStoreName": {
            "title": "Alerts: state store name",
            "type": "string",
            "description": "Named key-value store that remembers delivered notices between runs, used only when alerts are on. Example: my-it-tenders. Use a different name to keep separate histories. Letters, numbers and hyphens only.",
            "default": "uk-tenders-monitor-seen-notices"
          },
          "discordWebhookUrl": {
            "title": "Discord webhook URL",
            "type": "string",
            "description": "Post results to a Discord channel. In Discord: Server Settings -> Integrations -> Webhooks -> New Webhook -> choose the channel -> Copy Webhook URL. Example: https://discord.com/api/webhooks/<id>/<token>. Leave empty to skip Discord."
          },
          "telegramBotToken": {
            "title": "Telegram bot token",
            "type": "string",
            "description": "Post results to Telegram. Create a bot by chatting with @BotFather on Telegram (send /newbot) and paste the token it gives you, e.g. 123456789:AA.... Needs \"Telegram chat ID\" below. Leave empty to skip Telegram."
          },
          "telegramChatId": {
            "title": "Telegram chat ID",
            "type": "string",
            "description": "Where the bot should post: a numeric chat id (e.g. 123456789, or -1001234567890 for a group or channel) or a public @channelusername. The bot must be added to that chat or channel first (as an administrator for a channel), and for a private chat you must press Start on the bot. Needs \"Telegram bot token\" above."
          },
          "slackWebhookUrl": {
            "title": "Slack webhook URL",
            "type": "string",
            "description": "Post results to a Slack channel (Block Kit cards, up to 10 per message). Create an incoming webhook at api.slack.com/apps -> Create New App -> Incoming Webhooks -> Add New Webhook to Workspace. Example: https://hooks.slack.com/services/T000/B000/XXXX. Leave empty to skip Slack."
          },
          "slackCompatibleWebhookUrl": {
            "title": "Slack-compatible webhook URL (Mattermost, Rocket.Chat)",
            "type": "string",
            "description": "Post results to a Mattermost or Rocket.Chat incoming webhook, which accept Slack-style webhook payloads. Must be a public https:// address, e.g. https://chat.example.com/hooks/abc123 (no localhost, private IP or .local/.internal hosts). These apps do not render Slack Block Kit, so they get a plain Markdown list. For real Slack use \"Slack webhook URL\" above. Leave empty to skip."
          },
          "teamsWebhookUrl": {
            "title": "Microsoft Teams webhook URL (Workflows)",
            "type": "string",
            "description": "Post results to a Teams channel as an Adaptive Card. In Teams: channel -> ... -> Workflows -> \"Post to a channel when a webhook request is received\" -> copy the URL. The host must end in .logic.azure.com or .powerplatform.com, e.g. https://prod-12.westeurope.logic.azure.com/workflows/... The retired Office 365 connector webhooks are not supported. Leave empty to skip Teams."
          },
          "googleChatWebhookUrl": {
            "title": "Google Chat webhook URL",
            "type": "string",
            "description": "Post results to a Google Chat space. In the space: Apps & integrations -> Webhooks -> Add webhook -> copy the URL. Example: https://chat.googleapis.com/v1/spaces/<space>/messages?key=...&token=.... Leave empty to skip Google Chat."
          },
          "ntfyTopic": {
            "title": "ntfy topic",
            "type": "string",
            "description": "Get a phone push with no account via ntfy (ntfy.sh). Install the ntfy app, subscribe to a topic name, and enter the same name here. Anyone who knows the topic can read it, so pick a long, unguessable name (letters, numbers, - and _), e.g. acme-leads-7k2x9q. At most 10 individual pushes per run, then one \"...and N more\". Leave empty to skip ntfy."
          },
          "ntfyServer": {
            "title": "ntfy server",
            "type": "string",
            "description": "Only used with \"ntfy topic\". Leave as https://ntfy.sh, or enter the public https:// address of your own ntfy server, e.g. https://ntfy.example.com.",
            "default": "https://ntfy.sh"
          },
          "ntfyToken": {
            "title": "ntfy access token (optional)",
            "type": "string",
            "description": "Only used with \"ntfy topic\", for a self-hosted server or a reserved topic that needs a login. An access token from ntfy (starts with tk_, e.g. tk_abc123...). Leave empty for open topics."
          },
          "pushoverUserKey": {
            "title": "Pushover user key",
            "type": "string",
            "description": "Get a phone push via Pushover. Your user key (30 characters, e.g. uQiRzpo4DXghDmr9QzzfQu27cmVRsG) is shown on the Pushover dashboard (pushover.net). Needs \"Pushover app token\" below. At most 10 individual pushes per run, then one \"...and N more\". Leave empty to skip Pushover."
          },
          "pushoverAppToken": {
            "title": "Pushover app token",
            "type": "string",
            "description": "The API token of a Pushover application you create at pushover.net/apps/build (name it after this Actor), e.g. azGDORePK8gMaC0QOYAMyEEuzJnyUi. Needs \"Pushover user key\" above."
          },
          "webhookUrl": {
            "title": "Generic JSON webhook URL (Zapier, Make, n8n, Pipedream, IFTTT, Home Assistant)",
            "type": "string",
            "description": "POST the delivered rows as JSON to any public https:// URL: {source, actor, runId, count, items}. At most 100 rows per POST; every delivered row is sent regardless of the max-notifications cap. For example, route results to email, a spreadsheet or any app. Localhost, private IP and .local/.internal addresses are rejected. Leave empty to skip."
          },
          "maxNotifications": {
            "title": "Max notifications per run",
            "minimum": 1,
            "maximum": 100,
            "type": "integer",
            "description": "Caps how many results are sent to chat and phone channels per run (Discord, Telegram, Slack, Teams, Google Chat, ntfy, Pushover), 1-100, default 25 (e.g. 10). Extra results are still in the dataset. The generic webhook is not capped. Only used when a destination above is set.",
            "default": 25
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}