FastAPI service for accessing Context News RDS data.
- Install dependencies with Poetry:
poetry install- Set
DATABASE_URLto your RDS connection string (use.envor export).
Example:
export DATABASE_URL="postgresql+psycopg2://user:pass@host:5432/dbname"poetry run uvicorn app.main:app --reloadBuild the image:
docker build -t context-api .Run the container (pass your database URL as an env var):
docker run --rm -p 8000:8000 -e DATABASE_URL="postgresql+psycopg2://user:pass@host:5432/dbname" context-apiThe API is organized into four main sections:
/admin- Administrative endpoints (status checks)/landing- Landing page endpoints (top stories by region)/news- News data endpoints (stories, articles, analytics, sources)/data- Time series data endpoints (indicators, entities, datapoints)
Most /news endpoints support these filtering parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
period |
enum | today |
Time period filter: today, last_24_hours, week, month |
region |
enum | none | Region filter: north_america, south_america, europe, africa, middle_east, asia, oceania |
from_date |
date | none | Custom start date (YYYY-MM-DD) |
to_date |
date | none | Custom end date (YYYY-MM-DD) |
limit |
int | none | Max results (1-100) |
| Method | Endpoint | Description |
|---|---|---|
| GET | /admin/status/ |
Health check |
| GET | /admin/status/badge |
Status badge for shields.io |
| Method | Endpoint | Description |
|---|---|---|
| GET | /landing/top-stories |
Top 3 stories per region |
The top-stories endpoint supports the period query parameter (default: week).
Period semantics:
today: current calendar day (00:00to next00:00)last_24_hours: rolling 24-hour window ending now
| Method | Endpoint | Description |
|---|---|---|
| GET | /news/stories/ |
List stories with full details (including persons) |
| GET | /news/stories/news-feed |
Paginated story cards for news feed UI |
| GET | /news/stories/{story_id} |
Get a single story by ID |
| Method | Endpoint | Description |
|---|---|---|
| GET | /news/articles/ |
List articles |
| GET | /news/articles/{article_id} |
Get a single article by ID |
| Method | Endpoint | Description |
|---|---|---|
| GET | /news/analytics/top-locations |
Top mentioned locations |
| GET | /news/analytics/top-people |
Top mentioned people |
| GET | /news/analytics/top-organizations |
Top mentioned organizations |
Analytics endpoints support an additional interval parameter:
| Parameter | Type | Default | Description |
|---|---|---|---|
interval |
enum | none | Historical breakdown: hourly, daily |
When interval is provided, the response includes a history array with counts per time bucket.
| Method | Endpoint | Description |
|---|---|---|
| GET | /news/sources/ |
List all news sources |
| Method | Endpoint | Description |
|---|---|---|
| GET | /data/entities |
List entities, optionally filtered by type |
| GET | /data/entities/{entity_id} |
Get a single entity by ID |
Supports entity_type query param: country, region, union, bloc.
| Method | Endpoint | Description |
|---|---|---|
| GET | /data/sources |
List all data sources (e.g. World Bank, IMF) |
| GET | /data/indicators |
List indicators, optionally filtered by source or frequency |
| GET | /data/indicators/{indicator_id} |
Get a single indicator by ID |
/data/indicators supports source_id (int) and frequency (annual, quarterly, monthly) query params.
| Method | Endpoint | Description |
|---|---|---|
| GET | /data/datapoints |
Fetch time series data grouped by (indicator, entity) |
| Parameter | Type | Required | Description |
|---|---|---|---|
indicator_id |
string | Yes | Repeatable: ?indicator_id=X&indicator_id=Y |
entity_id |
string | No | Repeatable. Omit to get all entities for the given indicators |
period |
enum | No | 1y, 5y (default), 10y, 20y, all |
from_date |
date | No | Explicit start date, overrides period |
to_date |
date | No | Explicit end date, overrides period |
{
"status": "ok"
}{
"schemaVersion": 1,
"label": "api",
"message": "healthy",
"color": "brightgreen"
}[
{
"region": "north_america",
"stories": [
{
"story_id": "47cb5ca6",
"title": "Example story title",
"locations": [
{
"wikidata_qid": "Q30",
"name": "United States",
"location_type": "country",
"country_code": "USA",
"latitude": 39.8283,
"longitude": -98.5795
}
]
}
]
},
{
"region": "south_america",
"stories": []
}
][
{
"id": "string",
"source": "string",
"title": "string",
"summary": "string",
"url": "string",
"published_at": "2024-01-01T12:00:00Z",
"ingested_at": "2024-01-01T12:05:00Z",
"locations": [
{
"wikidata_qid": "Q39",
"name": "Switzerland",
"location_type": "country",
"country_code": "CHE",
"latitude": 46.8182,
"longitude": 8.2275
}
]
}
][
{
"story_id": "47cb5ca6",
"title": "Example story title",
"summary": "A summary of the story...",
"key_points": [
"First key point",
"Second key point"
],
"topics": ["Politics", "Economy"],
"locations": [
{
"wikidata_qid": "Q39",
"name": "Switzerland",
"location_type": "country",
"country_code": "CHE",
"latitude": 46.8182,
"longitude": 8.2275
}
],
"persons": [
{
"wikidata_qid": "Q76",
"name": "Barack Obama",
"description": "44th president of the United States",
"nationalities": ["United States"],
"image_url": "https://upload.wikimedia.org/example.jpg"
}
],
"story_period": "2024-01-01T00:00:00Z",
"generated_at": "2024-01-01T12:00:00Z",
"updated_at": "2024-01-01T14:00:00Z",
"articles": [
{
"article_id": "e6489b58bc3e7fb4",
"headline": "Article headline",
"source": "bbc",
"url": "https://www.bbc.com/news/articles/example",
"image_url": "https://example.com/image.jpg"
}
]
}
]Returns the same shape as GET /news/stories/ plus:
{
"related_stories": [
{
"story_id": "a1b2c3d4",
"title": "Related story title",
"summary": "A summary of the related story...",
"story_period": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T14:00:00Z"
}
]
}Supports pagination via offset and limit query parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
offset |
int | 0 |
Number of stories to skip |
limit |
int | 25 |
Page size (1-100) |
{
"stories": [
{
"story_id": "47cb5ca6",
"title": "Example story title",
"topics": ["Politics", "Economy"],
"locations": [
{
"wikidata_qid": "Q39",
"name": "Switzerland",
"location_type": "country",
"country_code": "CHE",
"latitude": 46.8182,
"longitude": 8.2275
}
],
"persons": [
{
"wikidata_qid": "Q76",
"name": "Barack Obama",
"description": "44th president of the United States",
"nationalities": ["United States"],
"image_url": "https://upload.wikimedia.org/example.jpg"
}
],
"article_count": 5,
"sources_count": 3,
"story_period": "2024-01-01",
"updated_at": "2024-01-01T14:00:00Z",
"image_url": "https://example.com/image.jpg"
}
],
"offset": 0,
"limit": 25,
"has_more": true
}Without interval parameter:
[
{
"type": "gpe",
"name": "United States",
"count": 542
}
]With interval=daily parameter:
[
{
"type": "gpe",
"name": "United States",
"count": 542,
"history": [
{"timestamp": "2024-01-01T00:00:00Z", "count": 72},
{"timestamp": "2024-01-02T00:00:00Z", "count": 85},
{"timestamp": "2024-01-03T00:00:00Z", "count": 68}
]
}
][
{
"indicator": {
"id": "NY.GDP.MKTP.CD",
"name": "GDP (current US$)",
"unit": "USD",
"frequency": "annual",
"source": {
"id": 1,
"name": "World Bank",
"url": "https://data.worldbank.org"
}
},
"entity": {
"id": "Q142",
"name": "France",
"entity_type": "country"
},
"datapoints": [
{ "date": "2020-01-01", "value": 2694228152353.0 },
{ "date": "2021-01-01", "value": 2957878836969.0 },
{ "date": "2022-01-01", "value": 2779092039232.0 }
]
}
][
{
"source": "bbc",
"name": "BBC News",
"url": "https://feeds.bbci.co.uk/news/rss.xml",
"bias": "center",
"owner": "BBC",
"state_media": true,
"based": "UK"
}
]