# Public Tenders Feed for TED and Grants.gov Notices (`verrr/public-procurement-digest`) Actor

Get EU public tenders and contract awards from TED plus US federal funding calls from Grants.gov as one clean JSON record per notice. Filter by keyword, country, CPV code and notice type, and switch on new-notices mode for a daily digest. Official keyless APIs, no login and no proxy needed.

- **URL**: https://apify.com/verrr/public-procurement-digest.md
- **Developed by:** [VER RR](https://apify.com/verrr) (community)
- **Categories:** Business
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 notice results

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

Public tenders feed for EU tenders and contract awards from TED and US federal funding calls from Grants.gov, delivered as one clean JSON record per notice, with an optional new-notices mode for a daily digest.

> This product uses the Grants.gov API but is not endorsed or certified by the U.S. Department of Health and Human Services.

Instead of learning two portals and two data formats, you get the same eighteen fields for every notice. Run it with no input to see the latest notices, or filter by keyword, buyer country, CPV code and notice type.

### What data you get

- `id`: stable notice id, prefixed with the source
- `source`: `ted` or `grants`
- `noticeType`: `planning`, `tender`, `award` or `other` (modifications and pre-award notices)
- `sourceNoticeType`: the source's own type, such as `cn-standard`, `can-standard`, `synopsis` or `forecast`
- `referenceNumber`: TED publication number or Grants.gov opportunity number
- `title`: the notice title, in English when the notice has it, otherwise in the language published
- `description`: the notice description, or null when the source has none or the text contains an email address or phone number
- `language`: three-letter language code of the title
- `buyerName`: the contracting authority or funding agency
- `buyerCountry`: three-letter ISO country code
- `publishedAt`: publication date, `YYYY-MM-DD`
- `deadlineAt`: earliest submission deadline, `YYYY-MM-DD`, or null
- `categoryCodes`: CPV codes (TED) or Assistance Listing numbers (Grants.gov)
- `contractType`: `services`, `works` or `supplies` (TED), or the funding instrument (Grants.gov)
- `value`: total value, meaning the awarded amount on award notices and the estimate on all others, or null
- `currency`: currency of `value`, or null
- `winners`: winning firms on TED award notices, only when the name carries a legal form such as GmbH, S.A., Sp. z o.o., Ltd or AB. Coverage is partial: see Limits and FAQ
- `url`: link to the official notice

### Input

Every field is optional. An empty run returns the latest notices from both sources, whatever their date.

| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| `sources` | array | no | `["ted", "grants"]` | Which official sources to read |
| `keywords` | array | no | `[]` | Keep notices that mention any of these words or phrases |
| `noticeTypes` | array | no | `[]` | Keep only `planning`, `tender` or `award` notices. Empty means every type |
| `countries` | array | no | `[]` | Buyer countries as three-letter ISO codes. Grants.gov is skipped unless the list includes USA |
| `cpvCodes` | array | no | `[]` | Eight-digit CPV codes, TED only. A parent code also matches its child codes. Grants.gov is skipped when this is set |
| `onlyNew` | boolean | no | `false` | Return only notices not yet delivered for these same filters |
| `maxItems` | integer | no | `50` | Stop after this many notices, split evenly between the sources in use. Maximum 10,000 |

### Pricing

Pay-Per-Event:

| Event | Price |
|---|---|
| `notice-result` | $2.00 per 1,000 notices ($0.002 each) |
| `apify-actor-start` | $0.00005 per run |

`maxItems` caps each run, so it is also your spending limit. Only saved notices are billed.

### Sample output

```json
{
  "id": "ted:768844-2026",
  "source": "ted",
  "noticeType": "award",
  "sourceNoticeType": "can-standard",
  "referenceNumber": "768844-2026",
  "title": "Stöd för personalsäkerhet",
  "description": "System för hantering och omvärldbevakning inom personsäkerhet samt tjänster inom bakgrundskontroller, säkerhetsprövning m.m..",
  "language": "swe",
  "buyerName": "Region Gotland",
  "buyerCountry": "SWE",
  "publishedAt": "2026-11-05",
  "deadlineAt": null,
  "categoryCodes": ["79417000", "75241000", "79710000"],
  "contractType": "services",
  "value": 2700000,
  "currency": "SEK",
  "winners": ["SR Intelligence AB"],
  "url": "https://ted.europa.eu/en/notice/-/detail/768844-2026"
}
```

### Daily digest with new-notices mode

Turn on `onlyNew` and run the Actor on an Apify schedule. The first run returns the latest notices and starts tracking from there. Each later run returns only what has not been delivered for the same filters, oldest first. If a run stops at `maxItems`, at your spending limit or at its timeout, the next run continues from that point. Set `maxItems` above your daily volume to keep up: TED alone publishes thousands of notices per issue when no filters are set.

Two limits apply, both on Grants.gov:

- A forecast keeps its `id` when it opens as a funding call, and its date moves to the opening date. You get the notice a second time, as a `tender` with the same `id`, and are billed a second time. So one opportunity can be delivered and billed twice: once as a forecast and once when it opens.
- A notice that first appears more than 30 days behind its own date is missed.

Each combination of sources and filters keeps its own position, so several saved tasks can run side by side. A run that finds nothing new still succeeds and tells you so in the log.

### Integrations

Call it from n8n, Make or Zapier, or through the Apify API:

```bash
curl -X POST "https://api.apify.com/v2/acts/VERRR~public-procurement-digest/runs?token=<YOUR_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{ "keywords": ["<your keyword>"], "onlyNew": true, "maxItems": 500 }'
```

### Use cases

- Bid teams watching EU public tenders in their CPV codes and countries
- Grant writers tracking new US federal funding calls and forecasts by keyword
- Market researchers following public buying by sector and country from TED notices
- Consultants sending clients a weekly public procurement digest
- AI agents and automations that need one predictable tender format

### Limits and FAQ

- **Which sources are covered?** TED and Grants.gov, through their official keyless APIs. SAM.gov and USAspending are not included, so there are no US federal contract awards.
- **Does Grants.gov have award notices?** No. It lists funding calls (`tender`) and forecasts (`planning`), so filtering on `award` returns TED only.
- **How complete is `winners`?** Partial, by design. TED does not mark which winners are private individuals, so a name is kept only when it carries a recognised legal form. Sole traders and many real firms are left out as a result. On 3,000 recent award notices, 33% of winner names were left out and 24.5% of notices with a winner ended with an empty list. It varies by country: the list was empty on 159 of 206 such notices from France and 35 of 44 from Belgium, against 78 of 440 from Germany. Use it as a sample of winners, not a full record, and follow `url` for the official notice.
- **Why is my `value` null?** Many notices do not publish one. TED values are in the notice's own currency and are not converted.
- **Why is a title not in English?** TED notices are published in the buyer's language. Text is delivered as published and is not translated.
- **Does it include contact people?** Contact fields are never collected, and a description containing an email address or phone number is left out. A person's name written in free text cannot be detected and may remain.
- **How long does a run take?** TED returns 250 notices per request. Grants.gov needs one request per notice for the description and funding, at about 2 notices a second, so 1,000 Grants.gov notices take about 8 minutes.
- **What if a run is about to time out?** It stops early and saves what it has, leaving a minute or a quarter of the time left, whichever is less. Grants.gov notices still waiting for their details are not saved or billed, and the status message says how many.
- **What if a source is down?** The other source's notices are still saved and billed, and the run's status message names what failed. If nothing could be saved, the run fails.
- **Do I need a proxy?** No.
- **What if a source changes its API?** This Actor is monitored weekly and repaired automatically.

### Legal note

This Actor collects publicly available data only, through official public APIs. You are responsible for using the output in compliance with applicable laws and each source's terms.

TED notices: source TED (Tenders Electronic Daily), © European Union, 1998-2026, reused under the European Commission's reuse policy. Grants.gov notices: source Grants.gov, U.S. Department of Health and Human Services. This Actor changes field names, date formats and text markup into one common format. The words of titles and descriptions are not changed. It is an independent product and is not affiliated with the European Union, the Publications Office of the European Union or the U.S. Department of Health and Human Services.

# Actor input Schema

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

Which official sources to read. TED holds EU and EEA tenders and contract awards. Grants.gov holds US federal funding calls and forecasts.

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

Keep notices that mention any of these words or phrases. Leave empty for all notices.

## `noticeTypes` (type: `array`):

Keep only these types. Leave empty for every type, including contract modifications. Grants.gov has no award notices.

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

Keep notices from buyers in these countries, as three-letter ISO 3166-1 alpha-3 codes. Leave empty for all countries. Grants.gov is skipped unless the list includes USA.

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

Keep TED notices in these eight-digit Common Procurement Vocabulary codes. A parent code also matches its child codes. Grants.gov has no CPV codes, so it is skipped when this is set.

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

Return only notices not yet delivered for these same filters. The first run returns the latest notices and starts tracking from there. Later runs go oldest first, so if a run stops at Maximum notices the next one continues from that point. Set Maximum notices above your daily volume to keep up. One exception: a Grants.gov forecast is returned again, and billed a second time, when it opens as a funding call.

## `maxItems` (type: `integer`):

Stop after this many notices, split evenly between the sources in use. Each saved notice is billed once, so this is also your spending cap.

## Actor input object example

```json
{
  "sources": [
    "ted",
    "grants"
  ],
  "keywords": [],
  "noticeTypes": [],
  "countries": [],
  "cpvCodes": [],
  "onlyNew": false,
  "maxItems": 50
}
```

# Actor output Schema

## `results` (type: `string`):

All notices found: id, source, noticeType, sourceNoticeType, referenceNumber, title, description, language, buyerName, buyerCountry, publishedAt, deadlineAt, categoryCodes, contractType, value, currency, winners, url.

# 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("verrr/public-procurement-digest").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("verrr/public-procurement-digest").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 '{}' |
apify call verrr/public-procurement-digest --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,verrr/public-procurement-digest"
        }
    }
}
```

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/SMSsXbaIwLGYKDwA5/builds/Mi3IydnyLcpK9ccWs/openapi.json
