Partner API
The Partner API gives approved partners programmatic access to Geek Haus articles, sources, and weekly digests.
Base URL
https://geekhaus.club/api/v1Authentication
Every request must include an API key in the Authorization header.
Authorization: Bearer YOUR_API_KEYYou can also send it as X-API-Key: YOUR_API_KEY.
Keys are issued manually. To request one, contact us.
Endpoints
List articles
GET /api/v1/articlesReturns the most recent articles in reverse-chronological order.
| Query param | Type | Default | Notes |
|---|---|---|---|
locale | en | ko | en | Editorial copy locale. |
source | string | — | Source slug (see /sources). |
since | ISO-8601 datetime | — | Only return articles at or after this time. |
limit | integer (1-100) | 20 | Page size. |
cursor | string | — | Pass the previous response's nextCursor. |
Request (curl):
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://geekhaus.club/api/v1/articles?source=anthropic-com&limit=5"Request (JavaScript / fetch):
const res = await fetch('https://geekhaus.club/api/v1/articles?source=anthropic-com&limit=5', {
headers: { Authorization: 'Bearer YOUR_API_KEY' },
})
const { items, nextCursor } = await res.json()Request (Python / requests):
import requests
res = requests.get(
"https://geekhaus.club/api/v1/articles",
params={"source": "anthropic-com", "limit": 5},
headers={"Authorization": "Bearer YOUR_API_KEY"},
timeout=10,
)
res.raise_for_status()
data = res.json()Response (200):
{
"items": [
{
"id": "8305e1bb-ba61-4c7d-a14c-0615970f3b36",
"slug": "2026/05/22/computer-science-student-in-a-ugandan-refugee",
"title": "Computer science student in a Ugandan refugee camp struggles to replace a broken laptop needed for remote coursework",
"originalTitle": "Shipping a Laptop to a Refugee Camp in Uganda",
"summary": "A University of London computer science student named Django, a Congolese refugee in Western Uganda, relies on solar power and prepaid Airtel data to complete remote coursework. His laptop's motherboard failed after a power accident, threatening his ability to attend lectures, submit assignments, and take proctored exams.",
"insight": "The story highlights how remote education can expand access while still depending on fragile infrastructure like electricity, devices, and connectivity. For students in crisis settings, **hardware access** is not a convenience but a core requirement for participation in the digital economy.",
"sourceUrl": "https://notesbylex.com/shipping-a-laptop-to-a-refugee-camp-in-uganda",
"sourceName": "notesbylex.com",
"sourceSlug": "notesbylex-com",
"publishedAt": "2026-05-22T21:36:55.000Z",
"crawledAt": "2026-05-23T00:00:25.186Z",
"thumbnailUrl": null
}
],
"nextCursor": "2026-05-22T21:36:55.000Z"
}Article body is intentionally not exposed. Use sourceUrl to link readers to the original.
Get a single article
GET /api/v1/articles/{slug}The slug is the full path form returned by /articles (e.g. 2026/05/22/foo-bar). Returns 404 if not found.
Request (curl):
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://geekhaus.club/api/v1/articles/2026/05/22/computer-science-student-in-a-ugandan-refugee"Request (JavaScript):
const slug = '2026/05/22/computer-science-student-in-a-ugandan-refugee'
const res = await fetch(`https://geekhaus.club/api/v1/articles/${slug}`, {
headers: { Authorization: 'Bearer YOUR_API_KEY' },
})
if (res.status === 404) throw new Error('Article not found')
const article = await res.json()Request (Python):
slug = "2026/05/22/computer-science-student-in-a-ugandan-refugee"
res = requests.get(
f"https://geekhaus.club/api/v1/articles/{slug}",
headers={"Authorization": "Bearer YOUR_API_KEY"},
timeout=10,
)
if res.status_code == 404:
raise SystemExit("Article not found")
article = res.json()Response (200): a single PublicArticle (same shape as one entry in items above).
Response (404):
{ "error": { "code": "not_found", "message": "Article not found: 2026/05/22/missing" } }List sources
GET /api/v1/sourcesReturns every publication that Geek Haus tracks, with article counts.
Request (curl):
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://geekhaus.club/api/v1/sources"Request (JavaScript):
const res = await fetch('https://geekhaus.club/api/v1/sources', {
headers: { Authorization: 'Bearer YOUR_API_KEY' },
})
const { sources } = await res.json()Response (200):
{
"sources": [
{
"name": "github.com",
"slug": "github-com",
"articleCount": 6,
"latestAt": "2026-05-22T18:11:09.000Z"
},
{
"name": "blog.google",
"slug": "blog-google",
"articleCount": 3,
"latestAt": "2026-05-21T15:42:00.000Z"
},
{
"name": "anthropic.com",
"slug": "anthropic-com",
"articleCount": 2,
"latestAt": "2026-05-22T19:31:45.000Z"
}
]
}Weekly digest
GET /api/v1/digestTop recent articles within a sliding window.
| Query param | Type | Default | Notes |
|---|---|---|---|
locale | en | ko | en | |
days | integer (1-90) | 7 | Window size in days. |
limit | integer (1-50) | 7 | Number of items to return. |
Request (curl):
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://geekhaus.club/api/v1/digest?days=7&limit=5"Request (JavaScript):
const res = await fetch('https://geekhaus.club/api/v1/digest?days=7&limit=5', {
headers: { Authorization: 'Bearer YOUR_API_KEY' },
})
const { items, window } = await res.json()Request (Python):
res = requests.get(
"https://geekhaus.club/api/v1/digest",
params={"days": 7, "limit": 5},
headers={"Authorization": "Bearer YOUR_API_KEY"},
timeout=10,
)
digest = res.json()Response (200):
{
"items": [
{
"id": "4a865ae5-ecee-4bf2-8812-78fe216d57b4",
"slug": "2026/05/22/project-glasswing-says-claude-mythos-preview",
"title": "Project Glasswing says Claude Mythos Preview found 10,000+ severe vulnerabilities across critical open-source software",
"originalTitle": "Project Glasswing: An Initial Update",
"summary": "Project Glasswing reports that Claude Mythos Preview and roughly 50 partners have identified more than 10,000 high- or critical-severity vulnerabilities in systemically important software.",
"insight": "The update suggests that vulnerability discovery has shifted from being scarce to being an operational overload problem for maintainers and defenders.",
"sourceUrl": "https://www.anthropic.com/research/glasswing-initial-update",
"sourceName": "anthropic.com",
"sourceSlug": "anthropic-com",
"publishedAt": "2026-05-22T19:31:45.000Z",
"crawledAt": "2026-05-23T00:01:03.824Z",
"thumbnailUrl": null
}
],
"window": {
"from": "2026-05-17T00:00:00.000Z",
"to": "2026-05-24T00:00:00.000Z"
}
}Error format
All errors share one envelope:
{ "error": { "code": "unauthorized", "message": "Missing API key." } }| HTTP | code | When |
|---|---|---|
| 400 | bad_request | Invalid query parameters. details contains field errors. |
| 401 | unauthorized | Missing or invalid API key. |
| 404 | not_found | Article or resource not found. |
| 502 | upstream_error | Feed service is unreachable. |
| 500 | internal_error | Unexpected server error. |
Field reference
PublicArticle
| Field | Type | Notes |
|---|---|---|
id | string (UUID) | Stable identifier. |
slug | string | Path form (2026/05/22/foo-bar). Pass to /articles/{slug}. |
title | string | Editor-rewritten headline when available, otherwise the original. Use this as the display title. |
originalTitle | string | Raw source headline. |
summary | string | null | Editorial summary (plain text). |
insight | string | null | Editorial commentary in markdown. |
sourceUrl | string | null | Link to the original article. |
sourceName | string | null | Human-readable source label (e.g. anthropic.com). |
sourceSlug | string | null | URL-safe slug derived from sourceName. |
publishedAt | string (ISO-8601) | null | When the source published the piece. |
crawledAt | string (ISO-8601) | When Geek Haus aggregated it. |
thumbnailUrl | string | null | Optional. |
PublicSource
| Field | Type | Notes |
|---|---|---|
name | string | Display name. |
slug | string | Pass to ?source= filter. |
articleCount | integer | Number of editorially-curated articles. |
latestAt | string (ISO-8601) | Most recent article timestamp. |
Conventions
- ▸HTTP methods: every endpoint accepts
GETonly. Other methods return405. - ▸Caching: responses are cached server-side for up to 60 seconds. Treat data as freshly published if you need real-time fan-out (use the digest for daily/weekly use cases).
- ▸CORS: the API is intended for server-to-server use. Browser clients on other origins will be blocked. If you need a browser-safe surface, contact us.
- ▸Versioning:
/api/v1/*is stable. Breaking changes will ship under/api/v2/*. Additive changes (new optional fields) may land onv1without notice.
Notes
- ▸Only articles with an editorial layer (summary or rewritten title) appear in list endpoints. Direct slug lookups return any article we have.
- ▸Source filter (
source=) is matched against the slug form (lowercased, non-alphanumerics replaced with-). - ▸
nextCursoris opaque. Pass it back verbatim to fetch the next page. - ▸Rate limiting is not enforced at the moment, but expect to be cut off if you sustain unusual traffic. Reach out so we can size up your access properly.