# ClinicalTrials.gov + FDA Orange Book - Trial Delta API (`stefano_seggio/clinicaltrials-orange-book-delta`) Actor

Delta-tracks ClinicalTrials.gov status changes (RECRUITING, COMPLETED, TERMINATED) and FDA Orange Book patent/exclusivity data from live public APIs. Fingerprint-based diffing returns only new or changed records as structured JSON, with full-jitter retry and ISO 8601 timestamps.

- **URL**: https://apify.com/stefano\_seggio/clinicaltrials-orange-book-delta.md
- **Developed by:** [Stefano Seggio](https://apify.com/stefano_seggio) (community)
- **Categories:** Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 new or changed trial/patent records

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

## ClinicalTrials.gov + FDA Orange Book - Trial Delta API

#### Stop re-scraping trials that haven't changed â€” get paid-for updates only when a trial's status or a drug's patent protection actually moves

Clinical trial status shifts â€” a study moves from RECRUITING to COMPLETED or gets TERMINATED â€” and Orange Book patent/exclusivity data updates on its own schedule, but most monitoring setups re-pull the entire dataset every time just to catch the handful of records that changed. That means paying for and processing thousands of identical rows over and over. **This Actor solves that**: it fingerprints every trial and Orange Book record on each run and only delivers what's new or changed.

***

### Why this outperforms a standard scraper

- **Delta tracking, not re-scraping.** Every record is fingerprinted on every run. Unchanged records are never re-delivered â€” and never billed.
- **Pay only for what's new.** You're charged $0.002 only for a trial whose status changed (RECRUITING â†’ COMPLETED â†’ TERMINATED, etc.) or for a new or changed FDA Orange Book patent/exclusivity record. A run that finds nothing new costs nothing beyond the flat actor-start fee.
- **Two regulatory sources, one delta engine.** `sources` lets you query ClinicalTrials.gov and FDA Orange Book through the same fingerprint-diffing pipeline, so you can track a drug's trial pipeline and its patent/exclusivity runway from a single actor run, backed by full-jitter retry and strict ISO 8601 timestamps for clean downstream processing.

### See it before you trust it

```json
{
  "sources": ["clinicaltrials", "orangebook"],
  "condition": "diabetes",
  "orangeBookQuery": "metformin",
  "maxPages": 20,
  "onlyChanged": true
}
```

`onlyChanged` combined with the fingerprint engine is what makes this valuable â€” flip it to `true` and every record returned is a status change or a new patent/exclusivity entry worth acting on, not noise you already have.

### Zero-risk trial

Unchanged records cost **$0.00**. Run it once against real data before you commit to anything:

```bash
curl -X POST "https://api.apify.com/v2/acts/PkYgfW33Sh6teGXUX/run-sync-get-dataset-items?token=<YOUR_API_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"sources":["clinicaltrials"],"condition":"diabetes","maxPages":20,"onlyChanged":true}'
```

```python
import requests

response = requests.post(
    "https://api.apify.com/v2/acts/PkYgfW33Sh6teGXUX/run-sync-get-dataset-items",
    params={"token": "<YOUR_API_TOKEN>"},
    json={"sources": ["clinicaltrials"], "condition": "diabetes", "maxPages": 20, "onlyChanged": True},
)
records = response.json()
print(f"{len(records)} records returned")
```

```javascript
const response = await fetch(
  "https://api.apify.com/v2/acts/PkYgfW33Sh6teGXUX/run-sync-get-dataset-items?token=<YOUR_API_TOKEN>",
  {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ sources: ["clinicaltrials"], condition: "diabetes", maxPages: 20, onlyChanged: true }),
  }
);
const records = await response.json();
console.log(records.length + " records returned");
```

### Pricing

| Event | What it means | Price |
|---|---|---|
| New or changed trial/patent record | A trial whose status changed, or a new/changed Orange Book patent/exclusivity record. | $0.002 |

Actor-start fee: $0.00005/GB-memory (one-time per run, not per record).

### What you get on every record

- Trial status tracking across RECRUITING, COMPLETED, and TERMINATED states, sourced directly from ClinicalTrials.gov
- FDA Orange Book patent and exclusivity data cross-referenced alongside trial records
- Fingerprint-based diffing so only genuinely new or changed records are delivered per run
- Full-jitter retry logic to handle upstream API instability without duplicate or dropped records
- Strict ISO 8601 timestamps on every record for reliable downstream date handling

### Input parameters

| Field | Type | Description | Default |
|---|---|---|---|
| sources | array | clinicaltrials and/or orangebook. | `['clinicaltrials']` |
| condition | string | Passed to ClinicalTrials.gov's query.cond parameter, e.g. 'diabetes'. | none (all) |
| orangeBookQuery | string | Filter for Orange Book query â€” an ingredient name or application number. | none |
| maxPages | integer | Hard cap on 100-record ClinicalTrials.gov API pages walked per run. | 20 |
| onlyChanged | boolean | Returns only trials/products new or whose tracked fields (status, patent/exclusivity) changed. | false |

### Source & reliability

Data is pulled directly from ClinicalTrials.gov and the FDA Orange Book â€” verified live public APIs, not a scraped or cached mirror. Runs use full-jitter retry to absorb upstream rate limits or transient failures without corrupting the delta record, and every timestamp is normalized to strict ISO 8601 so trial and patent data can be joined reliably across runs.

# Actor input Schema

## `sources` (type: `array`):

clinicaltrials = ClinicalTrials.gov API v2 trial-status delta tracking. orangebook = FDA Orange Book patent/exclusivity delta tracking.

## `condition` (type: `string`):

Passed to ClinicalTrials.gov's query.cond parameter, e.g. 'diabetes'. Leave empty to walk all trials matching other filters (not recommended without a narrow maxPages).

## `orangeBookQuery` (type: `string`):

Filter applied to the Orange Book query - an ingredient name or application number.

## `maxPages` (type: `integer`):

Hard cap on the number of 100-record ClinicalTrials.gov API pages walked per run.

## `onlyChanged` (type: `boolean`):

Returns only trials/products that are new or whose tracked fields (overall\_status, patent/exclusivity data) changed since a previous run. State persists in a named key-value store unique to this actor across scheduled runs.

## `maxRetries` (type: `integer`):

Maximum retry attempts (full-jitter exponential backoff) for a single page/extract fetch before it is dead-lettered.

## `fdaApiKey` (type: `string`):

Optional. openFDA allows 1,000 requests/day without a key (240/min) or 120,000/day with a free key (still 240/min). Only matters for high-volume Orange Book runs - the ClinicalTrials.gov source does not use this key.

## `watchlistKeywords` (type: `array`):

Optional keywords, drug/ingredient/trade names, sponsor names, or application numbers to watch for. Matched case-insensitively against each delivered record's NCT ID, brief title, lead sponsor, conditions (ClinicalTrials.gov records) or application number, trade name, ingredient (Orange Book records). Each delivered record that matches at least one keyword also charges the additional 'watchlist-hit' event, separate from and in addition to the 'result' event every delivered record already charges. Leave empty to disable (no watchlist-hit charges will ever occur).

## Actor input object example

```json
{
  "sources": [
    "clinicaltrials"
  ],
  "maxPages": 20,
  "onlyChanged": true,
  "maxRetries": 5,
  "watchlistKeywords": []
}
```

# Actor output Schema

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

No description

## `resultsNewestFirst` (type: `string`):

No description

## `csv` (type: `string`):

No description

## `excel` (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 = {
    "onlyChanged": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("stefano_seggio/clinicaltrials-orange-book-delta").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 = { "onlyChanged": True }

# Run the Actor and wait for it to finish
run = client.actor("stefano_seggio/clinicaltrials-orange-book-delta").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 '{
  "onlyChanged": true
}' |
apify call stefano_seggio/clinicaltrials-orange-book-delta --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,stefano_seggio/clinicaltrials-orange-book-delta"
        }
    }
}
```

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/PkYgfW33Sh6teGXUX/builds/0q7xP4fnzmFgcbzhx/openapi.json
