# PubMed Article Monitor (`artemi_kupolov/pubmed-article-monitor`) Actor

Monitor new PubMed articles by query, publication type and date via the official NCBI E-utilities (esearch, esummary, efetch). Incremental 'new since last run' monitoring, a markdown digest and an optional webhook. No API key required at 3 requests/second, no scraping.

- **URL**: https://apify.com/artemi_kupolov/pubmed-article-monitor.md
- **Developed by:** [Artemi Kupolov](https://apify.com/artemi_kupolov) (community)
- **Categories:** Developer tools, Automation, AI
- **Features:** Limited permissions
- **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/actors/running/actors-in-store.md#pay-per-usage

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

## PubMed Article Monitor

Monitor **new scientific articles in PubMed** by keyword, MeSH term, author, journal or any other PubMed query, through the **official NCBI E-utilities**. No HTML scraping, no API key required at three requests per second, no bypass of any protection.

Use it as a one-off search or as a scheduled watch that only returns **new articles since the last run**.

Sources (official):

- [`esearch.fcgi`](https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi) — find PMIDs
- [`esummary.fcgi`](https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi) — document summaries
- [`efetch.fcgi`](https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi) — full Medline records (title, authors, journal, date, DOI, abstract, MeSH)

Every request sends the `tool` and `email` parameters NCBI asks for, and the Actor stays at or below **3 requests per second** without a key (or 10 r/s if you provide your own NCBI API key).

### Why this Actor

PubMed is the standard bibliographic database for biomedical and life-science literature. This Actor turns a PubMed search into a clean, Google-Sheets-ready dataset:

- **Familiar query language** — any PubMed term, including field tags such as `[Title]`, `[Author]`, `[Journal]` or `[MeSH Terms]`.
- **Publication type and date window** — filter to journal articles, reviews, trials, preprints and more; default window is the last 7 days on the Entrez entry date (`edat`), which is what you want for a "what's new" monitor.
- **Incremental monitoring** — `sinceLastRun` + `onlyNew` store seen PMIDs and the last date in a key-value store, so a daily schedule only costs you the new rows.
- **Flat, useful rows** — title, authors, journal, date, DOI, PMID, abstract, MeSH terms and the official PubMed link.
- **Digest and webhook** — an email-friendly markdown digest is saved to the key-value store; optionally POSTed to a URL you provide. The Actor never sends email itself.

### Use cases

- **Topic watch** — schedule a daily run for `mRNA vaccine`, `CRISPR[Title]` or a MeSH term, and forward the digest to Slack or Make via `webhookUrl`.
- **Author or journal alerts** — follow a lab (`Smith J[Author]`) or a journal (`Nature[Journal]`) without leaving PubMed's official API.
- **Evidence reviews** — pull 30 or 90 days of systematic reviews and meta-analyses into a spreadsheet, with abstracts and MeSH already filled in.
- **RAG / research pipelines** — drop new papers into a dataset on a schedule, with DOI and abstract ready for downstream tools.

### Input highlights

| Field | What it does |
| --- | --- |
| `query` | PubMed search term (`mRNA vaccine`, `CRISPR[Title]`, `Smith J[Author]`) |
| `publicationTypes` | `Journal Article`, `Review`, `Systematic Review`, `Meta-Analysis`, `Clinical Trial`, `RCT`, `Preprint`, … |
| `dateType` | `edat` (entry date, default), `pdat` (publication date), `mhdat`, `mdat` |
| `datePreset` | `last_24_hours`, `last_7_days` (default), `last_30_days`, `last_90_days`, `ytd`, `custom`, `since_last_run` |
| `sinceLastRun` + `onlyNew` + `monitorKey` | Incremental watch; use a distinct `monitorKey` per schedule |
| `webhookUrl` | HTTPS endpoint that receives the digest of *new* articles |
| `maxItems` | 1–10 000, default 100 |
| `tool` / `email` | Official E-utilities identification (defaults are filled in) |
| `ncbiApiKey` | Optional; only needed above 3 requests per second |

The default date window is **the last 7 days**, so a run never asks PubMed for the entire archive.

#### Example: new mRNA-vaccine papers this week

```json
{
  "query": "mRNA vaccine",
  "publicationTypes": ["Journal Article", "Review"],
  "datePreset": "last_7_days",
  "dateType": "edat",
  "sinceLastRun": false,
  "maxItems": 50,
  "includeDigest": true,
  "monitorKey": "mrna-vaccine"
}
```

#### Example: incremental daily watch

```json
{
  "query": "CRISPR[Title]",
  "publicationTypes": ["Journal Article"],
  "datePreset": "since_last_run",
  "dateType": "edat",
  "sinceLastRun": true,
  "onlyNew": true,
  "maxItems": 200,
  "webhookUrl": "https://example.com/hooks/pubmed",
  "monitorKey": "crispr-title-daily"
}
```

### Output

Each dataset item is one article. The most useful fields:

| Field | Contents |
| --- | --- |
| `pmid` | PubMed identifier |
| `title` | Article title |
| `authors` / `authorsText` | Author list, and the same names joined with `; ` |
| `journal` / `journalAbbrev` | Full journal title and ISO abbreviation |
| `publicationDate` | Best available date (`YYYY-MM-DD` when the day is known) |
| `doi` / `doiUrl` | Digital Object Identifier and `https://doi.org/…` |
| `abstract` | Abstract, with labelled sections kept (`BACKGROUND: …`) |
| `meshTerms` / `meshHeadings` | MeSH descriptors, and descriptor/qualifier pairs |
| `publicationTypes` | e.g. `Journal Article`, `Review` |
| `link` / `pubmedUrl` | Official record, `https://pubmed.ncbi.nlm.nih.gov/{pmid}/` |
| `pmcid` / `pmcUrl` | PubMed Central id and link, when the article is in PMC |
| `isNew` | `true` if this PMID was not in the monitor's seen list |

A markdown digest of *new* articles is written to the key-value store as `digest.md`.

### Pricing and fair use

This Actor is published **free**. A later pay-per-event price of **$3 per 1,000 articles** is documented only as a proposal and is **not enabled**.

The Actor uses the official NCBI E-utilities. Please keep scheduled runs reasonable (a daily or hourly watch on a focused query is fine; do not harvest the entire database). Large jobs should follow [NCBI's usage guidelines](https://www.ncbi.nlm.nih.gov/books/NBK25497/): identify yourself with `tool` and `email`, stay within the rate limit, and prefer evenings and weekends in US Eastern time for very large downloads.

### Changelog

- **0.1** — First public version. esearch + efetch, filters, onlyNew / sinceLastRun, digest, webhook.

# Actor input Schema

## `query` (type: `string`):

A PubMed search term, using the usual field tags if you want them. Examples: `mRNA vaccine`, `CRISPR[Title]`, `Smith J[Author]`, `Nature[Journal]`. Combined with publication type and the date window using AND. Leave empty only if you want every article in the date window (capped by `maxItems`).

## `publicationTypes` (type: `array`):

Official PubMed publication types, AND-ed into the query as `"Journal Article"[Publication Type]`. Short aliases such as `review`, `RCT`, `trial`, `preprint` or `guideline` are also accepted. Leave empty for any type.

## `datePreset` (type: `string`):

Quick window for the date selected in `dateType`. Defaults to the last 7 days so a run never queries the entire PubMed archive. Use `custom` with the date fields below, or `since_last_run` for incremental monitoring.

## `dateType` (type: `string`):

Which PubMed date the window applies to. `edat` (default) is the Entrez / entry date — when the record appeared in PubMed — and is the right choice for a 'what's new' monitor. `pdat` is the publication date, `mhdat` the MeSH date, `mdat` the modification date.

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

Inclusive start of the date range (`YYYY-MM-DD`). Used when `datePreset` is `custom`, or as a floor under `sinceLastRun`. Sent to E-utilities as `mindate`.

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

Inclusive end of the date range (`maxdate`).

## `sinceLastRun` (type: `boolean`):

Set the start date from the previous successful run of this monitor (minus one day of overlap). Combine with `onlyNew` for a scheduled watch.

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

Drop PMIDs stored in the key-value store from a previous run. Seen articles are still counted in the log. Turn off to re-export the full window.

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

Hard cap on articles written to the dataset (1–10 000). Default 100.

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

PMIDs requested per esearch call (10–500, default 200). EFetch then retrieves records in batches of up to 200.

## `includeDigest` (type: `boolean`):

Write an email-friendly markdown digest of *new* articles to the key-value store as `digest.md`.

## `webhookUrl` (type: `string`):

Optional HTTPS URL. When at least one *new* article is found, the Actor POSTs a JSON body with `digest`, `newCount` and the article list. The Actor never sends email itself.

## `monitorKey` (type: `string`):

Namespace for stored seen-PMIDs and the last date. Use a different key for each scheduled watch (for example `mrna-vaccine` vs `crispr-reviews`).

## `tool` (type: `string`):

Value of the official E-utilities `tool` parameter (no spaces). Identifies this software to NCBI. Default `pubmed-article-monitor`.

## `email` (type: `string`):

Value of the official E-utilities `email` parameter. NCBI uses it only to contact the developer if a run violates the usage policy. Default is the Actor author's address; override it with your own if you run this heavily.

## `ncbiApiKey` (type: `string`):

Optional E-utilities API key. Without a key the Actor stays at or below 3 requests per second (the official limit). With a key the cap is 10 r/s and the default delay is lowered. Get a key from your NCBI account settings. Leave empty unless you need a higher rate.

## `requestDelaySecs` (type: `number`):

Pause before each E-utilities request. Default 0.4 s (just under 3 r/s) without a key, or 0.12 s with a key. The Actor will not go below the official rate limit.

## Actor input object example

```json
{
  "query": "mRNA vaccine",
  "datePreset": "last_7_days",
  "dateType": "edat",
  "sinceLastRun": false,
  "onlyNew": true,
  "maxItems": 100,
  "pageSize": 200,
  "includeDigest": true,
  "monitorKey": "default",
  "tool": "pubmed-article-monitor",
  "email": "artemikupolov@gmail.com",
  "requestDelaySecs": 0.4
}
```

# Actor output Schema

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

One item per article: title, authors, journal, date, DOI, PMID, abstract, MeSH terms and official PubMed link.

# 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 = {
    "query": "mRNA vaccine"
};

// Run the Actor and wait for it to finish
const run = await client.actor("artemi_kupolov/pubmed-article-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 = { "query": "mRNA vaccine" }

# Run the Actor and wait for it to finish
run = client.actor("artemi_kupolov/pubmed-article-monitor").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 '{
  "query": "mRNA vaccine"
}' |
apify call artemi_kupolov/pubmed-article-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,artemi_kupolov/pubmed-article-monitor"
        }
    }
}
```

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/MrZZgbthFwTc9Jcsb/builds/eOAko1u92vCPxo7zZ/openapi.json
