# EUDAMED Device Search & Export (`yuancore/eudamed-device-monitor`) Actor

Search and export EU EUDAMED device records in Apify-ready datasets. Supports UDI/device filters, pagination, detail enrichment, API use, schedules, and integrations.

- **URL**: https://apify.com/yuancore/eudamed-device-monitor.md
- **Developed by:** [YuanCore](https://apify.com/yuancore) (community)
- **Categories:** Developer tools, Automation, Lead generation
- **Stats:** 2 total users, 1 monthly users, 25.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

## EUDAMED Device Search & Export (EU MDR/IVDR)

Search public **EUDAMED** medical-device records and export normalized results to **JSON, CSV, Excel, XML, or HTML** through Apify.

Use it to turn a registry search into a dataset that can be scheduled, downloaded, queried through the Apify API, or connected to downstream workflows.

> The European Commission launched a documented Public EUDAMED API in 2026. This actor is an Apify-native adapter, not an exclusive data source. It currently uses the public, no-auth endpoint behind the EUDAMED search interface because that payload exposes useful registry fields in a compact shape.

### What this actor is good for

- Export a bounded EUDAMED search without paging through the website manually.
- Normalize UDI, manufacturer, risk-class, status, and version fields into one dataset.
- Schedule repeatable search/export jobs through Apify.
- Feed public device data into spreadsheets, databases, webhooks, or compliance tooling.

### What you get per device

`basicUdi`, `primaryDi`, `uuid`, `deviceName`, `tradeName`, `deviceModel`, `reference`, `riskClass`, `manufacturerName`, `manufacturerSrn`, `deviceStatusType`, `applicableLegislation`, `sterile`, `multiComponent`, `issuingAgency`, `containerPackageCount`, version fields, and `scrapedAt`.

Enable **Fetch full device detail** to attach the richer per-device response. This adds one request per device, so keep the result cap low.

### Input

| Field | Meaning |
|---|---|
| `searchParams` | Advanced filters passed to EUDAMED's public UI-backed endpoint. Leave `{}` to list records without a filter. |
| `maxItems` | Stop after N devices. Use a modest cap; the registry contains millions of records. |
| `pageSize` | Records requested per page through the effective `size` parameter, maximum 300. |
| `fetchDetails` | Fetch the deeper record for each device. Slower: one extra request per device. |
| `includePersonalData` | Include the authorised-representative name. Off by default. |
| `languageIso2Code` | Language for EUDAMED reference labels, default `en`. |

Example:

```json
{
  "searchParams": {
    "deviceStatusCode": "refdata.device-model-status.on-the-market"
  },
  "maxItems": 100,
  "pageSize": 100,
  "fetchDetails": false,
  "includePersonalData": false,
  "languageIso2Code": "en"
}
```

### Change-monitoring status

The former `monitorSince` mode is temporarily unavailable. EUDAMED's current device-list payload exposes `lastUpdateDate` as `null`, so using it as a date cursor would silently return unfiltered data.

Version 0.1.4 rejects legacy `monitorSince` input explicitly instead of presenting a false change feed. Use search/export mode while a trustworthy snapshot-diff or supported update cursor is being evaluated.

### Reliability

- **Schema-drift guard** fails loudly if the list response changes shape or an unfiltered first page unexpectedly becomes empty.
- **Dataset-contract test** validates normalized live records against the actual Apify Dataset Schema, including nullable fields.
- **De-duplication** uses the device version UUID, with a UDI fallback; identity-less records are kept rather than folded together.
- **Core-field completeness** is recorded each run and warns if data quality collapses.
- The automated read-back test (`npm test`) checks the live public endpoint.

### Data and compliance

- Public, no-auth European Commission EUDAMED data only.
- The authorised-representative name can identify a natural person, so it is **redacted by default**. Enable it only when you have a lawful basis.
- Attribute the source as **European Commission – EUDAMED** and follow the Commission's reuse terms.
- This actor is **not affiliated with the European Commission**. Verify important regulatory decisions against the official source.
- Requests use bounded retries and polite pacing.

### FAQ

#### Is there now an official Public EUDAMED API?

Yes. The European Commission's 2026 Public API is open to individuals and organisations, provides GET endpoints for EUDAMED public data, and synchronizes production data on a regular cadence. This actor remains useful when you want Apify-native scheduling, dataset exports, normalized field names, and workflow integration.

#### How do I export to Excel or CSV?

Run a bounded search, open the run's **Storage / Dataset** tab, and choose the required export format. You can also retrieve the dataset through the Apify API.

#### Can I use `monitorSince`?

Not in version 0.1.4. It now fails explicitly because the source list timestamp is nullable. This prevents an apparently successful run from returning the wrong scope.

#### How large should a run be?

Start with 25–100 records and a narrow filter. Increase `maxItems` only after checking runtime and compute usage. Avoid repeated unfiltered full-registry pulls.

# Actor input Schema

## `searchParams` (type: `object`):

Advanced query params passed to EUDAMED's public UI-backed endpoint (e.g. {"deviceStatusCode":"refdata.device-model-status.on-the-market"}). Leave empty {} to list everything.

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

Stop after this many devices. ⚠️ EUDAMED holds millions of records, so a full pull takes hours and consumes significant compute. Keep this modest and use searchParams to narrow the result.

## `pageSize` (type: `integer`):

Devices fetched per API request (the EUDAMED 'size' param, max 300). Larger = fewer requests. Leave at the default unless tuning throughput.

## `fetchDetails` (type: `boolean`):

Also call the per-device detail endpoint (deep fields). ⚠️ Adds 1 API call PER device — keep maxItems low (e.g. ≤500) when enabled, or runs get very slow/expensive. Off by default.

## `includePersonalData` (type: `boolean`):

EUDAMED is public company-level data, but the authorised-representative field can hold an individual's name. Off by default = redacted. Enable only if you have a lawful basis to process it.

## `languageIso2Code` (type: `string`):

ISO 639-1 language code for EUDAMED reference-data labels in the response (e.g. 'en', 'de', 'fr'). Default 'en'.

## Actor input object example

```json
{
  "searchParams": {},
  "maxItems": 25,
  "pageSize": 25,
  "fetchDetails": false,
  "includePersonalData": false,
  "languageIso2Code": "en"
}
```

# 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 = {
    "maxItems": 25,
    "pageSize": 25
};

// Run the Actor and wait for it to finish
const run = await client.actor("yuancore/eudamed-device-monitor").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 = {
    "maxItems": 25,
    "pageSize": 25,
}

# Run the Actor and wait for it to finish
run = client.actor("yuancore/eudamed-device-monitor").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 '{
  "maxItems": 25,
  "pageSize": 25
}' |
apify call yuancore/eudamed-device-monitor --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/2xv5DLna13IyE1AzE/builds/73nX665iYu9JAgH6D/openapi.json
