Open Causal Graph Data Standard (CausalJSON)

Version 0.2 · August 2026 · supersedes version 0.1 of December 2025

CausalJSON is a JSON format for causal graphs — directed acyclic graphs (DAG), acyclic directed mixed graphs (ADMG), maximal ancestral graphs (MAG), partial ancestral graphs (PAG) and causal loop diagrams (CLD) — that records not just the nodes and edges, but the reasoning behind each edge and the credit, licence and provenance of the graph itself. Every graph published here is available in this format from the record's Code tab.

Structure

Four top-level keys are required: $schema, graph, nodes and edges.

{
  "$schema": "https://opencausal.org/causaljson/0.2/causaljson.schema.json",
  "graph":          { ... },   // identity, credit, licence, provenance
  "nodes":          [ ... ],   // the variables
  "edges":          [ ... ],   // relationships asserted to exist
  "excluded_edges": [ ... ]    // relationships considered and ruled out
}

Nothing else is allowed: a document carrying a field this standard does not define is invalid, rather than quietly carrying data the next tool will drop. Version 0.2 has no extension mechanism, so a conversion from a richer source loses whatever does not fit.

The graph object

FieldTypeRequiredDescription
titlestringYes Human-readable title, up to 255 characters.
descriptionstringYes Purpose, context, scope, and the assumptions a reader needs in order to use the graph correctly.
typeenumYes dag, admg, mag, pag, pdag, cld or other. Decides how the edges are read, and which edge types are legal.
createdISO 8601 datetimeYes When this version was created. There is no modified: a revision is a new version with its own date.
authorsarray of agentsYes The citation list, in citation order. An agent is given_name, family_name, orcid and affiliations (each with a name and an optional ROR id); an organisation uses name with type: "organisation".
licensestringYes SPDX identifier, e.g. CC-BY-4.0, CC0-1.0.
idstringNo Identifier within the issuing system. Platform-local; a file passed between colleagues need not have one.
doistringNo Bare DOI: 10.83031/k3m9x2qp, with no https://doi.org/ prefix.
versionintegerNo Counts from 1, the way preprint servers number versions.
submitteragentNo The single person who deposited the record. Not part of the citation. Required for publication here.
research_questionstringNo The causal question the graph was drawn to answer, in one sentence.
related_identifiersarray of objectsNo Evidence, documentation, source datasets, earlier versions. Each has an identifier, a scheme (DOI, URL, PMID, arXiv, …) and a relation_type from the DataCite vocabulary, which defaults to References.
statistical_unitstringNo What the variables are defined on: individual, household, country-year. Whether a study's unit matches decides whether the graph applies at all.
populationstringNo The population and setting the graph is claimed to hold for.
provenancestringNo How the graph was built, in prose: expert workshops, a literature review, a discovery algorithm and its settings.
rights_urlstringNo Licence deed URL.
publisherstringNo The issuing platform.
languagestringNo A BCP 47 language tag, default en.
layoutstringNo The coordinate frame node positions are expressed in.

Nodes

FieldTypeRequiredDescription
idstringYes Unique within the document, matching ^[A-Za-z0-9_]{1,64}$ so that it survives DOT, R and Python without quoting.
labelstringYes Display name. Unrestricted text.
descriptionstringNo Precise enough that another researcher would operationalise the variable the same way.
roleenumNo exposure, outcome or covariate (the default). Confounder, mediator and collider are deliberately absent: they are properties of a variable relative to an exposure–outcome pair, computed from the structure rather than declared.
unmeasuredbooleanNo Default false. True when the variable is not in the data the graph is meant for.
variable_typeenumNo binary, categorical, ordinal, continuous, count, time_to_event, composite, other.
unitstringNo Unit of measurement. UCUM codes recommended where they fit (kg/m2, mm[Hg]), plain words where they do not.
time_pointintegerNo Occasion of measurement, counting from 0. Only the ordering carries meaning: no directed edge may run from a higher time point to a lower one. Two nodes sharing a label at different time points are the same variable measured twice.
identifiersarray of stringsNo Ontology terms as CURIEs: snomedct:22298006, mesh:D001835, loinc:39156-5. This is what makes nodes comparable across graphs.
positionobject {x, y}No Layout coordinates, in the frame declared by graph.layout.

Edges

FieldTypeRequiredDescription
sourcestringYes Node id.
targetstringYes Node id.
typeenumYes One of six values — see below.
signenumNo positive, negative or ambiguous (the sign depends on context). Absent means it has not been stated. Required on every edge of a CLD.
strengthnumberNo How strong the effect is, on whatever scale the author is working in — a standardised coefficient, a qualitative weight, an effect estimate. State the scale in justification whenever the number is meant to be read quantitatively: 0.62 as a coefficient and 0.62 as an odds ratio are different claims.
delayedbooleanNo Default false. True when the effect arrives materially later than the others — the hash marks on a causal loop diagram arrow. How long goes in justification.
justificationstringNo Why this edge is in the graph: the reasoning, evidence or expert judgement behind it.
referencesarray of stringsNo Sources, as CURIEs or URLs: doi:10.1093/ije/dyaa213, pmid:33269396.
curvaturenumberNo Drawing hint, default 0. The midpoint is displaced perpendicular to the straight line by curvature × the distance between the endpoints.

What each edge type claims

Each type is defined by the mark at each end — a tail, an arrowhead or a circle. That is what lets one format cover DAGs, ADMGs, MAGs and PAGs at once.

TypeDrawnAlso writtenReading
directedA → B->A is a direct cause of B
bidirectedA ↔ B<->an unmeasured common cause of A and B
undirectedA — B--A and B are adjacent; the orientation is not determined
partially_directedA o→ B@->B is not a cause of A; either A causes B or they share a latent cause
nondirectedA o—o B@-@adjacent, with both endpoints undetermined
partially_undirectedA o— B--@A is not a cause of B; the other end is undetermined

These three are not interchangeable, and confusing them is the most common import error in causal graph tooling. “A and B share a cause we did not measure” is one bidirected edge. “A causes B and B causes A” is two directed edges, which makes the graph cyclic and therefore a cld. “A and B are related but we have not resolved which way” is one undirected edge, in a graph whose type is pdag.

Which edge types each graph type allows

typeAllowed edgesCyclesAlso
dagdirectedno
admgdirected, bidirectednomay carry both X→Y and X↔Y between one pair
magdirected, bidirected, undirectedno
pagall sixnothe equivalence class FCI returns
pdagdirected, undirectednopartially oriented: some arrows resolved, some not
clddirectedexpectedsign required on every edge
otherall sixuncheckedanything the other six do not describe

Excluded edges

A missing edge is the strongest claim a causal graph makes, and there is no way to tell a considered absence from an oversight by looking at the picture. excluded_edges records the pairs that were thought about and deliberately left out, with the reasoning:

"excluded_edges": [
  {
    "source": "ice_cream",
    "target": "drowning",
    "justification": "No mechanism at the population-week level; the association is attributed entirely to weather.",
    "references": ["doi:10.1234/example"]
  }
]

It asserts that no direct causal relationship exists between the pair, in either direction, so nothing should render these as arrows. Note that an exclusion and a bidirected edge between the same pair are not in conflict: “no direct effect either way, but a shared unmeasured cause” is the exclusion restriction of instrumental-variable analysis.

Example

{
  "$schema": "https://opencausal.org/causaljson/0.2/causaljson.schema.json",
  "graph": {
    "id": "k3m9x2qp",
    "doi": "10.83031/k3m9x2qp",
    "version": 1,
    "title": "Ice cream sales and drowning deaths",
    "description": "Ice cream sales and drowning deaths move together across the year because both are driven by warm weather, not because either causes the other.",
    "research_question": "Does ice cream consumption increase the risk of drowning?",
    "type": "dag",
    "created": "2026-04-13T09:00:00Z",
    "authors": [
      {
        "given_name": "Abdullah",
        "family_name": "Ademoğlu",
        "orcid": "0000-0002-1825-0097",
        "affiliations": [{ "name": "Utrecht University", "ror": "https://ror.org/04pp8hn57" }]
      }
    ],
    "license": "CC-BY-4.0",
    "publisher": "Open Causal",
    "statistical_unit": "population-week",
    "provenance": "Constructed as a teaching illustration; no literature search was performed.",
    "layout": { "coordinate_system": "screen" }
  },
  "nodes": [
    { "id": "weather", "label": "Warm weather", "variable_type": "continuous",
      "unit": "Cel", "identifiers": ["wikidata:Q11466"],
      "position": { "x": 50, "y": 50 } },
    { "id": "ice_cream", "label": "Ice cream sales", "role": "exposure",
      "variable_type": "count", "position": { "x": 200, "y": 150 } },
    { "id": "drowning", "label": "Drowning deaths", "role": "outcome",
      "variable_type": "count", "position": { "x": 350, "y": 150 } }
  ],
  "edges": [
    { "source": "weather", "target": "ice_cream", "type": "directed", "sign": "positive",
      "justification": "Demand for ice cream rises with temperature." },
    { "source": "weather", "target": "drowning", "type": "directed", "sign": "positive",
      "justification": "Warm weather increases open-water exposure, and so the opportunities to drown." }
  ],
  "excluded_edges": [
    { "source": "ice_cream", "target": "drowning",
      "justification": "No mechanism by which buying ice cream changes drowning risk." }
  ]
}

Validation

CausalJSON is defined by a JSON Schema (draft 2020-12), identified by the URL that every document carries in its $schema key: https://opencausal.org/causaljson/0.2/causaljson.schema.json. A second, stricter profile describes what Open Causal additionally requires before publishing a graph and minting its DOI: a DOI, a version, a submitter, one of the Creative Commons licences, and a full name plus ORCID for every author.

Some rules cannot be expressed in JSON Schema and are checked separately: node ids are unique, every edge endpoint is a declared node, an excluded pair is not also asserted as an edge, no directed edge runs backwards in time, and a graph declaring itself a dag really is acyclic.

Metadata standards

The metadata follows existing standards rather than reinventing them — ORCID for people, ROR for organisations, SPDX for licences, DOI and the DataCite relation vocabulary for links, CURIEs for ontology terms — so a record maps onto DataCite mechanically.

Versions and feedback

This is CausalJSON 0.2, of August 2026, superseding version 0.1 of December 2025. The format is pre-1.0 and may still change in ways that break earlier files; each version is identified by its $schema URL, so a document always says which one it follows.

We welcome contributions from the research community. If you have suggestions or feedback, or would like to help develop the standard, please get in touch.