# Hacker News API — stories, comments, full comment trees, polls, front-page, user profiles and full-text search across Hacker News (news.ycombinator.com)

> single item by id (story/comment/job/poll/pollopt) — all official fields + time_iso/kids_count/hn_url; hydrate_kids=resolve top-level comments
> ReefAPI engine `hackernews` · 9 endpoints · clean JSON, no scraping or browsers to manage.

## How to call
- **Endpoint:** `POST https://api.reefapi.com/hackernews/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 /hackernews/v1/item — 1 credit
single item by id (story/comment/job/poll/pollopt) — all official fields + time_iso/kids_count/hn_url; hydrate_kids=resolve top-level comments

**Parameters:**
- `id` (integer, required) — HackerNews item id (story/comment/job/poll/pollopt) — the digits in an item URL (news.ycombinator.com/item?id=...).
- `hydrate_kids` (boolean, optional, default false) — If true, resolve the item's top-level comments into full objects instead of bare ids.
- `kids_limit` (integer, optional, default 30) — When hydrate_kids=true, how many top-level comments to resolve (1-100).

**Returns:** item{} — id, type, by, time/time_iso, title/text/url, score, kids/kids_count, hn_url (+ comments[] if hydrate_kids)

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

### POST /hackernews/v1/item_tree — 1 credit
full nested comment TREE for a story in ONE call; recursive children + descendants count

**Parameters:**
- `id` (integer, required) — HackerNews item id (story/comment/job/poll/pollopt) — the digits in an item URL (news.ycombinator.com/item?id=...).

**Returns:** item{} — story with recursive children[] (nested comments), descendants count, direct children_count, author

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

### POST /hackernews/v1/user — 1 credit
user profile by id: karma/created/about/submitted; hydrate_submitted=resolve recent submissions

**Parameters:**
- `id` (string, required) — HackerNews username (case-sensitive), e.g. 'pg'.
- `hydrate_submitted` (boolean, optional, default false) — If true, resolve the user's recent submissions into full objects instead of bare ids.
- `submitted_limit` (integer, optional, default 20) — When hydrate_submitted=true, how many recent submissions to resolve (1-100).

**Returns:** user{} — id, karma, created/created_iso, about, submitted[] (+ recent_items[] if hydrate_submitted)

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

### POST /hackernews/v1/stories — 2 credits
story-list (list=top/new/best/ask/show/job) → ranked hydrated stories; offset/limit pagination, hydrate=false for ids only

**Parameters:**
- `list` (enum, optional, default "top") — Which HackerNews story list to return. [one of: top, new, best, ask, show, job]
- `limit` (integer, optional, default 30) — Stories to return (1-100, default 30). Out-of-range values are clamped.
- `offset` (integer, optional, default 0) — Pagination offset into the story list (0-500). Skip N ranked stories.
- `hydrate` (boolean, optional, default true) — If true, resolve each ranked story id into full objects instead of bare ids (default true).

**Returns:** list, stories[] (ranked, hydrated) or ids[] (hydrate=false), count, total, offset, max_available, stop_reason

**Example request body:**
```json
{
  "list": "top",
  "limit": 15
}
```

### POST /hackernews/v1/search — 1 credit
Full-text search: query + tags(story/comment/ask_hn/show_hn/poll/front_page/author_X/story_X) + min_points/max_points/min_comments/before/after + sort(relevance|date), paginated

**Parameters:**
- `query` (string, optional) — Full-text search keywords. search needs query OR tags.
- `tags` (string, optional) — Tag filter. Built-ins: story, comment, ask_hn, show_hn, poll, front_page. Dynamic: author_USERNAME, story_ID. Comma-joins = AND, (a,b) = OR. search needs query OR tags.
- `sort` (enum, optional, default "relevance") — Result ordering: relevance (default) or date (newest first). Any non-date value is treated as relevance. [one of: relevance, date]
- `page` (integer, optional, default 0) — 0-based search results page (0-50). Page forward via meta.nbPages.
- `hits_per_page` (integer, optional, default 20) — Search results per page (1-100, default 20).
- `min_points` (integer, optional) — Minimum score (points) filter for search hits.
- `max_points` (integer, optional) — Maximum score (points) filter for search hits.
- `min_comments` (integer, optional) — Minimum comment-count filter for search hits.
- `max_comments` (integer, optional) — Maximum comment-count filter for search hits.
- `before` (string, optional) — Only hits created on/before this date. Accepts a unix timestamp or an ISO date (YYYY-MM-DD).
- `after` (string, optional) — Only hits created on/after this date. Accepts a unix timestamp or an ISO date (YYYY-MM-DD).
- `numeric_filters` (string, optional) — Advanced: raw Algolia numericFilters string, appended to the built min/max/date filters (e.g. 'points>100,created_at_i>1700000000').
- `restrict` (string, optional) — Advanced: restrictSearchableAttributes — limit matching to given Algolia fields (e.g. 'title' or 'title,story_text').

**Returns:** hits[] (title/text, points, author, num_comments, created_at, hn_url), count, nbHits, nbPages, page, sort

**Example request body:**
```json
{
  "query": "python",
  "tags": "story"
}
```

### POST /hackernews/v1/poll — 1 credit
Poll detail by id: the question + every voting option resolved and ranked by votes, with total_votes and the comment count. (Find poll ids via search with tags=poll.)

**Parameters:**
- `id` (integer, required) — HackerNews poll id (the digits in a poll's item URL). Find polls with the search action using tags=poll.

**Returns:** poll{} — id, title/text, by, time_iso, options[] (each id/text/score=votes, ranked), options_count, total_votes, descendants (comments), hn_url

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

### POST /hackernews/v1/front_page — 1 credit
Stories that recently made the Hacker News front page (newest-first), paginated. Optional after/before date window. NOTE: the front-page index only retains ~the last 7 days — it is 'what's on / recently hit the front page', not a historical archive.

**Parameters:**
- `limit` (integer, optional, default 30) — Front-page stories to return (1-100, default 30). Out-of-range values are clamped.
- `page` (integer, optional, default 0) — 0-based search results page (0-50). Page forward via meta.nbPages.
- `after` (string, optional) — Only front-page stories created on/after this date (unix ts or YYYY-MM-DD). Note: the front-page index only retains ~the last 7 days.
- `before` (string, optional) — Only front-page stories created on/before this date (unix ts or YYYY-MM-DD).

**Returns:** stories[] (title, author, points, num_comments, created_at, hn_url), count, nbHits, nbPages, page

**Example request body:**
```json
{
  "limit": 10
}
```

### POST /hackernews/v1/updates — 1 credit
live changefeed: recently changed item ids + profiles + max_item; hydrate=resolve changed items

**Parameters:**
- `hydrate` (boolean, optional, default false) — If true, resolve the changed item ids into full objects instead of bare ids.
- `limit` (integer, optional, default 30) — Changed items to hydrate (1-100, default 30). Out-of-range values are clamped.

**Returns:** items[] (changed ids), profiles[] (changed usernames), items_count, profiles_count, max_item (+ changed_items[] if hydrate)

### POST /hackernews/v1/max_item — 1 credit
the current largest item id on Hacker News — the newest id, useful for backfilling / id-range walks

**Parameters:** none

**Returns:** max_item (int)

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