# Germany Public Procurement Notices - OCDS, Per Release (`nexgensignal/de-public-procurement-notice-records`) Actor

Germany public procurement notices (oeffentlichevergabe.de) as clean per-record OCDS releases - OCID, buyer, tender title/status, method, category and value, by month. CC0 per package; contacts/description dropped. $0.05 per record.

- **URL**: https://apify.com/nexgensignal/de-public-procurement-notice-records.md
- **Developed by:** [NexGen Signal](https://apify.com/nexgensignal) (community)
- **Categories:** Business, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $33.50 / 1,000 procurement release records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#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

## Germany Public Procurement Notices - OCDS, Per Release

Germany's public-procurement notices - across all government levels - as clean **OCDS release** records, one
per release, for the month you choose. OCID, buyer, tender title/status, procurement method and category, and
value. Every package is **CC0**; contact persons and free-text descriptions are dropped.

### What one record represents

The source is the **Datenservice Oeffentlicher Einkauf** (`oeffentlichevergabe.de`), Germany's federal
procurement data service, which publishes notices in the **Open Contracting Data Standard (OCDS)**. Each record
is **one OCDS release**: its OCID, release id and date, the release tag, initiation type, the buyer
organisation, the tender id, title and status, the procurement method and main category (goods/works/services),
and the tender value.

### Coverage and volume

For month **2026-08** the export holds **22,892** OCDS releases - measured live at build time.

**Sol's Wave-4 index put this door at 22,892 EXACT for 2026-08; measured live at build time the month's export
holds 22,892 releases - matching the index.**

Each month is one partition: set the **Publication month** input (`YYYY-MM`) to pull that export. The Actor
downloads the month's OCDS zip and delivers each release, stopping as soon as your **Maximum records** cap is
met.

### Licence and attribution

Every OCDS package embeds a **CC0 1.0** licence (`opendefinition.org/licenses/cc-zero/`) - a public-domain
dedication. The full notice travels on every record:

> Datenservice Oeffentlicher Einkauf (oeffentlichevergabe.de). Every OCDS package embeds a Creative Commons Zero (CC0 1.0) licence (opendefinition.org/licenses/cc-zero/) - public-domain dedication, free to use for any purpose. The CC0 licence is asserted per package.

The CC0 licence is **asserted per package**: a per-record check rejects any package whose embedded licence is
not CC0 (verified with a planted-row test), so no non-CC0 release is ever delivered.

### Person-data policy

OCDS releases carry `parties[].contactPoint` blocks with contact persons, and a free-text `tender.description`.
This Actor **never reads either**: the contact points and the description are not extracted, and a per-record
assertion rejects any contactPoint/description/person field (verified with a planted-field test). The buyer is
delivered as an **organisation** name. No natural-person data is processed.

### Interpretation caveat

One record per OCDS release from the German federal procurement service, for the selected month: OCID, release date, buyer organisation, tender id/title/status, procurement method and category, and value. parties\[].contactPoint (contact persons) and the free-text tender.description are never read. Each package's embedded CC0 licence is asserted per record.

Values are reproduced verbatim from the OCDS packages; the Actor never rewrites a field. `value_amount` is a
real number where the release records one (many notices have no value and leave it null).

### Provenance and compliance

Every run reads the door host's `robots.txt` at runtime; the gate result (URL, status, byte length and, where a
policy is served, its SHA-256) is written to the run's `RUN_RECEIPT`. Where the host serves no robots.txt, the
gate records that fact (flagged) and proceeds on the licence, which expressly grants re-use. The endpoint is
keyless. The Actor never bypasses a block or fetches through a mirror.

### Data quality and freshness

Boolean columns are delivered as real booleans and numeric columns as real numbers. Delivery is keyed on a
stable id, so the dataset is safe to diff, deduplicate or upsert. Every run re-reads the live door, so the data
is as fresh as the source publishes, and each record's `observed_at` stamp dates the snapshot. The run's
`RUN_RECEIPT` records the source URL and how many records were delivered and charged, and confirms
`charge_equals_delivered`.

### Billing and delivery

Pricing is per record: you are billed only for records the Actor actually delivers, with the charge raised
after each record is pushed (push-then-charge), so a failed or empty run costs nothing. The **Maximum records**
cap bounds every run, so you control spend precisely - sample cheaply, then raise it. Because delivery is keyed
on a stable id, re-running and upserting keeps a downstream table current without re-paying for rows you already
hold; only new and changed records add cost, and every receipt reconciles delivered against charged.

### Schema, typing and joins

Every record is a flat object with a fixed, typed schema: strings stay strings, numbers are parsed to real
numbers, and booleans to real booleans, so the data loads into a warehouse or a dataframe without a cleaning
pass. The `record_id` is a stable composite key, which means the dataset is safe to diff between runs, to
deduplicate, and to upsert into a table you maintain over time. Because the identifiers the source uses are
preserved verbatim, the dataset joins cleanly onto other sources keyed on the same identifier, and a scheduled
run keeps the downstream copy current with no manual reconciliation - the new and changed rows simply upsert
over the old ones, and the `observed_at` stamp on every record tells you when each was last seen live.

### Inputs

- **Publication month** (`month`, required) - the month to pull, as `YYYY-MM`. Prefilled with `2026-08`.
- **Maximum records** (`maxRecords`) - hard cap on releases delivered and billed within the month.

### Output

Records land in the Actor's default dataset and export as JSON, CSV, Excel or via the Apify API. A tabular
overview surfaces OCID, release date, buyer, tender title, status, category and value.

### Fields in detail

The record leads with `ocid`, `release_id`, `release_date`, `tag`, `initiation_type`, `buyer_name`,
`tender_id`, `tender_title`, `tender_status`, `procurement_method`, `procurement_method_details`,
`main_procurement_category`, `value_amount`, `value_currency`, `published_date` and the `licence_id` (CC0). The
provenance block closes every record.

### Typical uses

German bid teams use this cell to track public tenders across all government levels - who is buying what, under
which procedure and category - as a clean OCDS series keyed on the OCID. Because the buyer, category and status
are first-class fields, a group-by gives the pipeline per category or per buyer without parsing OCDS JSON
yourself. To build a multi-month history, run the cell once per month and concatenate on the OCID. A scheduled
monthly run keeps a downstream procurement table current.

### The OCDS format

OCDS (the Open Contracting Data Standard) is the international schema for procurement data, so a record from
this cell has the same shape as procurement data from any OCDS publisher worldwide - the OCID is a globally
unique contracting identifier, and the tender/buyer/value structure is standardised. This cell flattens the
release to the fields most teams query, keeping the OCID so you can always trace back to the full package. The
German service publishes across all government levels - federal, state and municipal - in one export, so a
single month gives the complete national picture rather than one authority at a time.

### Why the monthly partition

Procurement notices arrive continuously, and the service organises them by publication month, so the month is
the natural pull unit. Making it a required input keeps each run bounded and reproducible: one month is one
zip, one clean set of releases. The capacity line is the month's count (about 22,892 for 2026-08), and the
archive spans many months; to build a longer series, run once per month and concatenate on the OCID, which
never changes for a contracting process.

### Reading the fields

`main_procurement_category` separates goods, works and services; `procurement_method` and its details name the
procedure; `tender_status` tracks the notice's state; and `value_amount`/`value_currency` give the contract
value where the notice records one. A group-by on category or buyer turns the month into a pipeline view, and
because the buyer is a clean organisation name, aggregation needs no cleaning.

### Sibling Actors

It sits beside the fleet-2 EU TED tender monitor (EU-level corpus, ~30% overlap) and the fleet's Netherlands TenderNed and other national procurement cells. It shares its zip/OCDS engineering with the fleet's other records Actors.

# Actor input Schema

## `month` (type: `string`):

Which month's OCDS export to pull (YYYY-MM). One month is one partition; 2026-08 holds ~22,892 releases. The archive spans multiple months.

## `maxRecords` (type: `integer`):

Maximum releases delivered and billed within the month. You are billed only for records delivered.

## Actor input object example

```json
{
  "month": "2026-08",
  "maxRecords": 500
}
```

# Actor output Schema

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

The delivered Germany OCDS procurement release record.

# 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 = {
    "month": "2026-08",
    "maxRecords": 500
};

// Run the Actor and wait for it to finish
const run = await client.actor("nexgensignal/de-public-procurement-notice-records").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 = {
    "month": "2026-08",
    "maxRecords": 500,
}

# Run the Actor and wait for it to finish
run = client.actor("nexgensignal/de-public-procurement-notice-records").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 '{
  "month": "2026-08",
  "maxRecords": 500
}' |
apify call nexgensignal/de-public-procurement-notice-records --silent --output-dataset

```

## MCP server setup

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

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/RM5iZdM8l9xUs6evV/builds/qiksNcggp59FVu647/openapi.json
