Skip to content

Ci Watchlist Api

JSON API for the external CI Monitor frontend application.

All endpoints require JWT authentication via Authorization: Bearer <token> header. Base path: /api/ci_watchlists

Key format: The backend outputs snake_case keys. OliveBranch middleware transforms to camelCase when the client sends X-Key-Inflection: camel. Examples below show snake_case (backend output).


Returns option metadata for the watchlist builder UI.

Response:

{
"data": {
"monitoringCategories": [
{
"key": "clinical_results",
"label": "Clinical Results",
"description": "New efficacy and safety data...",
"iconKey": "chart-bar",
"defaultSelected": true,
"enabled": true,
"disabledReason": null
},
{
"key": "press_releases",
"label": "Press Releases",
"description": "Company announcements...",
"iconKey": "newspaper",
"defaultSelected": false,
"enabled": false,
"disabledReason": "Coming soon — press release monitoring is planned for a future release."
}
],
"stages": [
{ "value": "early_stage", "label": "Early stage" },
{ "value": "metastatic", "label": "Metastatic" }
],
"treatmentLines": [
{ "value": "1L", "label": "1L" },
{ "value": "2L", "label": "2L" }
]
}
}

Disease, technology, target, and biomarker options are fetched via existing /api/diseases, /api/technologies, /api/targets, and /api/biomarkers search endpoints. Each returns BioLoupe entity IDs.


Preview watchlist membership without persisting.

Request:

{
"disease_ids": [123],
"stages": ["metastatic"],
"treatment_lines": ["1L", "2L"],
"target_ids": [456],
"technology_ids": [789],
"selected_categories": ["clinical_results", "trial_changes", "new_trials", "new_drugs"]
}

Response:

{
"data": {
"criteria": {
"disease_ids": [123],
"stages": ["metastatic"],
"treatment_lines": ["1L", "2L"],
"target_ids": [456],
"technology_ids": [789]
},
"matchSummary": {
"activeDrugs": 42,
"ongoingTrials": 108
},
"matchBreakdown": [
{ "label": "Monoclonal Antibody", "count": 15, "proportion": 0.357 },
{ "label": "Small Molecule", "count": 12, "proportion": 0.286 }
],
"sampleDrugs": [
{
"drugId": 101,
"drugName": "Pembrolizumab",
"technologyName": "Monoclonal Antibody",
"targetNames": "PD-1",
"companyName": "Merck & Co.",
"developmentStatus": "drug_marketed",
"highestPhase": "APPROVED",
"ongoingTrialCount": 24
}
]
}
}

Validation errors: Returns 422 with { "error": "Invalid criteria", "errors": [...] } when disease_ids is empty, categories are invalid, or text-only entity criteria are submitted.


Create a persisted watchlist.

Request:

{
"name": "mCRC Competitive Intelligence",
"disease_ids": [123],
"stages": ["metastatic"],
"treatment_lines": ["1L"],
"target_ids": [],
"technology_ids": [],
"selected_categories": ["clinical_results", "trial_changes", "new_trials", "new_drugs"]
}

Response (201):

{
"data": {
"id": 1,
"name": "mCRC Competitive Intelligence",
"status": "active",
"criteria": { "disease_ids": [123], "stages": ["metastatic"], "treatment_lines": ["1L"] },
"selectedCategories": ["clinical_results", "trial_changes", "new_trials", "new_drugs"],
"matchSummary": { "activeDrugs": 42, "ongoingTrials": 108 },
"unreadEventCount": 0,
"lastRefreshedAt": "2026-04-27T10:00:00Z",
"createdAt": "2026-04-27T10:00:00Z",
"updatedAt": "2026-04-27T10:00:00Z",
"items": {
"drugs": [
{
"id": 1,
"drugId": 101,
"drugName": "Pembrolizumab",
"technologyName": "Monoclonal Antibody",
"drugStatus": "drug_marketed",
"pinned": false,
"muted": false,
"excluded": false,
"inclusionReason": "criteria_match",
"source": "auto"
}
],
"trials": [
{
"id": 50,
"trialId": 500,
"nctId": "NCT12345678",
"briefTitle": "A Phase III Study of...",
"phase": "PHASE3",
"overallStatus": "RECRUITING",
"parentItemId": 1,
"pinned": false,
"muted": false,
"excluded": false,
"inclusionReason": "criteria_match",
"source": "auto"
}
]
}
}
}

Returns full watchlist detail with items and event counts.


Update watchlist name or status.

Request: { "name": "New Name" } or { "status": "archived" }


PATCH /api/ci_watchlists/:id/items/:item_id

Section titled “PATCH /api/ci_watchlists/:id/items/:item_id”

Update item curation flags.

Request: { "pinned": true } or { "muted": true } or { "excluded": true }

Response: Updated item object.


Queue or run a watchlist refresh.

Response:

{
"data": {
"refreshRunId": 5,
"status": "completed",
"startedAt": "2026-04-27T10:00:00Z",
"watchlistId": 1
}
}

If a refresh is already running, returns the existing run state without starting a duplicate.


List monitoring events with filtering and pagination.

Query parameters:

  • category — filter by event category
  • priority — filter by priority (high, medium, low)
  • user_status_filter — filter by user status (unread, read, dismissed)
  • since — events detected after this timestamp
  • until — events detected before this timestamp
  • page — pagination page number
  • per_page — items per page (default 25)

Response:

{
"data": [
{
"id": 1,
"category": "clinical_results",
"priority": "medium",
"summary": "New clinical results for Pembrolizumab (NCT12345678)...",
"sourceType": "Publication",
"sourceId": 999,
"watchlistItemId": 1,
"userStatus": "unread",
"detectedAt": "2026-04-27T09:00:00Z",
"createdAt": "2026-04-27T09:00:00Z"
}
],
"meta": {
"current_page": 1,
"total_pages": 3,
"total_count": 52,
"per_page": 25
}
}

PATCH /api/ci_watchlists/:id/events/:event_id

Section titled “PATCH /api/ci_watchlists/:id/events/:event_id”

Update event user status.

Request: { "user_status": "read" } or { "user_status": "dismissed" }


Categories returned with enabled: false are planned for future releases:

  • press_releases — Company press release monitoring
  • regulatory — FDA/EMA regulatory action monitoring
  • comparative_analytics — Cross-program benchmarking

The frontend should render these as disabled or hidden based on the enabled and disabledReason fields.

  • Watchlist membership is deterministic (BioLoupe data only, no LLM-driven membership)
  • Event detection covers: clinical results, trial changes, new drugs, new trials
  • No email digest, PowerPoint export, or comparative analytics
  • No UI in this Rails app — frontend is a separate application