HubNews API
Free, public, no-auth REST API. Integrate tech articles, categories, and reaction data into your application in minutes.
Quick Start
Make your first request right now. No API key required:
curl -s "https://api.hubnews.ai/api/v1/public/articles?locale=en&per_page=3" | python3 -m json.toolBase URL
https://api.hubnews.ai/api/v1/publicRate Limiting
1,000 requests per hour per IP. Response headers include:
| Header | Description |
|---|---|
| X-RateLimit-Limit | Total limit per hour |
| X-RateLimit-Remaining | Remaining requests |
If you hit the limit, wait for the reset or contact us for higher limits.
Endpoints
GET
/articlesList Articles
Returns a paginated list of published articles, sorted by publication date (newest first).
Parameters
| Name | Type | Description |
|---|---|---|
| locale | string | Language (pt, en, es, fr). Default: pt |
| category | string | Filter by category slug |
| per_page | integer | Items per page (1-50). Default: 20 |
| page | integer | Page number |
Response
{
"data": [
{
"id": 123,
"title": "...",
"slug": "...",
"summary": "...",
"content": "...",
"category": { "name": "...", "slug": "..." },
"source": "TechCrunch",
"source_url": "https://...",
"image_url": "https://...",
"published_at": "2026-02-15T10:00:00+00:00",
"locale": "pt",
"views": 1234,
"reactions": { "like": 10, "dislike": 2 }
}
],
"meta": {
"current_page": 1,
"last_page": 340,
"per_page": 20,
"total": 6800
}
}GET
/articles/{slug}Get Article
Returns a full article by its translated slug.
Parameters
| Name | Type | Description |
|---|---|---|
| locale | string | Language (pt, en, es, fr). Default: pt |
Response
{
"data": {
"id": 123,
"title": "...",
"slug": "...",
"summary": "...",
"content": "<p>Full HTML content...</p>",
"category": { "name": "...", "slug": "..." },
"source": "TechCrunch",
"source_url": "https://...",
"image_url": "https://...",
"published_at": "2026-02-15T10:00:00+00:00",
"locale": "pt",
"views": 1234,
"reactions": { "like": 10, "dislike": 2 }
}
}
// 404
{
"error": "not_found",
"message": "Article not found."
}GET
/categoriesList Categories
Returns all active categories with article counts.
Parameters
| Name | Type | Description |
|---|---|---|
| locale | string | Language (pt, en, es, fr). Default: pt |
Response
{
"data": [
{
"id": 1,
"name": "Artificial Intelligence",
"slug": "artificial-intelligence",
"news_count": 3030
},
{
"id": 2,
"name": "Hardware",
"slug": "hardware",
"news_count": 859
},
{
"id": 5,
"name": "Cybersecurity",
"slug": "cybersecurity",
"news_count": 1241
}
]
}Article Fields
| Field | Type | Description |
|---|---|---|
| id | integer | Unique identifier |
| title | string | Article title in the requested language |
| slug | string | Article slug (used in the URL) |
| summary | string | Short article summary |
| content | string | HTML content (truncated in list, full in detail) |
| category | object|null | Object with category name and slug |
| source | string|null | Original source name |
| source_url | string | Original source URL |
| image_url | string|null | Cover image URL |
| published_at | string | Publication date in ISO 8601 format |
| locale | string | Language of the returned content |
| views | integer | Number of views |
| reactions | object | Reaction counts (like/dislike) |
Code Examples
cURL
# List latest articles in English
curl "https://api.hubnews.ai/api/v1/public/articles?locale=en&per_page=5"
# Get a specific article
curl "https://api.hubnews.ai/api/v1/public/articles/article-slug-here?locale=pt"
# List categories
curl "https://api.hubnews.ai/api/v1/public/categories?locale=en"
# Filter by category
curl "https://api.hubnews.ai/api/v1/public/articles?locale=pt&category=artificial-intelligence&per_page=10"JavaScript (fetch)
const API_BASE = "https://api.hubnews.ai/api/v1/public";
// List articles
async function getArticles({ locale = "pt", category, page = 1, perPage = 20 } = {}) {
const params = new URLSearchParams({ locale, page: String(page), per_page: String(perPage) });
if (category) params.set("category", category);
const res = await fetch(`${API_BASE}/articles?${params}`);
if (!res.ok) throw new Error(`API error: ${res.status}`);
return res.json(); // { data: Article[], meta: { ... } }
}
// Get single article
async function getArticle(slug, locale = "pt") {
const res = await fetch(`${API_BASE}/articles/${slug}?locale=${locale}`);
if (!res.ok) throw new Error(`API error: ${res.status}`);
return res.json(); // { data: Article }
}
// Get categories
async function getCategories(locale = "pt") {
const res = await fetch(`${API_BASE}/categories?locale=${locale}`);
if (!res.ok) throw new Error(`API error: ${res.status}`);
return res.json(); // { data: Category[] }
}Errors
The API returns standardized JSON responses for errors:
| Status | Description |
|---|---|
| 404 | Resource not found |
| 422 | Invalid parameters |
| 429 | Rate limit exceeded |
| 500 | Internal server error |
// 404 example
{
"error": "not_found",
"message": "Article not found."
}
// 422 example (validation)
{
"message": "The locale field must be one of: pt, en, es, fr.",
"errors": { "locale": ["The locale field must be one of: pt, en, es, fr."] }
}
// 429 example
HTTP 429 Too Many Requests
Retry-After: 3600Need higher limits?
If your project requires more than 1,000 requests per hour, get in touch. We can offer custom limits for partners and integrators.
Contact Us