API Reference
Public REST API for 21st News. Read-only access to stories, comments, and users — no authentication required.
Base URL
https://news.21st.dev
All endpoints are public. No API key or authentication is needed. Responses are JSON with a Cache-Control: public, s-maxage=60 header.
Endpoints
Stories
| GET | /api/v1/news/top | Top Stories |
| GET | /api/v1/news/new | New Stories |
| GET | /api/v1/news/best | Best Stories |
| GET | /api/v1/news/show | Show Stories |
| GET | /api/v1/news/ask | Ask Stories |
Items
| GET | /api/v1/news/item/:id | Get Item |
Users
| GET | /api/v1/news/user/:username | Get User |
List Endpoints
GEThttps://news.21st.dev/api/v1/news/top
Each list endpoint returns a plain JSON array of up to 500 numeric item IDs. Use the item endpoint to fetch full details for each ID.
| Endpoint | Sort |
|---|---|
| /api/v1/news/top | Hot rank (trending) |
| /api/v1/news/new | Creation date (newest first) |
| /api/v1/news/best | Score (all-time highest) |
| /api/v1/news/show | Show 21st posts by hot rank |
| /api/v1/news/ask | Ask 21st posts by hot rank |
Response
[150, 149, 148, 147, 146, 145, ...]
Example
curl https://news.21st.dev/api/v1/news/top
Get Item
GEThttps://news.21st.dev/api/v1/news/item/:id
Returns a single item — either a story or a comment — by its numeric ID. Stories and comments share the same ID space.
Story Fields
| Field | Type | Description |
|---|---|---|
| id | number | Unique item ID |
| type | "story" | Always "story" |
| by | string | Username of the author |
| time | number | Unix timestamp of creation |
| title | string | Story title |
| url | string? | URL for link posts (omitted for text posts) |
| text | string? | Body markdown for text/show/ask posts |
| score | number | Upvote count |
| descendants | number | Total comment count |
| kids | number[] | IDs of direct child comments, ranked by score |
Response
{
"id": 42,
"type": "story",
"by": "serafim",
"time": 1713000000,
"title": "Show 21st: A new way to build UIs",
"url": "https://example.com/article",
"score": 15,
"descendants": 3,
"kids": [43, 44, 47]
}Comment Fields
| Field | Type | Description |
|---|---|---|
| id | number | Unique item ID |
| type | "comment" | Always "comment" |
| by | string | Username of the author |
| time | number | Unix timestamp of creation |
| text | string | Comment body in markdown |
| parent | number | ID of parent item (story or comment) |
| kids | number[] | IDs of direct child replies |
Response
{
"id": 43,
"type": "comment",
"by": "alice",
"time": 1713003600,
"text": "This looks great! How does it handle SSR?",
"parent": 42,
"kids": [45, 46]
}Deleted items return {"id": 42, "type": "story", "deleted": true}
Dead items (flagged/hidden) return {"id": 42, "type": "story", "dead": true}
Example
curl https://news.21st.dev/api/v1/news/item/42
Get User
GEThttps://news.21st.dev/api/v1/news/user/:username
Returns a public user profile by username.
| Field | Type | Description |
|---|---|---|
| id | string | Username |
| created | number | Unix timestamp of account creation |
| karma | number | User's news karma |
| about | string | User bio (empty string if not set) |
Response
{
"id": "serafim",
"created": 1700000000,
"karma": 42,
"about": "Building 21st.dev"
}Example
curl https://news.21st.dev/api/v1/news/user/serafim
Design Notes
- The API is modeled after the Hacker News API for maximum compatibility with existing clients and tools.
- Stories and comments share a single ID namespace — every ID is unique across both types.
- All responses include
Cache-Control: public, s-maxage=60for edge caching. - Hidden and killed items return minimal payloads with
deadordeletedflags. - Timestamps are Unix seconds (not milliseconds).
- Text content (
textfield) is raw Markdown.