OQO schema
Note: The OpenAlex Query Language is in alpha. It may change without warning — build against it at your own risk, and tell us what you think.
OQO (OpenAlex Query Objects) is the JSON abstract-syntax-tree format that OQL parses into — tools can construct or manipulate queries as OQO directly and skip string parsing entirely. The OQL API accepts both. The JSON Schema:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://openalex.org/schemas/oqo/v1.4",
"name": "OpenAlex_Query_Object",
"description": "The canonical JSON representation for OpenAlex queries. OQO is the intermediate format for bidirectional translation between URL parameters, OQL (human-readable query language), and programmatic JSON access. GENERATED from query_translation/oqo.py by query_translation/regen_schema.py — do not hand-edit. Entity values are BARE (the namespace is the column_id, resolved via the column registry): 'I136199984', 'de', 'article', '13' — never 'institutions/I136199984'. Negation is the per-node 'is_negated' polarity bit; the canonical form is NNF (negation on leaves only). JSON is the normative serialization; YAML is display-only and MUST round-trip to identical JSON (quote every string value on emit). The OQO describes WHICH ROWS a query matches — nothing else (#661 query/view split, v1.4). View/presentation parameters (sort, column projection, pagination) are NOT part of the OQO; they travel as sibling request parameters on the execute surface, in the classic URL syntax: `sort=<col>[:asc|desc][,…]`, `select=<col>,[…]`, `page`, `per_page`, `cursor` — as query-string params on `GET /?oqo=…` / `GET /?oql=…`, or as sibling top-level body keys on `POST / {\"oqo\": …, \"sort\": …}`.",
"type": "object",
"required": [
"get_rows"
],
"additionalProperties": false,
"properties": {
"get_rows": {
"$ref": "#/$defs/EntityType",
"description": "The entity type to retrieve (works, authors, institutions, ...)."
},
"corpus": {
"type": "string",
"enum": [
"all",
"core",
"expansion"
],
"default": "core",
"description": "Which corpus(es) seed the base result set (works only): 'core' (the curated corpus, default), 'expansion' (the expansion corpus alone — broader coverage, lower quality), or 'all' (core + expansion). A corpus SELECTION, distinct from a filter (which only narrows an already-chosen corpus). Absent ⇒ 'core'."
},
"filter_rows": {
"type": "array",
"description": "Filters applied to the retrieved rows. Top-level items are implicitly AND-joined.",
"items": {
"$ref": "#/$defs/Filter"
},
"default": []
},
"group_by": {
"type": "array",
"description": "Group-by dimensions (Stage B). A LIST, so multi-dimensional grouping (e.g. topic x year) is expressible; dimension order is meaningful. Live serving impl is single-dimension only (multi-dim deferred to #297).",
"items": {
"$ref": "#/$defs/GroupBy"
},
"default": []
},
"sample": {
"type": [
"integer",
"null"
],
"minimum": 1,
"maximum": 10000,
"description": "Return a random sample of N results instead of all matches.",
"default": null
},
"seed": {
"type": [
"string",
"integer",
"null"
],
"description": "Seed that makes a `sample` reproducible. Only meaningful alongside `sample`; ignored (with a warning) otherwise.",
"default": null
}
},
"$defs": {
"EntityType": {
"type": "string",
"description": "Valid OpenAlex entity types (the OQO `get_rows`). Sourced from oqo.VALID_ENTITY_TYPES.",
"enum": [
"authors",
"awards",
"concepts",
"continents",
"countries",
"domains",
"fields",
"funders",
"institution-types",
"institutions",
"keywords",
"languages",
"licenses",
"locations",
"oa-statuses",
"publishers",
"sdgs",
"source-types",
"sources",
"subfields",
"topics",
"types",
"works"
]
},
"Filter": {
"description": "A leaf filter (single condition) or a branch filter (boolean combination).",
"oneOf": [
{
"$ref": "#/$defs/LeafFilter"
},
{
"$ref": "#/$defs/BranchFilter"
}
]
},
"LeafFilter": {
"type": "object",
"description": "A single filter condition (a literal = atom + polarity).",
"required": [
"column_id",
"value"
],
"additionalProperties": false,
"properties": {
"column_id": {
"type": "string",
"description": "Filter field identifier; dot notation for nested fields. Valid columns/types come from the column registry, not this schema.",
"examples": [
"publication_year",
"type",
"open_access.is_oa",
"authorships.institutions.lineage",
"title_and_abstract.search",
"sustainable_development_goals.id"
]
},
"value": {
"description": "BARE value (no entity prefix). Native IDs self-namespace via their letter prefix (A/W/I/S/F/T/...); non-native values are bare slugs/codes/ints disambiguated by column_id. String for ids/slugs/search, integer for counts/years, boolean for flags, null for missing.",
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
},
{
"type": "number"
},
{
"type": "boolean"
},
{
"type": "null"
}
],
"examples": [
"article",
"I136199984",
"de",
"13",
2024,
true,
null
]
},
"operator": {
"$ref": "#/$defs/Operator",
"description": "Comparison operator. Defaults to 'is'. Strictly affirmative — negation is `is_negated`, never an operator.",
"default": "is"
},
"is_negated": {
"type": "boolean",
"description": "Polarity bit. true = the negation of this leaf (the single negation mechanism; maps 1:1 to URL `!`). In canonical (NNF) form, negation lives only on leaves.",
"default": false
}
}
},
"BranchFilter": {
"type": "object",
"description": "A boolean combination of filters (AND/OR), optionally negated.",
"required": [
"join",
"filters"
],
"additionalProperties": false,
"properties": {
"join": {
"type": "string",
"enum": [
"and",
"or"
],
"description": "'and' requires all children; 'or' requires at least one."
},
"filters": {
"type": "array",
"description": "Child filters (leaf or branch), enabling nested boolean logic.",
"minItems": 1,
"items": {
"$ref": "#/$defs/Filter"
}
},
"is_negated": {
"type": "boolean",
"description": "Negate the whole branch. The canonicalizer pushes this to the leaves via De Morgan (NNF), so a canonical OQO has is_negated only on leaves.",
"default": false
}
}
},
"GroupBy": {
"type": "object",
"description": "A single group-by dimension.",
"required": [
"column_id"
],
"additionalProperties": false,
"properties": {
"column_id": {
"type": "string",
"description": "The column to group by.",
"examples": [
"primary_topic.id",
"publication_year",
"authorships.countries",
"sustainable_development_goals.id"
]
}
}
},
"Operator": {
"type": "string",
"description": "Leaf comparison operators (strictly affirmative). Sourced from oqo.VALID_OPERATORS. Negation is the `is_negated` bit, not an operator.",
"enum": [
"<",
"<=",
">",
">=",
"has",
"in collection",
"is"
],
"default": "is"
}
},
"examples": [
{
"description": "Type filter (bare value)",
"value": {
"get_rows": "works",
"filter_rows": [
{
"column_id": "type",
"value": "article"
}
]
}
},
{
"description": "AND of filters (implicit at top level), with range + boolean flag",
"value": {
"get_rows": "works",
"filter_rows": [
{
"column_id": "type",
"value": "article"
},
{
"column_id": "publication_year",
"value": 2024,
"operator": ">="
},
{
"column_id": "open_access.is_oa",
"value": true
}
]
}
},
{
"description": "OR within a field (article OR review)",
"value": {
"get_rows": "works",
"filter_rows": [
{
"join": "or",
"filters": [
{
"column_id": "type",
"value": "article"
},
{
"column_id": "type",
"value": "review"
}
]
}
]
}
},
{
"description": "Negation via is_negated (COVID NOT pediatric)",
"value": {
"get_rows": "works",
"filter_rows": [
{
"column_id": "title_and_abstract.search",
"value": "covid",
"operator": "has"
},
{
"column_id": "title_and_abstract.search",
"value": "pediatric",
"operator": "has",
"is_negated": true
}
]
}
},
{
"description": "Stage B: multi-dimensional group_by (topic x year)",
"value": {
"get_rows": "works",
"filter_rows": [
{
"column_id": "publication_year",
"value": 1976,
"operator": ">="
}
],
"group_by": [
{
"column_id": "primary_topic.id"
},
{
"column_id": "publication_year"
}
]
}
},
{
"description": "Reproducible random sample (seed makes the sample stable)",
"value": {
"get_rows": "works",
"filter_rows": [
{
"column_id": "publication_year",
"value": 2024,
"operator": ">="
}
],
"sample": 100,
"seed": "42"
}
}
]
}