MétaCan
Menu
API

The same query, as an endpoint.

Every screen consumes public endpoints. The page, the API and the export parse the same parameters with the same function, so no surface can answer a different question from another.

Read-only, JSON, CORS-enabled, no key. Every endpoint is backed by the same functions the pages call. searchWorks() serves both /works and /api/v1/works, so the API cannot answer a different question from the page above it.

Base URL: https://metacan.xera.ac/api/v1

MethodEndpointDescription
GET/api/v1/cohortCount and page through a cohort for any filter set
GET/api/v1/works/{id}One record: routes, labels, predictions, provenance
GET/api/v1/facets/{facet}Typeahead values for venue and topic
POST/api/v1/permalinkMint a citable /q/ permalink for a pinned query
GET/api/v1/cohort/exportCSV or JSON export of the current cohort, capped
GET/api/v1/recentThe rolling live layer, synced daily
GET/api/v1/screenedThe three-model screen with verdicts and design weights
GET/api/v1/stats/…Frame-wide aggregates: summary, years, routes, fields, labels
GET/api/v1/findingsThe findings file the pilot scripts write, verbatim
GET /api/v1/cohort?route_fund=1&route_aff=0&lang=fr200
{
  "meta": {
    "total": 6784,
    "direct_labels_cover": 23,
    "predictions_cover": 6784,
    "query_hash": "23b0df378a31",
    "filters": { "route_fund": true,
                 "route_aff": false,
                 "lang": "fr" }
  },
  "results": [ … ]
}

Notes

  • CORS is open (*). This is a public CC-BY research dataset; the point of publishing it is that you can query it from your own page without proxying.
  • Caching. Responses carry s-maxage=3600. The frame is a pinned snapshot: it does not change between deploys, so a stale aggregate is not a risk and re-scanning 4.3M rows per request would be.
  • No key, no rate limit. It is one small server. Be reasonable, and if you need the whole frame, take the repository and rebuild it locally rather than paginating four million rows out of this box.
  • License. Data CC-BY-4.0, code MIT. Cite OpenAlex and Retraction Watch as the upstream sources.
GET/api/v1/cohort

The cohort builder's own query. Same parser, same function as the front page, so the API cannot answer a different question from the page above it. Takes every /api/v1/works parameter, plus the facets below.

The count is exact, and the label coverage travels with it. meta.total is the real N (a cohort is cited by its N), and meta.direct_labels_cover reports direct label coverage, while meta.predictions_cover reports prediction coverage. An empty labels array means unlabeled, never “not in the category”.
ParameterTypeMeaning
topicstringExact OpenAlex primary topic. Values come from the typeahead: /api/v1/facets/topic?q=…
venuestringExact venue string. Values come from /api/v1/facets/venue?q=…
route_aff, route_fund, route_venue, route_about1 | 0Tri-state route facets: 1 requires the route, 0 excludes it, absent means any. They compose (route_fund=1&route_aff=0 is the funder-only stratum), which the single `route` parameter cannot express.
retracted1 | 01 = retracted only; 0 = exclude retracted; absent = any.
abstracthas | nonehas = only works with an abstract; none = only works without.
categorymetaresearch | metaepi_narrow | metaepi_broad | bibliometrics | sts | scholarly_communication | open_science | research_integrityCategory facet. Its evidence source is selected by label_source. Direct labels and predictions are both unvalidated.
designrandomized_trial | nonrandomized_trial | observational | systematic_review | meta_analysis | case_report | qualitative | simulation_or_modeling | bench_or_experimental | theoretical_or_conceptual | not_applicable | design_otherStudy design facet. Its evidence source is selected by label_source. No study design is MEDLINE validated yet.
label_sourcedirect | predicteddirect uses sparse direct model outputs. predicted uses full frame teacher distillation outputs. Neither is human validated.
prediction_modecandidate | consensuscandidate uses the union of the thresholded Codex and Gemma heads. consensus uses their intersection.
agreementany | allFor direct labels only. any means one model suffices; all means every model that labeled the work agrees on the filtered value.
labeled1 | 0For direct labels only. 1 requires a direct label row; 0 requires no direct label row.
# Directly labeled metaresearch works, with exact coverage:
curl -sS "https://metacan.xera.ac/api/v1/cohort?label_source=direct&category=metaresearch" \
  | jq '{total: .meta.total, direct: .meta.direct_labels_cover}'

# Consensus frame predictions for metaresearch:
curl -sS "https://metacan.xera.ac/api/v1/cohort?label_source=predicted&prediction_mode=consensus&category=metaresearch" \
  | jq '{total: .meta.total, predicted: .meta.predictions_cover, first: .results[0].prediction}'
GET/api/v1/cohort/export

The whole cohort as a file, streamed from the database: every work column, direct labels, full prediction data, provisional legacy scores, and per-row status fields.

Capped at 100,000 rows. The truncation is never silent: it is declared in meta.truncated (JSON), in a trailing comment line (CSV), and in the X-Export-Truncated header. Past the cap, narrow the cohort or rebuild the frame from the repository.
ParameterTypeMeaning
formatcsv | jsoncsv (default) or json. Everything else is the same filter vocabulary as /api/v1/cohort.
# A labeled cohort as CSV:
curl -sSL "https://metacan.xera.ac/api/v1/cohort/export?category=metaresearch&format=csv" -o cohort.csv

# As JSON, metadata first:
curl -sS "https://metacan.xera.ac/api/v1/cohort/export?design=systematic_review&year_from=2020&format=json" | jq '.meta'
POST/api/v1/permalink

Mint the citable /q/<hash> permalink for a filter state. Idempotent: the hash is a function of the canonical filters, so the same cohort always gets the same URL, whoever asks and whenever.

curl -sS -X POST "https://metacan.xera.ac/api/v1/permalink?label_source=predicted&prediction_mode=consensus&category=metaresearch" \
  | jq '{url, total, direct_labels_cover, predictions_cover}'
GET/api/v1/facets/{venue,topic}

Search-as-you-type over the ~85,000 distinct venues and ~4,500 distinct topics, with frame-wide counts. Two characters minimum.

curl -sS "https://metacan.xera.ac/api/v1/facets/venue?q=canadian+journal" | jq '.results[:3]'
curl -sS "https://metacan.xera.ac/api/v1/facets/topic?q=peer+review" | jq '.results[:3]'
GET/api/v1/facets/author

Search-as-you-type over researchers with a Canadian-affiliated authorship, ranked by Canadian output. Returns the disambiguated OpenAlex A-id next to each name; the id is what ?author_id= and the network endpoint consume. Two characters minimum.

curl -sS "https://metacan.xera.ac/api/v1/facets/author?q=tricco" | jq '.results[:3]'
GET/api/v1/network

The Canada-only collaboration network. Without parameters: the overview graph of the strongest ties. With author_id: that researcher’s neighborhood. The meta block states the construction rules (nodes, edges, fractional weights, the density guard) on every response, because a graph whose rules are not in the response is not citable.

ParameterTypeMeaning
author_idstringOpenAlex author id (A...). Omit for the overview graph.
curl -sS "https://metacan.xera.ac/api/v1/network?author_id=A5044517411" | jq '.meta, .graph.nodes[:3]'
GET/api/v1/stats/labels

The label landscape: coverage, categories, study designs, years and languages over the machine-labeled subset. The same function the Landscape page renders, so the two cannot drift.

curl -sS https://metacan.xera.ac/api/v1/stats/labels | jq '{coverage, top: .by_category[:3]}'
GET/api/v1/stats/summary

The frame in one object: total works, the no-affiliation and no-abstract counts, the four route marginals, and the screen's consensus histogram.

curl -sS https://metacan.xera.ac/api/v1/stats/summary | jq
GET/api/v1/works

Browse and search the whole frame. Full-text over titles, every filter the browse page offers, paginated.

The count is capped at 10,000. Counting 4.3M rows exactly costs seconds and nobody reads the number, so total_is_capped: true means “at least 10,000”, not “exactly 10,000”. Page through if you need more.
ParameterTypeMeaning
qstringFull-text search over titles (Postgres tsvector; terms are ANDed).
authorstringAuthor-name search over the author layer (same websearch semantics as q). A name is a broad net: it can match many OpenAlex author identities; author_id is the precise form.
author_idstringExact OpenAlex author id (A...), the disambiguated identity. The citable author filter.
year_from, year_tointInclusive publication-year bounds.
cited_minintMinimum citation count (cited_by >= N).
langstringLanguage code, e.g. en, fr.
typestringWork type, e.g. article, preprint, dissertation.
fieldstringOpenAlex primary field, e.g. 'Medicine'.
routeaff | fund | venue | about | no_affRoute provenance: why the work is in the frame. no_aff returns the works with NO Canadian affiliation, which an affiliation-only frame never sees.
retracted1Only works OpenAlex flags as retracted.
no_abstract1Only works with no abstract. The screen finds half as much metaresearch here.
n_in0..3Screening consensus: how many of the three models called it metaresearch.
sortcited | year_desc | year_ascDefault: cited.
page, per_pageintper_page max 100, default 25.
# The works an affiliation-only frame would never have seen,
# most-cited first:
curl -sS "https://metacan.xera.ac/api/v1/works?route=no_aff&sort=cited&per_page=5" | jq '.results[] | {id, title, cited_by, routes}'

# French-language works with no abstract, published since 2015:
curl -sS "https://metacan.xera.ac/api/v1/works?lang=fr&no_abstract=1&year_from=2015&per_page=5" | jq

# Full-text search:
curl -sS "https://metacan.xera.ac/api/v1/works?q=reproducibility+crisis&per_page=3" | jq '.results[].title'
GET/api/v1/works/{id}

One work with every frame field, route provenance, Retraction Watch state, direct model labels, and the full frame prediction with teacher scores and uncertainty fields.

ParameterTypeMeaning
abstract1Fetch the abstract live from OpenAlex and de-invert it. Off by default: abstracts are not in this database, so asking for one costs an upstream round-trip.
# A work, with its provenance:
curl -sS https://metacan.xera.ac/api/v1/works/W2342586781 | jq '{id, title, routes}'

# With the abstract fetched live from OpenAlex:
curl -sS "https://metacan.xera.ac/api/v1/works/W2342586781?abstract=1" | jq '.abstract'
GET/api/v1/screened

The 5,600 screened works with all three models' tiers, genres, confidences and reasons, plus the design weight.

The sample is stratified. Every record carries a weight (inverse selection probability). Any rate you compute from these rows without applying the weight is wrong.
ParameterTypeMeaning
contested_only1THE DISAGREEMENT DOSSIER: every work any model called metaresearch. This subset, not the base rate, is the project’s deliverable.
n_in0..3Exact consensus count.
stratumstringe.g. aff_core, about_only, french, venue_new, fund_new.
page, per_pageintper_page max 100.
# The disagreement dossier: the works that mark the field's boundary.
curl -sS "https://metacan.xera.ac/api/v1/screened?contested_only=1" | jq '.meta.summary'

# The works only ONE model called metaresearch:
curl -sS "https://metacan.xera.ac/api/v1/screened?n_in=1" \
  | jq '.results[] | {title, opus: .opus.tier, gpt: .gpt.tier, grok: .grok.tier}'
GET/api/v1/stats/by-route

The four routes: marginals, and the exact route combinations.

The routes overlap; a work can be admitted by several. Therefore, marginals sums to more than the frame. combinations counts each work once and sums to the total.
curl -sS https://metacan.xera.ac/api/v1/stats/by-route | jq '{no_aff: .meta.no_aff, marginals, combinations: .combinations[:5]}'
GET/api/v1/stats/by-year

Works per year, with the no-affiliation and no-abstract counts alongside, because both gaps move over time.

curl -sS https://metacan.xera.ac/api/v1/stats/by-year | jq '.results[-5:]'
GET/api/v1/stats/by-field

The field breakdown, plus languages, the abstract gap by type, top venues, top funders, and the four-state retraction record. This is everything the analytics page draws in one call.

curl -sS https://metacan.xera.ac/api/v1/stats/by-field | jq '.retraction_states'
GET/api/v1/findings

All 32 findings, served verbatim from the file the pilot scripts write. Every pilot number quoted on this site comes from here.

curl -sS https://metacan.xera.ac/api/v1/findings | jq '.findings.three_model_screen.headline'
GET/api/v1/predictions

The full frame prediction summary and the model evaluation report, served directly from the generated pilot artifacts. They include source and model hashes, model version, category counts, policies, cross-validation results, and limitations. Every score measures fidelity to machine teachers, not human accuracy, and every prediction is machine predicted and unvalidated.

curl -sS https://metacan.xera.ac/api/v1/predictions | jq '{status: .predictions.prediction_status, n: .predictions.n_predictions, evidence: .meta.evidence_level, limitations: .predictions.limitations}'