# German Public Tenders — Ausschreibungen Deutschland (`alpinedata/german-public-tenders`) Actor

Daily feed of German public procurement notices from the official Open Data API (oeffentlichevergabe.de, CC0). Filter by CPV, region (NUTS), keyword. Includes buyer, submission deadline, documents links.

- **URL**: https://apify.com/alpinedata/german-public-tenders.md
- **Developed by:** [alpine data](https://apify.com/alpinedata) (community)
- **Categories:** Business, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## 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

## German Public Tenders — Ausschreibungen Deutschland

Structured daily feed of **German public procurement notices** from the official Open Data API of the Bekanntmachungsservice ([oeffentlichevergabe.de](https://oeffentlichevergabe.de)) — the national publication service for public tenders (eForms-DE). The data is published under the **Creative Commons CC Zero** license explicitly for reuse; this actor turns the raw daily exports into clean, filterable records.

Fuer KMU, Handwerksbetriebe und Berater: Alle neuen deutschen Ausschreibungen als strukturierter Datensatz — gefiltert nach CPV-Code, Region (NUTS) und Stichwort, mit Vergabestelle, **Angebotsfrist** und Link zu den Vergabeunterlagen. Taeglich per Schedule in CRM, Tabelle oder n8n/Make. Kommerzielle Tender-Dienste verkaufen vergleichbare Feeds ab 20–90 EUR pro Monat im Abo.

### What you get per record

| Field | Description | Coverage\* |
|---|---|---|
| `title`, `description` | Official notice title and description | 100% |
| `buyer` | Contracting authority: name, city, postal code, NUTS region | 100% |
| `cpvMain`, `cpvAll` | CPV classification codes | ~96% |
| `nuts` | NUTS region(s) of buyer and place of performance | ~94% |
| `submissionDeadline` | **Angebotsfrist** (BT-131), extracted from the official eForms XML | ~86% of competition notices (where published) |
| `documents` | Links to tender documents / procurement platform | ~99% |
| `estimatedValue` | Estimated value, where published | ~8% (rarely published in Germany) |
| `procurementMethod`, `lotsCount`, `ocid`, `noticeId` | Procedure metadata | 100% |

\*Measured on a full day (642 competition notices, 2026-08-14). Fields absent in the official notice stay empty rather than being guessed. Only the latest version of each notice is delivered.

### Why the submission deadline matters

The official OCDS and CSV exports of the portal do **not** carry the submission deadline. This actor additionally parses the official eForms XML export of the same day and joins the deadline (BT-131) into each record — so you can sort by what matters: how much time is left to bid.

### Input

```json
{
  "noticeKinds": ["competition"],
  "cpvPrefixes": ["45"],
  "nutsPrefixes": ["DE2"],
  "dateFrom": "",
  "dateTo": ""
}
```

Leave the dates empty to get **yesterday and today** — ideal for a daily schedule. `noticeKinds`: `competition` (open calls, default), `award` (contract awards — useful for market analysis), `planning`. CPV examples: `45` construction works, `72` IT services, `50` repair/maintenance, `90` environmental services. NUTS examples: `DE2` Bavaria, `DE3` Berlin, `DE7` Hesse.

### Output example

```json
{
  "title": "Elektroinstallationsarbeiten, Allgemein",
  "buyer": { "name": "Landeshauptstadt München, Baureferat", "city": "München", "nuts": "DE212" },
  "cpvMain": "45311200",
  "submissionDeadline": "2026-08-20T09:30:00",
  "publicationDate": "2026-08-14",
  "documents": ["https://www.meinauftrag.rib.de/public/..."],
  "kind": "competition"
}
```

### Volume and coverage

Measured mid-August 2026: **600–950 notices per weekday**, of which **~640 are open competitions**. The service covers notices published via the national eForms-DE channel (EU-wide procedures above threshold and connected national platforms). Notices published only on regional portals without eForms connection are not included.

### Reliability

- Official REST API, no HTML scraping, no proxies — runs cost fractions of a compute unit.
- A **scheduled daily self-test** verifies that a weekday yields data and that the deadline extraction still works (fails loudly on format drift).
- eForms-DE version jumps are a known maintenance point — handled as incidents, with the self-test as tripwire.

### Legal notes

- This is an **unofficial** tool, not a service of the Beschaffungsamt or any German authority.
- Data license: CC0 (per the portal's Open-Data-Richtlinie). Responsibility for notice content lies with the contracting authorities; records link to the official documents.
- No completeness guarantee: coverage follows the official service and its export availability.

# Actor input Schema

## `noticeKinds` (type: `array`):

competition = open calls for tenders (default), award = contract awards, planning = prior notices.

## `cpvPrefixes` (type: `array`):

Keep only notices whose CPV starts with one of these prefixes (e.g. 45 = construction works, 09 = fuels/energy, 72 = IT services). Empty = all.

## `nutsPrefixes` (type: `array`):

Keep only notices whose buyer or place of performance NUTS code starts with one of these (e.g. DE21 = Oberbayern, DE3 = Berlin). Empty = all of Germany.

## `keyword` (type: `string`):

Case-insensitive match in title or description.

## `dateFrom` (type: `string`):

Start of the publication window. Empty = yesterday.

## `dateTo` (type: `string`):

End of the publication window. Empty = today.

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

Stop after this many notices.

## `selfTest` (type: `boolean`):

Maintenance self-test (yesterday's window, fails loudly on anomalies). Used by the maintainer's daily schedule.

## Actor input object example

```json
{
  "noticeKinds": [
    "competition"
  ],
  "cpvPrefixes": [],
  "nutsPrefixes": [],
  "keyword": "",
  "dateFrom": "",
  "dateTo": "",
  "maxItems": 2000,
  "selfTest": false
}
```

# Actor output Schema

## `tenders` (type: `string`):

One record per published procurement notice

## `runSummary` (type: `string`):

Window, counts and join rates of this run

# 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 = {
    "noticeKinds": [
        "competition"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("alpinedata/german-public-tenders").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 = { "noticeKinds": ["competition"] }

# Run the Actor and wait for it to finish
run = client.actor("alpinedata/german-public-tenders").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 '{
  "noticeKinds": [
    "competition"
  ]
}' |
apify call alpinedata/german-public-tenders --silent --output-dataset

```

## MCP server setup

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

```

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/vDLmVN1su6HMoH2S2/builds/DPWdv58jJBckd44Ww/openapi.json
