Ci Watchlist Api
CI Watchlist API
Section titled “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).
GET /api/ci_watchlists/filter_options
Section titled “GET /api/ci_watchlists/filter_options”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.
POST /api/ci_watchlists/preview
Section titled “POST /api/ci_watchlists/preview”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.
POST /api/ci_watchlists
Section titled “POST /api/ci_watchlists”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" } ] } }}GET /api/ci_watchlists/:id
Section titled “GET /api/ci_watchlists/:id”Returns full watchlist detail with items and event counts.
PATCH /api/ci_watchlists/:id
Section titled “PATCH /api/ci_watchlists/:id”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.
POST /api/ci_watchlists/:id/refresh
Section titled “POST /api/ci_watchlists/:id/refresh”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.
GET /api/ci_watchlists/:id/events
Section titled “GET /api/ci_watchlists/:id/events”List monitoring events with filtering and pagination.
Query parameters:
category— filter by event categorypriority— filter by priority (high, medium, low)user_status_filter— filter by user status (unread, read, dismissed)since— events detected after this timestampuntil— events detected before this timestamppage— pagination page numberper_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" }
Deferred Categories
Section titled “Deferred Categories”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.
MVP Limitations
Section titled “MVP Limitations”- 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