# Government Tenders API: EU TED, UK Find a Tender & SAM.gov beta (`markdemian/gov-tenders-feed`) Actor

New public tenders from EU TED and UK Find a Tender, plus SAM.gov (beta, your own key), in one clean schema. Filter by keyword, CPV, NAICS, country and deadline. Official APIs only.

- **URL**: https://apify.com/markdemian/gov-tenders-feed.md
- **Developed by:** [Mark Demian](https://apify.com/markdemian) (community)
- **Categories:** Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 tender notices

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Government Tenders API: EU TED, UK Find a Tender & SAM.gov (beta)

### What does this government tenders feed do?

It collects new public-sector tenders and contract opportunities from official government sources and returns them in **one clean, consistent schema**:

| Source | Status | Coverage | How it's read |
|---|---|---|---|
| **TED** (Tenders Electronic Daily) | ✅ Live | EU and EEA public procurement and the EU institutions | Official TED Search API v3, anonymous |
| **UK Find a Tender** | ✅ Live | UK public procurement (above and below threshold, Procurement Act 2023 notices) | Official OCDS API |
| **SAM.gov** | 🧪 **BETA** | US federal contract opportunities | Official Get Opportunities Public API, using **your own free SAM.gov API key**. Built to the published API docs and unit-tested, but not yet verified against the live API. Please report any problem in the Issues tab. |
| **CanadaBuys** | ⛔ **Disabled** | Government of Canada (federal) tenders | Turned off pending permission from the publisher: the data is open data, but the download site's robots.txt disallows automated access, so this Actor respects that and does not contact it. |

Each notice has the same fields whichever source it comes from: title, buyer, country, stage, CPV / NAICS codes, value, published date, deadline and links. Schedule the Actor daily with **monitor mode** for a feed that contains only new notices.

#### Main features

- **One schema for several portals.** No more separate logins, search UIs and export formats.
- **Filters:** keywords (any), exclude keywords, CPV codes (EU/UK), NAICS codes (US), country, notice stage (tender / planning / award) and a deadline window (e.g. closes in 7–60 days).
- **Monitor mode:** "only new since last run", with memory kept in a named key-value store. Each monitor is separate.
- **Privacy by design:** personal contact names, emails and phone numbers are never output (PIPEDA / GDPR / UK GDPR data minimisation). See [Does it collect personal data?](#does-it-collect-personal-data).
- **Polite and official:** only documented public APIs. Each source's rate limits and robots.txt are respected, `Retry-After` is honoured, and there is no proxy rotation, no browser and no anti-bot evasion.
- **Cost control:** you pay per notice output, and the run stops cleanly at your max cost per run.

### What can you use it for?

- **Bid and sales teams:** a daily list of new tenders in your sector across the EU and UK (and the US, in beta).
- **GovTech / SaaS vendors:** watch CPV 72 (IT services) or NAICS 5415 for opportunities, and feed them into a CRM.
- **Market research:** count notices and values by buyer, country or code.
- **AI agents and alerts:** pipe new notices to Slack, email, Make or Zapier, or to an LLM that ranks them for fit.

### How to use it

1. Pick the **sources** (TED and UK Find a Tender by default). For SAM.gov (beta), paste your SAM.gov public API key (free: sign in at sam.gov, then Profile > Account Details > Public API Key).
2. Add **keywords** and/or **codes**, and optionally **countries** and a **deadline window**.
3. Run it. For an alert feed, turn on **Only new notices since last run** and add a daily **schedule**.

### Input examples

New IT tenders in Germany and Ireland closing in 10 days or more:

```json
{ "sources": ["ted"], "cpvCodes": ["72000000", "48000000"], "countries": ["DE", "IE"], "deadlineMinDays": 10 }
```

Daily "new software tenders" monitor across the EU, UK and (beta) US:

```json
{
  "sources": ["ted", "uk-fts", "sam"],
  "samApiKey": "<your SAM.gov key>",
  "keywords": ["software", "cloud", "cybersecurity"],
  "onlyNewSinceLastRun": true,
  "monitorName": "software-daily"
}
```

US (beta) small-business set-asides in NAICS 5415 (computer systems design):

```json
{ "sources": ["sam"], "samApiKey": "<key>", "naicsCodes": ["5415"], "publishedWithinDays": 7 }
```

#### Input fields

| Field | What it does |
|---|---|
| `sources` | `ted`, `uk-fts`, `sam` (beta). The default is `ted` + `uk-fts`. SAM.gov is skipped (with a warning) if there's no key. CanadaBuys is disabled pending permission. |
| `samApiKey` | BETA. Your SAM.gov public API key. It's a secret input: stored encrypted, never logged and never output. |
| `keywords` / `excludeKeywords` | Matched against the title, description and buyer. On TED, keywords use TED's own full-text search. |
| `cpvCodes` / `naicsCodes` | Prefix match (`72000000` = all of division 72). If you set codes, a notice must match at least one of them, so add a code for every source you use. |
| `countries` | ISO-2 codes (GB, DE, FR, US…). Sources outside these countries are skipped, which saves requests. |
| `noticeStages` | `tender` (default), `planning`, `award`. |
| `publishedWithinDays` | Fetch window, default 2 days. |
| `deadlineMinDays` / `deadlineMaxDays` / `includeNoDeadline` | Deadline window, in days from now. |
| `onlyNewSinceLastRun` / `monitorName` | Monitor mode. |
| `maxNoticesPerSource` / `maxRequestsPerSource` / `samMaxRequests` | Safety limits. SAM.gov allows 10 calls a day per personal key (1,000 with an entity role), so `samMaxRequests` defaults to 2. |
| `includeDescription` / `descriptionMaxChars` | Plain-text description, contact details removed. |

### Output

One dataset item per notice:

```json
{
  "key": "ted:726498-2026",
  "source": "ted",
  "noticeId": "726498-2026",
  "title": "Trygghetsskapande Teknik",
  "titleEnglish": "Sweden – IT services: consulting, software development, Internet and support – Trygghetsskapande Teknik",
  "description": "Kommunen avser att upphandla trygghetsskapande teknik …",
  "noticeStage": "tender",
  "noticeType": "cn-standard",
  "procedureType": "open",
  "buyerName": "Värmdö kommun",
  "buyerCity": "Gustavsberg",
  "country": "SE",
  "cpvCodes": ["72000000"],
  "naicsCodes": [],
  "unspscCodes": [],
  "estimatedValue": 25000000,
  "currency": "SEK",
  "publishedAt": "2026-10-20T22:00:00.000Z",
  "deadlineAt": "2026-11-05T23:00:00.000Z",
  "url": "https://ted.europa.eu/en/notice/-/detail/726498-2026",
  "documentsUrl": "https://www.kommersannons.se/elite/Notice/NoticeDispatch.aspx?NoticeId=96290",
  "language": "swe",
  "licence": "© European Union, https://ted.europa.eu. Procurement notices may be freely reused (TED legal notice; Commission Decision 2011/833/EU).",
  "scrapedAt": "2026-10-28T19:08:05.072Z"
}
```

#### Output fields

`key` (unique, `source:noticeId`), `source`, `noticeId`, `referenceNumber`, `title`, `titleEnglish`, `description`, `noticeStage` (tender / planning / award / other), `noticeType` (the source's own type), `status`, `procedureType`, `buyerName`, `buyerCity`, `buyerRegion`, `country`, `countries`, `placeOfPerformance`, `cpvCodes`, `naicsCodes`, `unspscCodes`, `otherCodes` (e.g. PSC, GSIN), `setAside`, `estimatedValue`, `currency`, `publishedAt`, `deadlineAt` (ISO 8601, UTC), `url`, `documentsUrl`, `submissionUrl`, `language`, `licence`, `scrapedAt`.

Each run also saves `RUN_STATS` in the default key-value store: per-source requests, counts read, matched and output, the fetch window, and any error.

### How much does it cost?

Pay per result: **$0.002 per notice** in the dataset, plus Apify's small standard Actor-start fee. 1,000 notices cost $2. A typical daily keyword monitor outputs 10–100 notices a day, which is about $0.60–$6 a month. Set a **max cost per run** and the Actor stops cleanly when it gets there ("stopped early: max cost per run reached").

### Use it from AI agents (Apify MCP)

AI agents and assistants (Claude, Cursor, VS Code and other MCP clients) can run this Actor through [Apify's hosted MCP server](https://docs.apify.com/platform/integrations/mcp). Add this to your MCP client's configuration. On first connection it opens your browser so you can sign in to Apify:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=fetch-actor-details,markdemian/gov-tenders-feed"
    }
  }
}
```

Then ask things like *"Find open EU tenders for cybersecurity services closing in the next 30 days"* or *"Any new UK NHS software tenders this week?"*

Tips for agents:

- Set `includeDescription: false` and a small `maxNoticesPerSource` to keep responses short and cheap.
- Use `countries` to skip sources you don't need, and codes (`cpvCodes`, `naicsCodes`) for precise matching.
- Set a max cost (`maxTotalChargeUsd` in the call options) to cap what a single call can spend.

### Sources and licences

Every item carries a `licence` field. **Keep it when you republish the data.**

- **UK Find a Tender:** *Contains public sector information licensed under the Open Government Licence v3.0.* ([OGL v3.0](https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/)). We re-checked the licence page on 28 Oct 2026. It allows you to copy, publish, adapt and exploit the information commercially, provided you acknowledge the source with that attribution statement and link to the licence where possible. The OGL does **not** cover personal data, and it does not let you imply official endorsement. The API also states the OGL in every response, and Find a Tender's terms say its content can be reproduced under the OGL.
- **TED:** © European Union, https://ted.europa.eu. According to the [TED legal notice](https://ted.europa.eu/en/legal-notice) and Commission Decision 2011/833/EU, the procurement notices may be freely reused for commercial or non-commercial purposes, and the source must be acknowledged. TED's fair-usage policy for the API (700 requests a minute) is respected: this Actor uses at most about 2 requests a second.
- **CanadaBuys:** currently **disabled**. The CanadaBuys tender data is published as open data under the [Open Government Licence – Canada](https://open.canada.ca/en/open-government-licence-canada), but the download host's robots.txt disallows automated access. The source stays off until the publisher confirms automated downloads are fine; it is not contacted at all.
- **SAM.gov (beta):** US federal government data, retrieved with your own API key under SAM.gov's terms of use. Works of the US federal government are not subject to copyright (17 U.S.C. 105).

This Actor is not affiliated with or endorsed by any of these governments or agencies.

### FAQ

#### Is it legal to use this data?

All enabled sources publish this data so that it can be reused, and the Actor only uses their official APIs. Follow each source's attribution terms (the `licence` field), and the terms of SAM.gov for your API key.

#### Does it collect personal data?

No, as far as is technically possible. Named contact points are never read into the output: SAM.gov `pointOfContact`, and Find a Tender `contactPoint`. Neither are SAM.gov awardee addresses (an awardee can be a sole proprietor). In descriptions, email addresses and phone numbers are replaced with `[email removed]` / `[phone removed]`, and links that are really email addresses are dropped. Free text can still mention a person's name (e.g. "send questions to …"), and names can't be removed reliably, so treat descriptions as public-sector text that may mention officials. Buyer names are organisations.

#### Why is SAM.gov skipped or failing?

SAM.gov support is in **beta**: it follows SAM.gov's published API documentation and is unit-tested, but has not yet been checked against the live API, so field shapes may still change. SAM.gov requires each user's own API key. A personal key allows about 10 requests a day. Each request returns up to 1,000 notices, so one or two calls per daily run is enough. Keys must be renewed every 90 days. When SAM.gov rejects a key, the Actor says so in the log and `RUN_STATS`, and the other sources still run.

#### How fresh is the data?

TED publishes on working days (Monday to Friday). UK Find a Tender updates continuously. SAM.gov updates continuously.

#### How does monitor mode work?

The Actor remembers the keys of notices it has already output (for 180 days) in a named key-value store, and outputs only unseen ones. If a run is interrupted or hits a limit, the next run reaches back to the last complete run (up to 31 days), so notices aren't skipped. Use `monitorName` to run several independent monitors.

#### Why is CanadaBuys disabled?

The CanadaBuys data is open data, but the server it's downloaded from has a robots.txt that disallows automated tools. This Actor respects robots.txt, so CanadaBuys stays off until the publisher confirms automated downloads are allowed. Selecting it is not possible in the input.

#### Can I use it via API, Python, JavaScript, Zapier or Make?

Yes, like any Apify Actor: use the Apify API, the client libraries, webhooks or the Zapier and Make integrations.

### Limitations

- **SAM.gov:** descriptions are not included, because the API returns only a link that needs your key. Use the `url` to read the full notice on SAM.gov.
- **TED:** deadlines are date-only (end of day, buyer's time zone). Titles and descriptions are in the original language, and `titleEnglish` is TED's English title line. Keyword search uses TED's full-text index.
- **UK Find a Tender:** "published in the last N days" uses the release *update* time, so an updated older notice can appear again. Monitor mode removes repeats. Stage filtering is done locally because the API's own `stages` filter returned incomplete results in testing.
- **SAM.gov is beta** and **CanadaBuys is disabled** (see above).
- Large back-fills need a higher `maxRequestsPerSource`. The default reads up to 2,000 notices per source per run.

# Changelog

This Actor's version history is a separate document: https://apify.com/markdemian/gov-tenders-feed/changelog.md

# Actor input Schema

## `sources` (type: `array`):

Which official sources to read. TED and UK Find a Tender work without a key. SAM.gov is BETA (not yet verified against the live API) and needs your own free SAM.gov public API key (below); without a key it is skipped. CanadaBuys is currently disabled pending permission from its publisher, so it is not offered.

## `keywords` (type: `array`):

Keep notices whose title, description or buyer contains ANY of these (case-insensitive). On TED the keywords use TED's own full-text search, which also matches other EU languages. Empty = all notices.

## `excludeKeywords` (type: `array`):

Drop notices whose title, description or buyer contains any of these.

## `cpvCodes` (type: `array`):

Prefix match, so 72000000 means all of division 72 (IT services). Used by TED and UK Find a Tender. If you set any code filter, notices must match at least one code in any scheme, so add codes for each source you use.

## `naicsCodes` (type: `array`):

Prefix match, so 5415 matches 541511, 541512 and the rest. Used by SAM.gov.

## `unspscCodes` (type: `array`):

Prefix match (trailing 00 pairs are ignored). Reserved for CanadaBuys, which is currently disabled pending permission, so this filter has no effect today.

## `countries` (type: `array`):

Buyer or place-of-performance country, e.g. US, GB, DE, FR. Sources with no matching country are skipped. Empty = all.

## `noticeStages` (type: `array`):

tender = open for bids (default). planning = prior information, market engagement, sources sought, requests for information. award = award and intent-to-award notices.

## `publishedWithinDays` (type: `integer`):

Fetch window. In monitor mode the window also reaches back to the previous complete run (up to 31 days), so a daily or weekly schedule never misses notices.

## `deadlineMinDays` (type: `integer`):

Skip notices that close sooner than this. 0 = no limit.

## `deadlineMaxDays` (type: `integer`):

Skip notices that close later than this. 0 = no limit.

## `includeNoDeadline` (type: `boolean`):

Many notices (especially planning notices) have no deadline. Keep them (default) or drop them when a deadline filter is set.

## `onlyNewSinceLastRun` (type: `boolean`):

Remembers notices already output (in a named key-value store) and outputs only new ones. Schedule the Actor daily for a new-tenders alert feed.

## `monitorName` (type: `string`):

Keeps separate memory for different monitors. If empty, a name is derived from your sources and filters.

## `samApiKey` (type: `string`):

BETA. Your own free public API key from SAM.gov (sam.gov > Profile > Account Details > Public API Key). Only used when SAM.gov is selected. Stored encrypted by Apify and never logged or output.

## `samMaxRequests` (type: `integer`):

Each call returns up to 1,000 notices. SAM.gov allows 10 calls a day for a personal key without an entity role and 1,000 with one, so keep this low for scheduled runs.

## `maxNoticesPerSource` (type: `integer`):

Cap on output notices per source after filters. 0 = no cap. The example input uses 10 to keep the first run cheap.

## `maxRequestsPerSource` (type: `integer`):

Safety limit for TED and UK Find a Tender (100 notices per page). Raise it for large back-fills.

## `includeDescription` (type: `boolean`):

Plain-text description. Emails and phone numbers are removed. SAM.gov's API returns only a keyed link, so SAM.gov descriptions are empty.

## `descriptionMaxChars` (type: `integer`):

0 = no limit.

## Actor input object example

```json
{
  "sources": [
    "ted",
    "uk-fts"
  ],
  "keywords": [
    "software"
  ],
  "excludeKeywords": [],
  "cpvCodes": [],
  "naicsCodes": [],
  "unspscCodes": [],
  "countries": [],
  "noticeStages": [
    "tender"
  ],
  "publishedWithinDays": 7,
  "deadlineMinDays": 0,
  "deadlineMaxDays": 0,
  "includeNoDeadline": true,
  "onlyNewSinceLastRun": false,
  "samMaxRequests": 2,
  "maxNoticesPerSource": 10,
  "maxRequestsPerSource": 20,
  "includeDescription": true,
  "descriptionMaxChars": 3000
}
```

# Actor output Schema

## `notices` (type: `string`):

All notices output in this run (default dataset).

## `runStats` (type: `string`):

Per-source counts, status, fetch window and errors.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "sources": [
        "ted",
        "uk-fts"
    ],
    "keywords": [
        "software"
    ],
    "publishedWithinDays": 7,
    "maxNoticesPerSource": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("markdemian/gov-tenders-feed").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "sources": [
        "ted",
        "uk-fts",
    ],
    "keywords": ["software"],
    "publishedWithinDays": 7,
    "maxNoticesPerSource": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("markdemian/gov-tenders-feed").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "sources": [
    "ted",
    "uk-fts"
  ],
  "keywords": [
    "software"
  ],
  "publishedWithinDays": 7,
  "maxNoticesPerSource": 10
}' |
apify call markdemian/gov-tenders-feed --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,markdemian/gov-tenders-feed"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/Bok79YmOFi5svdmzo/builds/Gi52BNDgBDs3aNIqQ/openapi.json
