# Crossref API New Works Feed: New DOIs & Journal Articles (`fecklesspleb/crossref-new-works-feed`) Actor

New journal articles, preprints and datasets registered with Crossref, via the keyless Crossref REST API. Monitor journals (ISSN), publishers, funders or keywords on a schedule; get only new DOIs with title, journal, dates, funders, licences. No author names or abstracts. Unofficial.

- **URL**: https://apify.com/fecklesspleb/crossref-new-works-feed.md
- **Developed by:** [Scott Williams](https://apify.com/fecklesspleb) (community)
- **Categories:** Education, Developer tools, News
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.00 / 1,000 crossref works

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

## Crossref API New Works Feed: New DOIs & Journal Articles

A scheduled feed of **newly registered scholarly works** (journal articles, conference papers, preprints, book chapters, datasets, reports and more), taken from the keyless **Crossref REST API**. Crossref is a DOI registration agency for scholarly content.

Each run returns everything registered in the last N days, or between two dates, newest first. You can narrow it to particular journals (ISSN), publishers (member ID or DOI prefix), funders, work types or keywords. On a schedule, each run returns only DOIs you have not received before.

> **Unofficial.** This Actor is not affiliated with or endorsed by Crossref. Records are copied from Crossref as publishers deposited them, and publishers can correct them later. Check `doiUrl` before you rely on a record.

### Use cases

- **Journal alerts:** get every new article in a list of journals by ISSN, each morning.
- **Publisher monitoring:** follow everything a publisher registers, by Crossref member ID or DOI prefix.
- **Funder reporting:** collect new works that acknowledge a funder, using its Open Funder Registry DOI.
- **Literature monitoring:** a daily keyword feed (for example "perovskite solar") restricted to new journal articles.
- **Corrections and retractions:** the `updatesTo` field shows which DOI a correction or retraction notice updates.
- **Open-licence collections:** keep only works with a Creative Commons licence.
- **Data pipelines:** send each run to Google Sheets, a webhook, Slack or your database with Apify integrations.

### What you get

| Field | Example |
|---|---|
| `doi`, `doiUrl`, `crossrefApiUrl` | `10.1007/s10735-026-11019-3`, `https://doi.org/10.1007/s10735-026-11019-3` |
| `type`, `title`, `subtitle`, `originalTitle` | `journal-article`, "Circ_0018814 promotes the osteogenic differentiation ..." |
| `containerTitle`, `shortContainerTitle`, `issnPrint`, `issnElectronic`, `issns`, `isbns` | "Journal of Molecular Histology", `1567-2379`, `1567-2387` |
| `publisher`, `crossrefMemberId`, `doiPrefix` | "Springer Science and Business Media LLC", `297`, `10.1007` |
| `publishedDate`, `publishedPrint`, `publishedOnline` | `2026-11-01`. A value can be `YYYY`, `YYYY-MM` or `YYYY-MM-DD`. |
| `createdAt`, `depositedAt` | When the DOI was first registered and when its metadata was last deposited (UTC) |
| `volume`, `issue`, `page`, `articleNumber`, `subjects` | |
| `authorCount`, `editorCount`, `hasAbstract` | Counts and flags only |
| `referencesCount`, `citedByCount` | Crossref's reference count and cited-by count |
| `funders` | Name, funder DOI, ROR ID and award numbers. Repeated funders are merged into one entry. |
| `licences`, `hasCreativeCommonsLicence` | Licence URL, content version, start date, embargo days |
| `updatesTo` | For a correction or retraction notice, the DOI it updates |
| `source`, `licenceNote`, `scrapedAt` | |

An example record from a run on 1 November 2026 (shortened):

```json
{
  "doi": "10.1007/s10735-026-11019-3",
  "type": "journal-article",
  "title": "Circ_0018814 promotes the osteogenic differentiation of mesenchymal stem cells in ankylosing spondylitis by regulating the miR-944/KLF4 axis",
  "containerTitle": "Journal of Molecular Histology",
  "issns": ["1567-2379", "1567-2387"],
  "publisher": "Springer Science and Business Media LLC",
  "crossrefMemberId": "297",
  "publishedDate": "2026-11-01",
  "createdAt": "2026-11-01T15:58:57Z",
  "authorCount": 6,
  "referencesCount": 50,
  "funders": [{"name": "Preliminary Research Project of the National Natural Science Foundation of China", "funderDoi": null, "ror": "https://ror.org/01h0zpd94", "awards": ["2025GZRYSY011"]}],
  "hasCreativeCommonsLicence": true,
  "updatesTo": []
}
```

Each run also writes a `RUN_SUMMARY` record to the key-value store. It shows how many works matched (`stats.totalResults`), how many were saved or skipped, and how many requests the run made.

### Input

| Input | Default | Notes |
|---|---|---|
| `mode` | `daily_feed` | `daily_feed` reads the last `lookbackDays` (default 1, meaning yesterday and today, UTC). `date_range` reads from `startDate` to `endDate`, up to 10 years. |
| `dateField` | `created` | `created` is when the DOI was first registered: the best choice for "new works". The other options are `published`, `indexed` (any change) and `deposited`. Results are sorted newest first by this field. |
| `types` | `["journal-article"]` | Any Crossref work type. Use `[]` for all types. |
| `query` | none | Bibliographic keywords. The date range and newest-first order still apply: results are sorted by date, not by relevance. Crossref's keyword matching is loose, so not every result contains every word (in one test only 28 of 246 `perovskite solar` matches had both words in the title). For precision, use the ISSN, DOI prefix, member, funder or type filters, or a narrower phrase. |
| `issns`, `doiPrefixes`, `memberIds`, `funderDois` | none | Up to 50 values each. Values in one list are combined with OR; different lists are combined with AND. |
| `hasAbstract`, `hasFunder`, `creativeCommonsOnly` | off | Works removed by the Creative Commons filter are not charged. |
| `maxItems` | 9 | The cap is 9 works (about $0.009) by default, including empty input `{}` from the API, CLI or a schedule. Raise it up to 100,000. The minimum is 1; there is no unlimited setting. |
| `onlyNewSinceLastRun`, `stateKey` | `auto`, `default` | With `auto`, results are deduplicated in daily feed mode. Use a separate key for each schedule. Each key remembers at most 200,000 DOIs; beyond that the earliest-saved DOIs are dropped, so they can be returned (and charged) again if a later run's date range still covers them. |

Example: new NSF-funded work in two journals, checked every day:

```json
{"lookbackDays": 2, "issns": ["0028-0836", "0036-8075"], "funderDois": ["10.13039/100000001"], "maxItems": 500}
```

#### Finding the IDs

- **Journal ISSN:** on the journal's website, or search `https://api.crossref.org/journals?query=<journal name>`.
- **Publisher member ID:** search `https://api.crossref.org/members?query=<publisher name>` and use the `id`.
- **Funder DOI:** search `https://api.crossref.org/funders?query=<funder name>`. The DOI is `10.13039/` followed by the `id`.

### Getting a complete daily feed

Results come newest first, and a run stops at `maxItems`. If more works match than `maxItems` allows, the run saves only the newest ones. Older works in the window can then age out of the look-back without ever being returned.

For a complete feed:

1. Filter narrowly (journals, publisher, funder or keywords).
2. Run once and read `stats.totalResults` in `RUN_SUMMARY`.
3. Set `maxItems` comfortably above that number.

`stoppedByMaxItems: true` in `RUN_SUMMARY` means the run hit the cap.

### How to schedule it

1. Save your input as a task.
2. Add a daily schedule in Apify Console (Schedules, then Create new).
3. Keep `mode` as `daily_feed` and give each scheduled task its own `stateKey`.
4. Optionally add an integration (Google Sheets, Slack, webhook) to send each run's new works on.

### Pricing

Pay per event: **$0.001 per work** saved. There is no start fee and there are no other events. Works skipped by deduplication or by the Creative Commons filter are free.

- By default a run returns at most 9 works, which costs at most $0.009.
- 1,000 works cost $1.00. Setting a maximum cost per run stops the run early.

**How many works is a day?** On a weekday Crossref registers roughly 27,000 to 35,000 new journal articles, and roughly 42,000 to 87,000 works of all types (Crossref counts by created date for Monday 26 to Friday 30 October 2026). Weekends are lower. Covering everything would cost tens of dollars a day, so use filters.

### Licence and privacy

- Crossref states: *"almost none of the metadata is subject to copyright, and you may use it for any purpose. Some abstracts contained in the metadata may be subject to copyright by publishers or authors."*
- The Actor therefore **never outputs abstracts**. `hasAbstract` only tells you whether one is on file.
- **Author, editor and other contributor names, ORCID iDs and affiliations are never output.** The Actor returns only the counts (`authorCount`, `editorCount`). To see who wrote a work, open its DOI.
- No account, API key or email address is needed.

### How it works

- **robots.txt:** the Actor checks `https://api.crossref.org/robots.txt` first. It currently returns 404, which means there are no rules. If the file ever disallows `/works`, the Actor stops.
- **Request rate:** it sends at most **1 request per second**, one at a time. That matches the public pool's `x-rate-limit-limit: 1`, `x-rate-limit-interval: 1s` and `x-concurrency-limit: 1` headers. Crossref currently allows filtered list requests at 1 per second in the public pool and 3 per second in its polite pool. The Actor uses 1 per second in both.
- **Errors and blocks:** it respects `Retry-After` and backs off on 429 and 5xx responses. If the API answers 403 or returns something that is not JSON, the Actor stops cleanly; it never tries to get past a block.
- **Paging:** results are paged with Crossref cursors, at most 1,000 rows per page. Each page asks only for the rows the run still needs, so a default run of 9 works makes one data request.
- **Run time:** a small run (`maxItems` 9 or less) ends well inside a minute. Every run stops starting requests 20 seconds before its timeout, so it ends SUCCEEDED with what it has.
- **When nothing could be saved:** if the API is down or nothing matched, the dataset gets one free record `{"type": "status", "status": "warning", ...}` with the reason. Filter on `type` if you only want works.
- **Invalid input:** if the input cannot be used (for example an unknown `types` value, a bad date or a field of the wrong type), nothing is fetched and the run still ends SUCCEEDED with one free record `{"recordType": "status", "type": "status", "status": "error", "statusRow": true, "charged": false, "message": "Invalid input, nothing was fetched or charged: <reason>", ...}`. No works are charged.
- **Fields requested:** `select=` asks only for the fields needed for the output above. Contributor lists and abstracts are requested only to compute `authorCount`, `editorCount` and `hasAbstract`; they are dropped in memory and never stored.

### Limits

- A new record can take minutes to a few hours to show up in the Crossref API after its DOI is registered. The default look-back of yesterday plus today catches late arrivals.
- The dedupe memory holds at most 200,000 DOIs per state key. When it is full, the earliest-saved DOIs are dropped first. A broad feed with a long look-back can reach this, and dropped DOIs can then be returned again.
- A run that stops at `maxItems` saves the newest matches only; see "Getting a complete daily feed".
- Crossref metadata is only as complete as each publisher's deposit. Fields such as funders, licences, abstracts and subjects are often missing.
- The Actor reads only Crossref metadata. It does not include full text, PDFs or citation lists.

### FAQ

**Why are there no author names?**
Privacy. The Actor outputs counts only. The DOI link shows the full record.

**How fast do new works appear?**
`createdAt` is when the DOI was first registered. A record can take minutes to a few hours to appear in the Crossref API. The default look-back (yesterday plus today) catches late arrivals, and deduplication stops repeats.

**How long does deduplication remember?**
The last 200,000 DOIs per state key.

**Is this complete?**
It returns what Crossref has, up to your `maxItems`; see "Getting a complete daily feed". Crossref metadata is only as complete as each publisher's deposit. Funders, licences, abstracts and subjects are often missing.

**Does it include full text or PDFs?**
No. It reads only Crossref metadata.

# Changelog

This Actor's version history is a separate document: https://apify.com/fecklesspleb/crossref-new-works-feed/changelog.md

# Actor input Schema

## `mode` (type: `string`):

Daily feed: works from the last N days, skipping DOIs already saved by earlier runs with the same state key. Date range: everything between two dates.

## `lookbackDays` (type: `integer`):

Daily feed only. 0 = today only (UTC), 1 = yesterday and today.

## `startDate` (type: `string`):

Date range only, e.g. 2026-10-01 (UTC, inclusive).

## `endDate` (type: `string`):

Date range only (inclusive). Empty = today.

## `dateField` (type: `string`):

Which Crossref date the range and the newest-first order use.

## `types` (type: `array`):

Crossref work types. Empty list = all types. Default: journal articles.

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

Optional bibliographic keywords (title, journal, ...). Results are still sorted newest first by the chosen date field, not by relevance, and the date range still applies. Crossref's keyword matching is loose: not every result contains every word (in one test only 28 of 246 'perovskite solar' matches had both words in the title). For precision, use filters (ISSN, DOI prefix, member, funder, type) or a narrower phrase.

## `issns` (type: `array`):

Only works in these journals, e.g. 0028-0836. Up to 50.

## `doiPrefixes` (type: `array`):

Only works with these DOI prefixes, e.g. 10.1038. Up to 50.

## `memberIds` (type: `array`):

Only works from these publishers (Crossref member id, e.g. 297 = Springer). Up to 50.

## `funderDois` (type: `array`):

Only works acknowledging these funders (Open Funder Registry DOI, e.g. 10.13039/100000001 = NSF). Up to 50.

## `hasAbstract` (type: `boolean`):

The abstract itself is never output.

## `hasFunder` (type: `boolean`):

Only works whose Crossref record lists at least one funder.

## `creativeCommonsOnly` (type: `boolean`):

Keep only works whose Crossref licence list includes a creativecommons.org licence.

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

Stop after this many works (charged per work). Default 9 (about $0.009), also when left empty. Minimum 1, maximum 100,000; there is no unlimited setting. A weekday brings roughly 27,000 to 35,000 new journal articles, so for a complete daily feed use filters and set this above your expected daily count.

## `onlyNewSinceLastRun` (type: `string`):

Skip DOIs saved by earlier runs with the same state key. Each state key remembers at most 200,000 DOIs. Beyond that, the earliest-saved DOIs are dropped from the list, so they can be returned (and charged) again if they are still inside the date range of a later run.

## `stateKey` (type: `string`):

Use different keys for different scheduled feeds so they keep separate 'seen' lists.

## Actor input object example

```json
{
  "mode": "daily_feed",
  "lookbackDays": 1,
  "dateField": "created",
  "types": [
    "journal-article"
  ],
  "hasAbstract": false,
  "hasFunder": false,
  "creativeCommonsOnly": false,
  "maxItems": 9,
  "onlyNewSinceLastRun": "auto",
  "stateKey": "default"
}
```

# Actor output Schema

## `documents` (type: `string`):

No description

## `summary` (type: `string`):

No description

# 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 = {
    "types": [
        "journal-article"
    ],
    "maxItems": 9
};

// Run the Actor and wait for it to finish
const run = await client.actor("fecklesspleb/crossref-new-works-feed").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 = {
    "types": ["journal-article"],
    "maxItems": 9,
}

# Run the Actor and wait for it to finish
run = client.actor("fecklesspleb/crossref-new-works-feed").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 '{
  "types": [
    "journal-article"
  ],
  "maxItems": 9
}' |
apify call fecklesspleb/crossref-new-works-feed --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,fecklesspleb/crossref-new-works-feed"
        }
    }
}
```

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/sbvGRz3qVeaimB2vv/builds/PV6YWAdumPmZyAAjH/openapi.json
