# Academic Papers API — search scholarly papers, authors, citations, institutions and journals across OpenAlex, arXiv and Crossref (abstracts, DOIs, open-access PDFs)

> search papers (source=openalex|arxiv|crossref|all; cursor pagination, year/OA/type filters, match=title, fulltext=; first-class author_id/venue_id/institution_id/concept_id/topic_id filters for papers BY an entity)
> ReefAPI engine `academic` · 12 endpoints · clean JSON, no scraping or browsers to manage.

## How to call
- **Endpoint:** `POST https://api.reefapi.com/academic/v1/<action>` with a JSON body.
- **Auth:** header `x-api-key: <YOUR_REEFAPI_KEY>` — create one free (1,000 credits, no card): https://reefapi.com/signup
- **Response (every call):** `{ ok: boolean, data: ..., meta: { record_count, credits, ... }, error: { code, message } }` — branch on `ok`. Failed or blocked calls are free.
- **One key + one shared credit pool** across every ReefAPI API. Per-call credits are listed on each endpoint below.
- **Use it from an AI agent (MCP):** connect `https://api.reefapi.com/mcp` (remote streamable-http, `Authorization: Bearer <key>`) and your assistant can call these actions directly.

## Endpoints

### POST /academic/v1/search — 1 credit
search papers (source=openalex|arxiv|crossref|all; cursor pagination, year/OA/type filters, match=title, fulltext=; first-class author_id/venue_id/institution_id/concept_id/topic_id filters for papers BY an entity)

**Parameters:**
- `query` (string, required) — Free-text search query.
- `source` (enum, optional, default "openalex") — Which backend(s) to search. Unknown values are rejected. [one of: openalex, arxiv, crossref, all]
- `per_page` (integer, optional, default 25) — Results per page (1-200, default 25); clamped.
- `cursor` (string, optional) — OpenAlex cursor for deep pagination (use '*' for the first page, then meta.next_cursor).
- `filter` (string, optional) — Advanced: raw OpenAlex (or Crossref) filter string, appended verbatim.
- `sort` (string, optional) — Sort key. OpenAlex accepts keys like cited_by_count:desc / publication_date:desc; arXiv accepts 'date'.
- `from_year` (integer, optional) — Filter to papers published on or after this year.
- `to_year` (integer, optional) — Filter to papers published on or before this year.
- `open_access` (boolean, optional, default false) — If true, restrict to open-access works (is_oa:true).
- `type` (string, optional) — OpenAlex work type filter (e.g. article, book-chapter, dataset); passed through.
- `match` (boolean, optional, default false) — If true, closest-title match (title.search) instead of relevance search (OpenAlex source only).
- `category` (string, optional) — arXiv subject category (source=arxiv); can stand in for `query`.
- `include_abstract` (boolean, optional, default true) — Include reconstructed abstracts in search results (default true).
- `fulltext` (string, optional) — Full-text search within the paper body (OpenAlex fulltext.search).
- `start` (integer, optional, default 0) — arXiv offset pagination (0-10000); clamped.
- `offset` (integer, optional, default 0) — Crossref offset pagination (0-10000); clamped.
- `author_id` (string, optional) — Restrict to papers by this OpenAlex author id (filter=author.id:…). A convenience over the raw `filter` string.
- `venue_id` (string, optional) — Restrict to papers by this OpenAlex venue/source id (filter=primary_location.source.id:…). A convenience over the raw `filter` string.
- `institution_id` (string, optional) — Restrict to papers by this OpenAlex institution id (filter=institutions.id:…). A convenience over the raw `filter` string.
- `concept_id` (string, optional) — Restrict to papers by this OpenAlex concept id (filter=concepts.id:…). A convenience over the raw `filter` string.
- `topic_id` (string, optional) — Restrict to papers by this OpenAlex topic id (filter=topics.id:…). A convenience over the raw `filter` string.

**Returns:** results[] (title, doi, authors[], venue, year, cited_by_count, abstract, oa_pdf, sources_merged), count, next_cursor, source

**Example request body:**
```json
{
  "query": "covid"
}
```

### POST /academic/v1/paper_detail — 1 credit
full paper (abstract/authors/affiliations/venue/year/DOI/OA-PDF/fields); id=OpenAlex|DOI|arXiv|PMID; cross-source abstract gap-fill

**Parameters:**
- `id` (string, required) — Paper id — OpenAlex id (W…), OR DOI (10.…), OR arXiv id, OR PMID.
- `enrich` (boolean, optional, default false) — Pull extra Crossref metadata (funders/license/references flag) for the paper.
- `raw` (boolean, optional, default false) — Attach the raw OpenAlex record under paper._raw_openalex.
- `fill_abstract` (boolean, optional, default true) — Gap-fill a missing OpenAlex abstract from arXiv/Crossref (default true).

**Returns:** paper{} — title, abstract, authors[]+affiliations, venue, year, doi, oa_pdf, fields, cited_by_count, sources_merged

**Example request body:**
```json
{
  "id": "W3177828909"
}
```

### POST /academic/v1/citations — 1 credit
papers that cite this work (cursor-paginated)

**Parameters:**
- `id` (string, required) — Paper id — OpenAlex id (W…), OR DOI (10.…), OR arXiv id, OR PMID.
- `per_page` (integer, optional, default 25) — Results per page (1-200, default 25); clamped.
- `cursor` (string, optional) — OpenAlex cursor for deep pagination (use '*' for the first page, then meta.next_cursor).

**Returns:** results[] (citing papers: id, title, year, …), count, next_cursor, cited_paper_id

**Example request body:**
```json
{
  "id": "W3009885589"
}
```

### POST /academic/v1/references — 1 credit
works this paper references (hydrated)

**Parameters:**
- `id` (string, required) — Paper id — OpenAlex id (W…), OR DOI (10.…), OR arXiv id, OR PMID.
- `limit` (integer, optional, default 50) — Max records (1-200, default 50); clamped.

**Returns:** results[] (referenced papers, hydrated), count, referenced_works_count, paper_id, stop_reason

**Example request body:**
```json
{
  "id": "W3009885589"
}
```

### POST /academic/v1/related — 2 credits
OpenAlex-curated related works for a paper (co-cited / topically-adjacent), hydrated

**Parameters:**
- `id` (string, required) — Paper id — OpenAlex id (W…), OR DOI (10.…), OR arXiv id, OR PMID.
- `limit` (integer, optional, default 25) — Max records (1-200, default 25); clamped.

**Returns:** results[] (related papers, hydrated), count, related_works_count, paper_id, stop_reason

**Example request body:**
```json
{
  "id": "W3177828909"
}
```

### POST /academic/v1/author — 1 credit
author search (query) or profile (id): works_count, h-index, affiliations; include_works for top papers

**Parameters:**
- `id` (string, optional) — OpenAlex author id for a profile. Supply `id` OR a `query`/`name`.
- `query` (string, optional) — Search text → ranked list. Supply this OR `id`.
- `include_works` (boolean, optional, default false) — Profile only: also return the author's top works (highest-cited first).
- `works_limit` (integer, optional, default 25) — Max top works when include_works=true (1-200).
- `per_page` (integer, optional, default 10) — Results per page (1-200, default 10); clamped.

**Returns:** profile: author{name,works_count,h_index,affiliations,top_works[]}; OR search: results[] (name, h_index, works_count), count

**Example request body:**
```json
{
  "query": "yoshua bengio"
}
```

### POST /academic/v1/institution — 1 credit
institution search/profile: ROR, country, geo, works/citation counts, h-index; include_works for the org's papers

**Parameters:**
- `id` (string, optional) — OpenAlex institution id for a profile. Supply `id` OR a `query`/`name`.
- `query` (string, optional) — Search text → ranked list. Supply this OR `id`.
- `per_page` (integer, optional, default 10) — Results per page (1-200, default 10); clamped.
- `include_works` (boolean, optional, default false) — Profile only: also return the institution's top works (highest-cited first).
- `works_limit` (integer, optional, default 25) — Max top works when include_works=true (1-200).

**Returns:** profile: institution{name,ror,country_code,geo,works_count,h_index,type,top_works[]?}; OR search: results[] (name, country_code, works_count), count

**Example request body:**
```json
{
  "query": "stanford"
}
```

### POST /academic/v1/venue — 1 credit
journal/venue search/profile: ISSN, publisher, OA/DOAJ, h-index, works/citation counts; include_works for the venue's papers

**Parameters:**
- `id` (string, optional) — OpenAlex venue/source id for a profile. Supply `id` OR a `query`/`name`.
- `query` (string, optional) — Search text → ranked list. Supply this OR `id`.
- `per_page` (integer, optional, default 10) — Results per page (1-200, default 10); clamped.
- `include_works` (boolean, optional, default false) — Profile only: also return the venue's top works (highest-cited first).
- `works_limit` (integer, optional, default 25) — Max top works when include_works=true (1-200).

**Returns:** profile: venue{name,issn_l,publisher,is_oa,is_in_doaj,h_index,works_count,top_works[]?}; OR search: results[] (name, issn_l), count

**Example request body:**
```json
{
  "query": "nature"
}
```

### POST /academic/v1/concept — 1 credit
concept search (query) or profile (id): level, works/citation counts, description; include_works for papers. NOTE: OpenAlex froze the Concepts dataset (ancestors/related now empty) — use `topic` for the live subject hierarchy

**Parameters:**
- `id` (string, optional) — OpenAlex concept id for a profile. Supply `id` OR a `query`/`name`.
- `query` (string, optional) — Search text → ranked list. Supply this OR `id`.
- `per_page` (integer, optional, default 10) — Results per page (1-200, default 10); clamped.
- `include_works` (boolean, optional, default false) — Profile only: also return the concept's top works (highest-cited first).
- `works_limit` (integer, optional, default 25) — Max top works when include_works=true (1-200).

**Returns:** profile: concept{name,level,works_count,cited_by_count,description,wikidata,ancestors[],related_concepts[],top_works[]?}; OR search: results[] (name, level), count

**Example request body:**
```json
{
  "query": "machine learning"
}
```

### POST /academic/v1/topic — 1 credit
topic search (query) or profile (id): domain>field>subfield hierarchy, keywords, siblings, works/citation counts; include_works for papers (the live replacement for Concepts)

**Parameters:**
- `id` (string, optional) — OpenAlex topic id for a profile. Supply `id` OR a `query`/`name`.
- `query` (string, optional) — Search text → ranked list. Supply this OR `id`.
- `per_page` (integer, optional, default 10) — Results per page (1-200, default 10); clamped.
- `include_works` (boolean, optional, default false) — Profile only: also return the topic's top works (highest-cited first).
- `works_limit` (integer, optional, default 25) — Max top works when include_works=true (1-200).

**Returns:** profile: topic{name,description,works_count,cited_by_count,keywords[],domain,field,subfield,siblings[],top_works[]?}; OR search: results[] (name), count

**Example request body:**
```json
{
  "query": "protein folding"
}
```

### POST /academic/v1/autocomplete — 1 credit
fast typeahead suggestions (works/authors/sources/institutions)

**Parameters:**
- `q` (string, required) — Typeahead prefix.
- `entity` (enum, optional, default "works") — Which entity type to autocomplete. An unknown value falls back to 'works'. [one of: works, authors, sources, institutions, concepts, topics]

**Returns:** suggestions[] (title, id, hint), count, entity

**Example request body:**
```json
{
  "q": "deep learn"
}
```

### POST /academic/v1/batch — 2 credits
hydrate up to 200 papers by id/DOI in one call (RAG/ETL)

**Parameters:**
- `ids` (array, required) — Up to 200 paper ids/DOIs to hydrate (list or comma-separated).
- `include_abstract` (boolean, optional, default false) — Include reconstructed abstracts in the hydrated rows (default false for batch).
- `limit` (integer, optional, default 100) — Max records (1-200, default 100); clamped.

**Returns:** results[] (hydrated papers), count, requested

## More
- Try it live, no code: https://reefapi.com/playground?engine=academic
- Human docs page: https://reefapi.com/docs/academic
- Every ReefAPI API in one file (for your AI): https://reefapi.com/llms-full.txt
