Back: Research

Janus for researchers

Open data, API, MCP server, CDS Hooks, pipelines and a worked example in one place.

Everything on this page exists in the repository today. Pick a source, run one request, run the example, read the limits. Counts are reports, never people.

Research prototype, not a medical device. Expert review has not yet been done.

Start in ten minutes

Four steps, no account needed.
  1. Pick a source: the FAERS onset table is a good first one.
  2. Run one request with curl (see the API card).
  3. Run the worked example: one file, standard library only.
  4. Read the limits before you use a number.

Open data

Files under data/open/, versioned, with a licence per file.
  • data/open/cascade-packageThe 65 PIPC rows with Janus's class mapping, and the supporting mappings. Version 1.0.0. Licences: CC BY 4.0 (PIPC rows), Apache-2.0 (mappings).
  • data/open/faers-onsetFAERS time to onset for the 65 PIPC rows, descriptive only. CC BY 4.0. The version string is in the file and in the API answer.
  • data/open/data-qualityWeekly ingredient data-quality findings. CC BY 4.0.
  • GET /open/outcomesOpen outcome dataset (API only, CC BY 4.0). No released cells yet: the file is valid and empty.

Cite a dataset by its version string and snapshot date. Each file keeps its own licence and source attribution.

Open data guide

Public read-only API

Routes without a request body that return released data.

Base URL https://janusmeds.org/api. These routes carry no personal data. Errors are short codes in an error field.

  • GET /open/cascade-package/pipcthe 65 PIPC rows with Janus's class mapping
  • GET /open/faers-onset, /open/faers-onset.csvFAERS time-to-onset table, JSON or CSV
  • GET /open/faers-onset/{position}one row (1-65) with its caveats
  • GET /open/data-quality, .csv, .mdweekly data-quality findings, JSON, CSV or Markdown
  • GET /open/outcomes, .csvopen outcome dataset, JSON or CSV (released cells only)
  • GET /memory/snapshotFAERS counts snapshot: build, date, quarters
  • GET /timemachine/catalogue, /timemachine/cascade/{id}in silico time machine data (exploratory)
  • GET /simulate/compoundsallow-list of the exploratory simulations
  • GET /cds-servicesCDS Hooks discovery document
Example requests (outputs of 2026-11-10; they change with each release)
curl -s https://janusmeds.org/api/open/faers-onset/5 | jq '.row | {status, median_days, reports_with_interval}'
# {"status": "small_sample", "median_days": 29.0, "reports_with_interval": 23}

curl -s https://janusmeds.org/api/open/data-quality | jq '.version, .summary.by_class'
# "data-quality-1+f75ead99e56f"
# {"benign_difference": 106, "confirmed_error": 12, "needs_pharmacist": 102}

curl -s https://janusmeds.org/api/open/cascade-package/pipc | jq '.version, (.rows | length)'
# "1.0.0"
# 65

curl -s https://janusmeds.org/api/simulate/compounds | jq '.version, .server_runs'
# "simulation-allowlist-3"
# true

Rate limits: the repository states them only for the queued simulations (3 submissions per 30 s and 5 per 10 min per client, 120 polls per minute; the answer is 429 with Retry-After). The read-only routes state no limit: be gentle, and download the files in data/open/ for bulk use. The public site refuses the default Python user agent (HTTP 403): send your own.

The POST routes (medicine resolution, cascade check, notes, donations) carry a person's medicines and are not public API.

OpenAPI descriptionRoute table and rules

Worked example

The FAERS onset table in 20 lines

Fetches the onset table, counts the rows that have a median time to onset and lists the three with the most reports. One request, standard library only. Set JANUS_API_URL to use a local API.

Python (onset_summary.py)
import json
import os
import urllib.request

base = os.environ.get("JANUS_API_URL", "https://janusmeds.org/api").rstrip("/")
# The public site refuses the default Python user agent; send your own.
request = urllib.request.Request(
    f"{base}/open/faers-onset", headers={"User-Agent": "janus-onset-example/1.0"}
)
with urllib.request.urlopen(request, timeout=30) as response:
    table = json.load(response)

rows = table["rows"]
with_median = [r for r in rows if r["median_days"] is not None]
print(table["version"], "snapshot", table["faers_snapshot_date"], table["license"])
print("rows:", len(rows), "| rows with a median time to onset:", len(with_median))
print("rows with a median under 7 days:", sum(r["median_days"] < 7 for r in with_median))
print("by status:", table["summary"]["by_status"])
for r in sorted(with_median, key=lambda r: -r["reports_with_interval"])[:3]:
    print(
        f"PIPC row {r['pipc_position']}: {r['pipc_drug_a']} -> {r['pipc_adverse_event']}: "
        f"median {r['median_days']} days from {r['reports_with_interval']} reports ({r['status']})"
    )

Output on 2026-11-10
faers-onset-pipc-1+b1df201877b1 snapshot 2026-10-28 CC BY 4.0
rows: 65 | rows with a median time to onset: 32
rows with a median under 7 days: 19
by status: {'cluster_dominated': 3, 'count_only': 19, 'described': 21, 'no_candidate_reports': 2, 'no_interval': 9, 'small_sample': 11}
PIPC row 2: Antihypertensive -> Orthostatic hypotension/dizziness: median 2.0 days from 276 reports (described)
PIPC row 15: Anticonvulsant -> Rash: median 13.0 days from 226 reports (described)
PIPC row 9: Hydroxymethylglutaryl-coenzyme A (HMG Co-A) reductase inhibitor (statin) -> Myalgia/myositis: median 35.0 days from 216 reports (described)

Description only: a median is published only for rows with enough reports and complete dates; zero-day and day-01 dates are heaped; the numbers are neither causal nor incidence.

Open the file

MCP server

Seven tools for MCP clients

apps/mcp is a thin client of the API for MCP clients such as Claude or Kiro. Tools: janus_resolve_code, janus_resolve_ndc, janus_search_medicines, janus_check_cascades, janus_cascade_package_rows, janus_time_machine_catalogue, janus_time_machine_cascade. Every result carries a safety block; nothing is logged or kept between calls.

Run it (stdio)
cd apps/mcp
uv sync
JANUS_API_URL=http://127.0.0.1:8000 uv run janus-mcp

Kiro: .kiro/settings/mcp.json
{
  "mcpServers": {
    "janus": {
      "command": "uv",
      "args": ["run", "--directory", "apps/mcp", "janus-mcp"],
      "env": { "JANUS_API_URL": "http://127.0.0.1:8000" },
      "disabled": false,
      "autoApprove": ["janus_cascade_package_rows", "janus_time_machine_catalogue", "janus_time_machine_cascade"]
    }
  }
}

MCP guide

CDS Hooks service

Hooks order-select and order-sign

Sandbox only, not for clinical use. Do not connect it to a live EHR.

The service janus-cascade checks draft medication orders against the PIPC list. Start dates are not read. No card does not mean the medicines are free of problems.

Discovery and service
GET https://janusmeds.org/api/cds-services
POST https://janusmeds.org/api/cds-services/janus-cascade

There is no client authentication (no signed JWT) yet.

CDS Hooks guide and sandbox walk-through

Reproducible pipelines

One job per source

pipelines/ is a separate uv project with one job per source. The source registry is sources.toml; the NOTICE file is generated from it.

Run a job locally
cd pipelines
uv sync
uv run janus-pipelines run pipc
uv run janus-pipelines status
uv run janus-pipelines notice --check

Exit codes: 0 succeeded, 1 failed, 3 needs review, 4 refused. Artifacts go to JANUS_DATA_DIR. Some sources are large (FAERS about 250 MB). Lists with unclear redistribution terms are fetched at runtime and never committed.

sources.tomlNOTICEPipelines guide

Research notes

Two draft notes

Draft notes, not peer reviewed. Expert review has not yet been done.

HTTK-Pop older-adult exposure compared with FDA label ratiosNegative and null results: seven pre-registered hypotheses

Limitations and how to report errors

Read these before you use a number.

Found a mistake in a file, a number or this page? Open an issue on GitHub. Do not put personal or patient data in an issue. For an error in a source database, have a pharmacist check it before you report it upstream.

GitHub issuesHow to contribute corrections

How to cite

Cite the version you used.

There is no CITATION.cff yet: the project has not published citation metadata. Until then, cite the dataset with its version string and snapshot date:

Citation text
Janus project (Copyright 2026 Mikail Üstüner). Janus FAERS onset table for the PIPC cascades, version faers-onset-pipc-1+b1df201877b1 (FAERS snapshot 2026-10-28), CC BY 4.0. https://github.com/mikailustuner/janus (accessed YYYY-MM-DD).

The PIPC list itself:

Rochon PA et al. Eur Geriatr Med 2025;16(5):1573-1584. doi:10.1007/s41999-025-01215-x