changedInput schema / properties / id / description
Previous value: -"Retrieve a single entity by ID. Supports: OpenAlex ID (\"W2741809807\"), DOI (\"10.1038/nature12373\"), ORCID (\"0000-0002-1825-0097\"), ROR (\"https://ror.org/00hx57361\"), PMID (\"12345678\" or \"https://pubmed.ncbi.nlm.nih.gov/12345678\"), ISSN (\"1234-5678\"). Keywords are identified by slug rather than a native ID — pass either the slug (\"groundwater\") or the URL a search returns (\"https://openalex.org/keywords/groundwater\"). A PMCID is recognized too, bare (\"PMC1234567\") or as a PubMed Central URL, but OpenAlex indexes no PMCIDs, so it resolves nothing — pass the work's PMID or DOI instead. When provided, `query`, `search_mode`, `filters`, `sort`, `sample`, and `seed` are not applied — the returned record is the entity at that ID regardless of them, and the response `notice` names any you passed. `select` still applies: the curated per-entity-type default is returned unless you pass `select` (use `[\"*\"]` for the complete record). To filter, drop `id` and search. Use openalex_resolve_name to find the ID if unknown."New value: +"Retrieve a single entity by ID. Supports: OpenAlex ID (\"W2741809807\"), DOI (\"10.1038/nature12373\"), ORCID (\"0000-0002-1825-0097\"), ROR (\"https://ror.org/00hx57361\"), PMID (\"12345678\" or \"https://pubmed.ncbi.nlm.nih.gov/12345678\"), ISSN (\"1234-5678\"). Keywords are identified by slug rather than a native ID — pass either the slug (\"groundwater\") or the URL a search returns (\"https://openalex.org/keywords/groundwater\"). A PMCID is recognized too, bare (\"PMC1234567\") or as a PubMed Central URL, but OpenAlex indexes no PMCIDs, so it resolves nothing — pass the work's PMID or DOI instead. When provided, `query`, `search_mode`, `filters`, `sort`, `sample`, and `seed` are not applied — the returned record is the entity at that ID regardless of them, and the response `notice` names any you passed. `select` still applies: the curated per-entity-type default is returned unless you pass `select` (use `[\"*\"]` for the complete record). An array too long for the response budget comes back as a window (`windows`); page the rest with `slice`. To filter, drop `id` and search. Use openalex_resolve_name to find the ID if unknown."
changedInput schema / properties / per_page / description
Previous value: -"Results per page (1-100). Default 25. Semantic search caps at 50 — when search_mode=\"semantic\", set per_page ≤ 50 (also subject to a 1 req/sec rate limit upstream). The cap applies to searches only; an `id` lookup returns its one record regardless of both."New value: +"Results per page (1-100). Default 25. Semantic search caps at 50 — when search_mode=\"semantic\", set per_page ≤ 50 (also subject to a 1 req/sec rate limit upstream). The cap applies to searches only; an `id` lookup returns its one record regardless of both. A budget-cut page returns fewer (`omitted`)."
changedInput schema / properties / select / description
Previous value: -"OpenAlex top-level field names to return. Always returned: `id`, `display_name` — additional fields you list are appended. A curated default per entity type applies to both searches and single-entity (`id`) lookups; pass field names to override it, or `[\"*\"]` to retrieve the complete record (every field). Only top-level fields project, so a nested value is requested by its parent object: bibliometrics (`h_index`, `i10_index`, `2yr_mean_citedness`) live under `summary_stats` on authors, sources, institutions, publishers, and funders, and naming a leaf returns that object. Invalid field names produce an error identifying the rejected field. Example: [\"doi\", \"authorships\", \"primary_topic\"]."New value: +"OpenAlex top-level field names to return. Always returned: `id`, `display_name` — additional fields you list are appended. A curated default per entity type applies to both searches and single-entity (`id`) lookups; pass field names to override it, or `[\"*\"]` to retrieve the complete record (every field). Only top-level fields project, so a nested value is requested by its parent object: bibliometrics (`h_index`, `i10_index`, `2yr_mean_citedness`) live under `summary_stats` on authors, sources, institutions, publishers, and funders, and naming a leaf returns that object. Invalid field names produce an error identifying the rejected field. Large projections may be cut to fit the response budget (`omitted`, `windows`). Not applied with `slice`. Example: [\"doi\", \"authorships\", \"primary_topic\"]."
addedInput schema / properties / slice
Added value: +{
+ "description": "Page one array of the record at `id`: returns `id`, `display_name`, and `field` from `offset` onward, as many elements as fit the response budget (at least one), with the window and its `next` call in `windows`. Requires `id`; replaces `select`. An offset at or past the end returns an empty window. Walks any partial array, including a possibly capped 100-authorship list.",
+ "properties": {
+ "field": {
+ "description": "Top-level array field to page, such as \"authorships\" or \"referenced_works\". Leave it empty to skip slicing.",
+ "type": "string"
+ },
+ "offset": {
+ "default": 0,
+ "description": "0-based index of the first element to return.",
+ "maximum": 9007199254740991,
+ "minimum": 0,
+ "type": "integer"
+ }
+ },
+ "required": [
+ "field"
+ ],
+ "type": "object"
+}
changedOutput schema / properties / error / properties / data / properties / reason / description
Previous value: -"Machine-readable failure mode. Declared by this tool: `semantic_per_page_cap`: A search (no `id`) set per_page above the semantic-search cap of 50. `semantic_without_query`: A search set search_mode to \"semantic\" without supplying the `query` it embeds. `semantic_with_cursor`: A search set search_mode to \"semantic\" and supplied `cursor`, which OpenAlex rejects on a semantic query. `page_without_semantic`: A search supplied `page` under a search_mode other than \"semantic\". `sample_with_cursor`: A search (no `id`) provided both `sample` and `cursor`. `sample_with_page`: A search (no `id`) provided both `sample` and `page`. `sample_with_semantic`: A search (no `id`) provided `sample` with search_mode \"semantic\", which OpenAlex does not sample — it returns the same ranked candidates under every seed. `sample_with_sort`: A search (no `id`) provided both `sample` and `sort`, which OpenAlex refuses together. `seed_without_sample`: A search (no `id`) provided `seed` without `sample`. `entity_not_found`: Lookup by id matched no OpenAlex entity. `rate_limited`: OpenAlex throttled the request for exceeding its per-second ceiling (HTTP 429). `upstream_budget_exhausted`: The OpenAlex daily usage budget is spent (HTTP 429). `upstream_timeout`: OpenAlex did not respond within the request deadline. `upstream_unavailable`: OpenAlex was unreachable or unusable — HTTP 503, a connection failure, or a body that was empty, HTML, or unparseable JSON. `upstream_unauthorized`: OpenAlex rejected the API key (HTTP 401). `upstream_forbidden`: OpenAlex denied access to the requested resource (HTTP 403). `comma_in_filter_value`: A filter value contains a comma, which collides with the OpenAlex filter separator. `upstream_invalid_params`: OpenAlex rejected an invalid filter, select, or sort field name (HTTP 400). `upstream_invalid_id_value`: An entity-ID filter received a value that is not an OpenAlex ID — usually a name (HTTP 400). `upstream_sort_requires_search`: sort=-relevance_score was used without an active search (HTTP 400). `query_too_long`: OpenAlex rejected `query` as longer than the search length it accepts (HTTP 400). `upstream_invalid_params_other`: OpenAlex rejected the request (HTTP 400) for a reason other than an invalid field name. `upstream_validation_failed`: OpenAlex rejected the request as semantically invalid (HTTP 422). Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `semantic_per_page_cap`: A search (no `id`) set per_page above the semantic-search cap of 50. `semantic_without_query`: A search set search_mode to \"semantic\" without supplying the `query` it embeds. `semantic_with_cursor`: A search set search_mode to \"semantic\" and supplied `cursor`, which OpenAlex rejects on a semantic query. `page_without_semantic`: A search supplied `page` under a search_mode other than \"semantic\". `sample_with_cursor`: A search (no `id`) provided both `sample` and `cursor`. `sample_with_page`: A search (no `id`) provided both `sample` and `page`. `sample_with_semantic`: A search (no `id`) provided `sample` with search_mode \"semantic\", which OpenAlex does not sample — it returns the same ranked candidates under every seed. `sample_with_sort`: A search (no `id`) provided both `sample` and `sort`, which OpenAlex refuses together. `seed_without_sample`: A search (no `id`) provided `seed` without `sample`. `slice_without_id`: A search passed `slice` without `id` — slice pages one array of one record. `slice_field_not_array`: The `slice` field is `*`, or is not an array on the record at `id` — absent, null, a scalar, or an object. `entity_not_found`: Lookup by id matched no OpenAlex entity. `rate_limited`: OpenAlex throttled the request for exceeding its per-second ceiling (HTTP 429). `upstream_budget_exhausted`: The OpenAlex daily usage budget is spent (HTTP 429). `upstream_timeout`: OpenAlex did not respond within the request deadline. `upstream_unavailable`: OpenAlex was unreachable or unusable — HTTP 503, a connection failure, or a body that was empty, HTML, or unparseable JSON. `upstream_unauthorized`: OpenAlex rejected the API key (HTTP 401). `upstream_forbidden`: OpenAlex denied access to the requested resource (HTTP 403). `comma_in_filter_value`: A filter value contains a comma, which collides with the OpenAlex filter separator. `upstream_invalid_params`: OpenAlex rejected an invalid filter, select, or sort field name (HTTP 400). `upstream_invalid_id_value`: An entity-ID filter received a value that is not an OpenAlex ID — usually a name (HTTP 400). `upstream_sort_requires_search`: sort=-relevance_score was used without an active search (HTTP 400). `query_too_long`: OpenAlex rejected `query` as longer than the search length it accepts (HTTP 400). `upstream_invalid_params_other`: OpenAlex rejected the request (HTTP 400) for a reason other than an invalid field name. `upstream_validation_failed`: OpenAlex rejected the request as semantically invalid (HTTP 422). Other values are possible when a failure originates below the handler."
changedOutput schema / properties / error / properties / data / properties / reason / examples
Previous value: -[
- "semantic_per_page_cap",
- "semantic_without_query",
- "semantic_with_cursor",
- "page_without_semantic",
- "sample_with_cursor",
- "sample_with_page",
- "sample_with_semantic",
- "sample_with_sort",
- "seed_without_sample",
- "entity_not_found",
- "rate_limited",
- "upstream_budget_exhausted",
- "upstream_timeout",
- "upstream_unavailable",
- "upstream_unauthorized",
- "upstream_forbidden",
- "comma_in_filter_value",
- "upstream_invalid_params",
- "upstream_invalid_id_value",
- "upstream_sort_requires_search",
- "query_too_long",
- "upstream_invalid_params_other",
- "upstream_validation_failed"
-]New value: +[
+ "semantic_per_page_cap",
+ "semantic_without_query",
+ "semantic_with_cursor",
+ "page_without_semantic",
+ "sample_with_cursor",
+ "sample_with_page",
+ "sample_with_semantic",
+ "sample_with_sort",
+ "seed_without_sample",
+ "slice_without_id",
+ "slice_field_not_array",
+ "entity_not_found",
+ "rate_limited",
+ "upstream_budget_exhausted",
+ "upstream_timeout",
+ "upstream_unavailable",
+ "upstream_unauthorized",
+ "upstream_forbidden",
+ "comma_in_filter_value",
+ "upstream_invalid_params",
+ "upstream_invalid_id_value",
+ "upstream_sort_requires_search",
+ "query_too_long",
+ "upstream_invalid_params_other",
+ "upstream_validation_failed"
+]
changedOutput schema / properties / meta / properties / next_cursor / description
Previous value: -"Cursor for next page. null if no more results."New value: +"Cursor for next page. null if no more results. Continues after the full upstream page, `omitted` records included."
changedOutput schema / properties / meta / properties / per_page / description
Previous value: -"Page size OpenAlex echoed for this request — the requested per_page, not the number of records returned. A short or exhausted page carries fewer records than this."New value: +"Page size OpenAlex echoed for this request — the requested per_page, not the number of records returned. A short or exhausted page carries fewer records than this, as does a page the response budget cut (`omitted`)."
changedOutput schema / properties / notice / description
Previous value: -"Guidance notice. Set when a first call returns no results (echoes the criteria and suggests how to broaden), when a paginated call ran past its last page (says the traversal is finished instead of advising a broader query), when an `id` lookup was passed search criteria it does not apply (names them), and on every semantic search to disclose that `meta.count` is a candidate total rather than a match total. Absent otherwise."New value: +"Guidance notice. Set when a first call returns no results (echoes the criteria and suggests how to broaden), when a paginated call ran past its last page (says the traversal is finished instead of advising a broader query), when an `id` lookup was passed search criteria it does not apply (names them), on every semantic search to disclose that `meta.count` is a candidate total rather than a match total, when the response budget cut records, windowed an array, or ran over, when a list record carries exactly 100 authorships (possibly capped), when a `slice` offset is past the end of its array, and when `slice` was passed with `select`, which it replaces. Absent otherwise."
addedOutput schema / properties / omitted
Added value: +{
+ "additionalProperties": false,
+ "description": "Present when the response budget cut whole records from the page end; pagination continues after the full upstream page.",
+ "properties": {
+ "ids": {
+ "description": "Bare IDs of the records left out, in page order (a keyword keeps its URL).",
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "next": {
+ "additionalProperties": false,
+ "description": "One call returning those records as a set, in OpenAlex's order, not page order. Budgeted too, so it may carry its own `omitted`.",
+ "properties": {
+ "arguments": {
+ "additionalProperties": {},
+ "description": "Arguments to pass as-is.",
+ "properties": {},
+ "type": "object"
+ },
+ "tool": {
+ "const": "openalex_search_entities",
+ "description": "Tool to call.",
+ "type": "string"
+ }
+ },
+ "required": [
+ "tool",
+ "arguments"
+ ],
+ "type": "object"
+ }
+ },
+ "required": [
+ "ids",
+ "next"
+ ],
+ "type": "object"
+}
addedOutput schema / properties / over_budget
Added value: +{
+ "description": "True when even the least this call can return — the first record's non-array fields (its arrays windowed to empty), or one `slice` element — exceeds the budget.",
+ "type": "boolean"
+}
changedOutput schema / properties / results / description
Previous value: -"OpenAlex entity objects. Text values are plain text — HTML entities decoded, HTML/JATS/MathML markup removed — and an abstract arrives reconstructed as `abstract`. Additional fields depend on entity_type and select."New value: +"OpenAlex entity objects. Text values are plain text — HTML entities decoded, HTML/JATS/MathML markup removed — except identifier and URL fields such as `id`, `doi`, `ids`, and `*_url`, returned exactly as OpenAlex stores them; an abstract arrives reconstructed as `abstract`. Additional fields depend on entity_type and select. Records cut by the response budget are in `omitted`; partial or possibly capped arrays are in `windows`."
changedOutput schema / properties / results / items / properties / id / description
Previous value: -"OpenAlex ID (e.g., \"W2741809807\", \"A1234567890\")."New value: +"OpenAlex ID URL (e.g., \"https://openalex.org/W2741809807\"). `windows` and `omitted` name records by the bare ID (\"W2741809807\"); a keyword keeps its URL."
addedOutput schema / properties / windows
Added value: +{
+ "description": "Arrays returned in part — windowed to fit the budget, paged by `slice`, or 100 possibly capped authorships — each with its continuation. A `slice` call always carries its window, even for a whole array; otherwise absent when every array is whole.",
+ "items": {
+ "additionalProperties": false,
+ "description": "An array returned in part.",
+ "properties": {
+ "field": {
+ "description": "Array field.",
+ "type": "string"
+ },
+ "id": {
+ "description": "Bare ID of the record.",
+ "type": "string"
+ },
+ "next": {
+ "anyOf": [
+ {
+ "additionalProperties": false,
+ "properties": {
+ "arguments": {
+ "additionalProperties": {},
+ "description": "Arguments to pass as-is.",
+ "properties": {},
+ "type": "object"
+ },
+ "tool": {
+ "const": "openalex_search_entities",
+ "description": "Tool to call.",
+ "type": "string"
+ }
+ },
+ "required": [
+ "tool",
+ "arguments"
+ ],
+ "type": "object"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "`id` + `slice` call for the next elements; null at the array end."
+ },
+ "offset": {
+ "description": "Index of the first element shown.",
+ "type": "number"
+ },
+ "possibly_capped": {
+ "description": "True for exactly 100 authorships on a list record (OpenAlex's cap): the list may be longer.",
+ "type": "boolean"
+ },
+ "shown": {
+ "description": "Elements shown.",
+ "type": "number"
+ },
+ "total": {
+ "description": "Array length as returned to this call.",
+ "type": "number"
+ }
+ },
+ "required": [
+ "id",
+ "field",
+ "offset",
+ "shown",
+ "total",
+ "possibly_capped",
+ "next"
+ ],
+ "type": "object"
+ },
+ "type": "array"
+}