# Clinical Trial Protocol Amendments — ClinicalTrials.gov Diff (`malekh/clinical-trial-protocol-amendments`) Actor

Track what actually changed between ClinicalTrials.gov record versions: primary endpoints re-specified, enrollment cut, eligibility widened, completion dates slipped, trials terminated. Structured before/after diffs with day shifts, percent changes and a critical/major/minor rating.

- **URL**: https://apify.com/malekh/clinical-trial-protocol-amendments.md
- **Developed by:** [Malek H](https://apify.com/malekh) (community)
- **Categories:** Automation, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.01 / 1,000 results

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/platform/actors/running/actors-in-store#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

## Clinical Trial Protocol Amendments — ClinicalTrials.gov version diff

**Find out what actually changed in a clinical trial protocol, amendment by amendment.**

ClinicalTrials.gov keeps every historical version of a study record. What it
does not give you is the *diff*. The site shows one version at a time plus a
list of which modules were touched — so answering "did they change the primary
endpoint?" means opening two versions in two tabs and reading them side by side.
For a portfolio of 100 competitor trials that is not a task anyone does.

This Actor does it for you. Give it NCT IDs, a condition, or a sponsor, and it
returns **one structured record per protocol amendment**, with before/after
values and a significance rating:

- **Primary endpoint re-specified** — outcome measures added, removed or redefined
- **Enrollment cut or raised** — with the delta and percent change
- **Eligibility widened or narrowed** — criteria text, age bounds, sex, healthy volunteers
- **Primary completion date slipped** — with the shift in days
- **Trial terminated, suspended or withdrawn** — with the stated reason
- **Arms and interventions added or dropped**
- **Phase, allocation, masking or primary purpose changed**
- **Lead sponsor or collaborators changed**

### Who this is for

- **Competitive intelligence** — an endpoint change or enrollment cut in a rival's phase 3 is a read on their readout
- **Feasibility and study startup** — see how often a sponsor amends eligibility, and how far completion dates really slip
- **Portfolio and BD teams** — a standing watch list of trials, checked on a schedule
- **Regulatory and medical writing** — reconstruct an amendment history without diffing PDFs by hand
- **Research on protocol amendments** — outcome switching, enrollment attrition, timeline drift, at scale

### Input

```json
{
  "nctIds": ["NCT04368728", { "recordId": "WATCH-17", "nctId": "NCT02576574" }],
  "since": "2024-01-01",
  "minSignificance": "major",
  "maxAmendmentsPerStudy": 20
}
```

Or search instead of listing IDs:

```json
{
  "searchCondition": "glioblastoma",
  "searchSponsor": "Novartis",
  "searchStatus": ["RECRUITING", "ACTIVE_NOT_RECRUITING"],
  "maxStudies": 50,
  "since": "2025-01-01"
}
```

| Field | Default | What it does |
|---|---|---|
| `nctIds` | — | NCT IDs, or objects with your own `recordId` to join results back to your system |
| `searchQuery` | — | Free-text search (`query.term`) |
| `searchCondition` | — | Condition or disease |
| `searchSponsor` | — | Lead sponsor or collaborator |
| `searchStatus` | — | Recruitment statuses, e.g. `["RECRUITING"]` |
| `maxStudies` | 25 | Cap on studies scanned (max 500) |
| `since` | — | Only report amendments on or after this date |
| `minSignificance` | `major` | `critical`, `major` or `minor` |
| `includeMinorChanges` | `false` | Include title, summary, contact and site-count edits |
| `maxAmendmentsPerStudy` | 20 | Most recent N version transitions per study |
| `maxVersionFetches` | 600 | Global budget on historical record fetches |

### Output

One dataset item per amendment. `type` is `amendment`, `no-amendments` or `error`.

```json
{
  "type": "amendment",
  "recordId": "WATCH-17",
  "nctId": "NCT02576574",
  "briefTitle": "…",
  "leadSponsor": "…",
  "amendmentDate": "2022-12-09",
  "fromVersion": 42,
  "toVersion": 43,
  "significance": "critical",
  "categories": ["arms", "endpoints"],
  "summary": "Primary outcome measures: 4 added, 2 removed — a primary endpoint was REMOVED or redefined; Study arms: 3 added, 3 removed",
  "changes": [
    {
      "field": "primaryOutcomes",
      "label": "Primary outcome measures",
      "category": "endpoints",
      "significance": "critical",
      "added": ["Overall survival [Up to 60 months]"],
      "removed": ["Progression-free survival [24 months]"]
    }
  ],
  "recordUrl": "https://clinicaltrials.gov/study/NCT02576574?tab=history"
}
```

Date changes carry `daysShifted`; enrollment changes carry `delta` and
`percentChange`; list fields carry `added` and `removed`.

**Significance** is `critical` for endpoint changes, phase changes,
terminations, enrollment moves of 30%+ and date shifts of six months or more;
`major` for ordinary eligibility, design, arm, sponsor and timeline edits;
`minor` for titles, summaries, site counts and sub-2% enrollment drift.

### Why you can trust a "no amendments" answer

This matters more than any feature. A monitoring tool that quietly returns
"nothing changed" because its data source moved is worse than no tool at all —
you would conclude a competitor's protocol was stable all year.

So this Actor is built to **fail loudly rather than report a clean sheet it
cannot stand behind**:

- Every history and version payload is shape-checked; a missing version list, a
  mismatched version number or a record without its core modules is an error,
  not an empty result.
- A study that does not exist returns `study_not_found`. A record that cannot be
  parsed returns `history_unreadable`. **Neither is ever reported as "no amendments."**
- If more than 25% of scanned studies fail to parse, the **entire run fails** —
  because at that point every clean answer in it is suspect.
- An unrecognised module label is treated as material, so a new
  ClinicalTrials.gov module cannot silently hide amendments.

A `no-amendments` record means exactly what it says: the version history was
read successfully and nothing at or above your significance threshold happened
in the window.

### Data source and licence

[ClinicalTrials.gov](https://clinicaltrials.gov), a service of the US National
Library of Medicine. Records are US Government works in the public domain and
NLM provides them for programmatic reuse. Study search uses the documented
[API v2](https://clinicaltrials.gov/data-api/api); version history uses the
JSON history endpoints behind the site's own "Study Record Versions" tab.
No API key, no scraping, no rate-limit circumvention — requests are throttled
and identify themselves.

Amendment records reflect what sponsors submitted to ClinicalTrials.gov. They
are not a substitute for the sponsor's own protocol amendment documents, and
this Actor is not medical, legal or regulatory advice.

### Pricing

Pay per event, platform costs included:

| Event | Price |
|---|---|
| Study scanned | $0.08 |
| Amendment reported | $0.04 |

Monitoring 100 trials monthly typically runs about **$18/month** — against
enterprise trial-intelligence subscriptions that start in the five figures.

### Tips

- Set `since` to your last run date and schedule this daily or weekly; you get
  only the new amendments.
- Use `recordId` to join output straight back to your watch list.
- Start with `minSignificance: "critical"` on a large portfolio, then widen.
- Deep histories are the expensive part — `maxAmendmentsPerStudy` bounds it.

# Actor input Schema

## `nctIds` (type: `array`):

The trials to diff, by NCT identifier. Case does not matter — "nct01439386" normalises. To carry your own identifier into the output, pass objects instead of strings: {"recordId": "COMP-1", "nctId": "NCT02576574"}; recordId is echoed on every row, including errors. Leave empty and use the search fields below to build the list instead — you can also combine the two, and duplicates are removed.

## `since` (type: `string`):

Ignore protocol changes older than this date (YYYY-MM-DD; a bare year or year-month is accepted). This is the main cost control on an actively-amended trial — a study registered in 2010 can carry 60 versions. Leave empty to diff the study's entire version history.

## `minSignificance` (type: `string`):

How large a change has to be before it is reported. "critical" is reserved for changes that undermine comparability — primary outcome measures re-specified, the trial terminated or withdrawn. "major" adds enrollment and eligibility changes and completion-date slips. "minor" adds everything else, including contact and administrative edits.

## `includeMinorChanges` (type: `boolean`):

Shortcut that forces the minimum significance down to "minor", overriding the setting above. Useful when you want the full audit trail rather than a competitive-intelligence view.

## `searchCondition` (type: `string`):

Build the study list by condition or disease, e.g. "non-small cell lung cancer". Combines with the sponsor, term and status filters; the matched NCT ids are added to anything given above, up to the maximum-studies cap.

## `searchSponsor` (type: `string`):

Build the study list by lead sponsor or collaborator, e.g. "Pfizer". This is the usual way to watch a competitor's whole trial portfolio for protocol changes.

## `searchQuery` (type: `string`):

Free-text search across the study record, passed through to the ClinicalTrials.gov v2 API as query.term. Use for anything the condition and sponsor fields do not cover — an intervention name, a device, a mechanism.

## `searchStatus` (type: `array`):

Restrict the search to these recruitment statuses, e.g. RECRUITING, ACTIVE\_NOT\_RECRUITING, TERMINATED. Applies only to studies found by search, not to NCT ids you supplied directly.

## `maxStudies` (type: `integer`):

Safety cap on how many studies are scanned, counting both the ids you supplied and anything the search adds, so a broad sponsor search cannot run up an unexpected bill. You are charged per study scanned.

## `maxAmendmentsPerStudy` (type: `integer`):

Caps how many amendments are reported for any one study, so a single heavily-revised trial cannot dominate the results. Amendments are reported newest first, so the cap drops the oldest.

## `maxVersionFetches` (type: `integer`):

Hard ceiling on total historical-version fetches across the whole run — the real compute cost here, since each amendment needs the record on both sides of it. Raise it if you are scanning many long-running trials and see the budget reported as exhausted; the default comfortably covers 25 studies.

## Actor input object example

```json
{
  "nctIds": [
    "NCT02576574"
  ],
  "since": "2022-01-01",
  "minSignificance": "major",
  "includeMinorChanges": false,
  "maxStudies": 25,
  "maxAmendmentsPerStudy": 20,
  "maxVersionFetches": 600
}
```

# 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 = {
    "nctIds": [
        "NCT02576574"
    ],
    "since": "2022-01-01"
};

// Run the Actor and wait for it to finish
const run = await client.actor("malekh/clinical-trial-protocol-amendments").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 = {
    "nctIds": ["NCT02576574"],
    "since": "2022-01-01",
}

# Run the Actor and wait for it to finish
run = client.actor("malekh/clinical-trial-protocol-amendments").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 '{
  "nctIds": [
    "NCT02576574"
  ],
  "since": "2022-01-01"
}' |
apify call malekh/clinical-trial-protocol-amendments --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=malekh/clinical-trial-protocol-amendments",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/0rwMHbRnGCUDnUkAf/builds/na29set4yqqqGhyFL/openapi.json
