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
- Pick a source: the FAERS onset table is a good first one.
- Run one request with curl (see the API card).
- Run the worked example: one file, standard library only.
- Read the limits before you use a number.
Open data
- 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 guidePublic read-only API
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
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"
# trueRate 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 rulesWorked example
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.
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']})"
)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 fileMCP server
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.
cd apps/mcp
uv sync
JANUS_API_URL=http://127.0.0.1:8000 uv run janus-mcp{
"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"]
}
}
}CDS Hooks service
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.
GET https://janusmeds.org/api/cds-services
POST https://janusmeds.org/api/cds-services/janus-cascadeThere is no client authentication (no signed JWT) yet.
CDS Hooks guide and sandbox walk-throughReproducible pipelines
pipelines/ is a separate uv project with one job per source. The source registry is sources.toml; the NOTICE file is generated from it.
cd pipelines
uv sync
uv run janus-pipelines run pipc
uv run janus-pipelines status
uv run janus-pipelines notice --checkExit 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 guideResearch 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 hypothesesLimitations and how to report errors
- Counts are reports, not people. FAERS is spontaneous reporting: not incidence, not deduplicated across cases.
- The onset table is descriptive, not causal. The time machine is in silico and exploratory.
- Mappings are made by automated rules and tests. Expert review has not yet been done.
- The CDS Hooks service has no client authentication yet and is for sandboxes only.
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 correctionsHow to cite
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:
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