# Government Tender Feed - Canada + EU, Normalized, New-Only (`gratifying_graph/tender-feed`) Actor

Open government tenders from CanadaBuys (Canada) and TED (EU) in one normalized schema, with keyword and category filters and new-since-last-run change detection. Official open data, no key. Business data only, no personal contact fields.

- **URL**: https://apify.com/gratifying\_graph/tender-feed.md
- **Developed by:** [Jimmy A](https://apify.com/gratifying_graph) (community)
- **Categories:** Lead generation, Automation
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 tender results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Government Tender Feed - Canada + EU, normalized, new-only

Open government tenders from **CanadaBuys** (Canada) and **TED** (European Union) in one clean schema, with keyword and category filters and **new-since-last-run** change detection. Official open data, no API key, no scraping fragile websites.

Built to do the one thing the existing tender actors don't: a single normalized feed across sources, deduplicated over time, so a scheduled run gives you only the new opportunities that match your business.

### What you get per notice

```json
{
  "source": "CA-CanadaBuys",
  "noticeId": "cb-62-85037229",
  "title": "Invitation to submit an expression of interest...",
  "status": "Open",
  "publishedDate": "2026-06-09",
  "closingDate": "2026-06-26T23:59:00",
  "category": "SRV",
  "gsin": "D302",
  "buyer": "Department of Public Works and Government Services (PSPC)",
  "region": "Ontario",
  "url": "https://canadabuys.canada.ca/...",
  "description": "..."
}
```

EU notices carry `cpv` codes and the TED notice URL. Both sources share the common fields above.

**Business data only.** CanadaBuys publishes a procurement-officer contact; this actor does not output any contact name, email, phone, or fax. Notice content only.

### Filters

- **keywords**: match title/description (any keyword hits)
- **cpvOrGsin**: category codes - GSIN for Canada (e.g. `D302`), CPV for EU (e.g. `72000000`), prefix-matched
- **euQuery**: raw TED expert query for power users (e.g. `classification-cpv=72000000*`)
- **onlyNew**: output only notices not seen by previous runs (per source); schedule it for a clean new-opportunities feed

### Use cases

- **Bid discovery**: vendors watching for relevant government work, daily, without paying a portal
- **Market intelligence**: who's buying what, across Canada and the EU
- **Lead feeds for consultants**: filter by category, pipe new matches to email/Slack/CRM
- **AI agents**: "any new IT tenders in Canada this week" as a standby call

### API / Standby mode

```
GET /?source=CA&keywords=software,it&code=D302&onlyNew=false
```

Returns matching notices synchronously - usable as an agent tool.

### Pricing

| Event | Price |
|---|---|
| Actor start | $0.001 |
| Per tender returned | $0.002 |
| Run digest | $0.02 |
| API call (standby) | $0.02 |

A daily filtered watch returning ~20 new tenders costs about $1.50/month.

### Sources & coverage

- **CanadaBuys** (canadabuys.canada.ca open data): federal + participating provincial/territorial tender notices, EN/FR, refreshed continuously.
- **TED** (ted.europa.eu): EU-wide notices, ~390k active, multilingual (English title preferred).
- Roadmap: SAM.gov (US) as a bring-your-own-key adapter; SEAO Quebec detail enrichment.

### FAQ

**Is this legal?**
Yes. Both sources are official open-data feeds published for public reuse. The actor reads no login-walled data and outputs no personal contact information.

**How does "only new" work?**
The actor remembers notice IDs it has seen (per source, up to 20,000) and outputs only unseen ones. First run saves the baseline; deltas start on run two. Use `monitorGroup` to keep separate watchlists independent.

**CSV export?**
Every Apify dataset exports as CSV, JSON, or Excel.

# Actor input Schema

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

Which official open-data sources to pull. CA = CanadaBuys, EU = TED (Tenders Electronic Daily).

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

Case-insensitive match on title or description. Empty = all notices. Any keyword matching counts.

## `cpvOrGsin` (type: `array`):

Filter by code: GSIN (Canada, e.g. D302) or CPV (EU, e.g. 72000000). Matched as a prefix.

## `euQuery` (type: `string`):

Optional raw TED expert query (overrides category for EU). Example: classification-cpv=72000000.

## `onlyNew` (type: `boolean`):

Remember notice IDs seen by previous runs (per source) and output only new ones. First run saves the baseline.

## `maxPerSource` (type: `integer`):

Cap on notices returned per source per run.

## `monitorGroup` (type: `string`):

Namespace for new-since-last-run memory, so separate watchlists track independently.

## Actor input object example

```json
{
  "sources": [
    "CA"
  ],
  "keywords": [],
  "cpvOrGsin": [],
  "onlyNew": false,
  "maxPerSource": 500,
  "monitorGroup": "default"
}
```

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("gratifying_graph/tender-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 = {}

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

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

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

```

## CLI example

```bash
echo '{}' |
apify call gratifying_graph/tender-feed --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=gratifying_graph/tender-feed",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

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