-
Notifications
You must be signed in to change notification settings - Fork 0
API Reference
Wiki Sync Bot edited this page Jul 20, 2025
·
1 revision
Complete documentation for Running Page 2.0 REST API endpoints.
Local Development: http://localhost:3000/api
Production: https://your-domain.com/api
Most endpoints are public for read access. Write operations require proper authentication.
# No authentication required for read operations
GET /api/activities
GET /api/stats
# GitHub Actions use repository secrets for sync operations
POST /api/sync/stravaRetrieve paginated list of activities with filtering options.
GET /api/activitiesQuery Parameters:
| Parameter | Type | Description | Default |
|---|---|---|---|
page |
number | Page number (1-based) | 1 |
limit |
number | Items per page (max 50) | 20 |
type |
string | Activity types (comma-separated) | all |
source |
string | Data sources (comma-separated) | all |
startDate |
string | Start date (ISO 8601) | - |
endDate |
string | End date (ISO 8601) | - |
minDistance |
number | Minimum distance (km) | - |
maxDistance |
number | Maximum distance (km) | - |
search |
string | Search in activity names | - |
Example Request:
curl "https://your-domain.com/api/activities?page=1&limit=10&type=running,cycling&search=morning"Response:
{
"activities": [
{
"id": 12345,
"name": "Morning Run",
"type": "Run",
"distance": 8500,
"moving_time": 2304,
"total_elevation_gain": 145,
"start_date": "2025-07-20T06:30:00Z",
"average_speed": 3.69,
"average_heartrate": 165,
"calories": 420,
"location_city": "San Francisco",
"location_country": "United States"
}
],
"pagination": {
"page": 1,
"limit": 10,
"total": 150,
"hasNext": true,
"hasPrev": false
},
"summary": {
"totalActivities": 150,
"totalDistance": 1250.5,
"totalTime": 345600,
"typeDistribution": [
{ "type": "Run", "count": 89, "percentage": 59.3 },
{ "type": "Ride", "count": 45, "percentage": 30.0 },
{ "type": "Swim", "count": 16, "percentage": 10.7 }
]
}
}GET /api/activities/{id}Response:
{
"id": 12345,
"name": "Morning Run",
"type": "Run",
"distance": 8500,
"moving_time": 2304,
"elapsed_time": 2400,
"total_elevation_gain": 145,
"start_date": "2025-07-20T06:30:00Z",
"start_latlng": [37.7749, -122.4194],
"end_latlng": [37.7849, -122.4094],
"average_speed": 3.69,
"max_speed": 5.2,
"average_heartrate": 165,
"max_heartrate": 185,
"calories": 420,
"location_city": "San Francisco",
"location_state": "California",
"location_country": "United States",
"polyline": "encoded_polyline_string",
"summary_polyline": "encoded_summary_polyline"
}GET /api/statsQuery Parameters:
| Parameter | Type | Description | Default |
|---|---|---|---|
year |
number | Filter by year | current year |
month |
number | Filter by month (1-12) | - |
type |
string | Activity types | all |
Response:
{
"overview": {
"totalActivities": 150,
"totalDistance": 1250.5,
"totalTime": 345600,
"totalElevation": 12500,
"averageDistance": 8.34,
"averageTime": 2304
},
"monthly": [
{
"month": "2025-01",
"activities": 12,
"distance": 98.5,
"time": 28800,
"elevation": 1200
}
],
"typeDistribution": [
{ "type": "Run", "count": 89, "distance": 750.2, "time": 201600 },
{ "type": "Ride", "count": 45, "distance": 450.8, "time": 108000 },
{ "type": "Swim", "count": 16, "distance": 49.5, "time": 36000 }
],
"heatmapData": [
{ "date": "2025-01-01", "count": 1, "distance": 8.5 },
{ "date": "2025-01-02", "count": 0, "distance": 0 }
],
"personalRecords": {
"longestDistance": { "value": 42.2, "date": "2025-06-15", "activityId": 98765 },
"longestTime": { "value": 10800, "date": "2025-06-15", "activityId": 98765 },
"fastestPace": { "value": 3.2, "date": "2025-05-20", "activityId": 87654 }
}
}GET /api/maps/{activityId}Response:
{
"exists": true,
"source": "cdn",
"url": "https://cdn.jsdelivr.net/gh/user/repo@master/apps/web/public/maps/12345.png",
"fallbackUrl": "https://api.mapbox.com/styles/v1/mapbox/dark-v10/static/...",
"cached": true,
"size": 245760
}GET /api/cache/statsResponse:
{
"totalMaps": 424,
"cacheHitRate": "94.2%",
"avgLoadTime": "245ms",
"cdnHits": 387,
"localHits": 36,
"apiFallbacks": 1,
"totalSize": "43.96 MB",
"lastUpdated": "2025-07-20T10:30:00Z"
}POST /api/sync/stravaHeaders:
Authorization: Bearer github_token
Content-Type: application/jsonRequest Body:
{
"force": false,
"generateMaps": true,
"dateRange": {
"start": "2025-01-01",
"end": "2025-07-20"
}
}Response:
{
"success": true,
"message": "Sync completed successfully",
"stats": {
"newActivities": 5,
"updatedActivities": 2,
"mapsGenerated": 3,
"processingTime": 45.2
},
"errors": []
}GET /api/sync/statusResponse:
{
"isRunning": false,
"lastSync": "2025-07-20T06:00:00Z",
"nextSync": "2025-07-20T12:00:00Z",
"status": "completed",
"progress": {
"current": 150,
"total": 150,
"percentage": 100
},
"logs": [
{ "timestamp": "2025-07-20T06:00:15Z", "level": "info", "message": "Starting Strava sync" },
{ "timestamp": "2025-07-20T06:01:30Z", "level": "success", "message": "Sync completed" }
]
}GET /api/debugResponse:
{
"version": "2.0.0",
"environment": "production",
"database": {
"path": "./data/running_page_2.db",
"size": "2.5 MB",
"tables": ["activities", "users", "sync_logs"],
"lastBackup": "2025-07-20T00:00:00Z"
},
"cache": {
"redis": false,
"memory": true,
"hitRate": "89.5%"
},
"maps": {
"total": 424,
"size": "43.96 MB",
"cdnEnabled": true
},
"performance": {
"uptime": 86400,
"memoryUsage": "125 MB",
"cpuUsage": "2.5%"
}
}GET /api/data-sourcesResponse:
{
"sources": [
{
"id": "strava",
"name": "Strava",
"enabled": true,
"connected": true,
"lastSync": "2025-07-20T06:00:00Z",
"activities": 145,
"status": "active"
},
{
"id": "garmin",
"name": "Garmin Connect",
"enabled": false,
"connected": false,
"lastSync": null,
"activities": 0,
"status": "not_configured"
}
],
"total": 145,
"lastUpdate": "2025-07-20T06:00:00Z"
}{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid query parameters",
"details": {
"field": "limit",
"value": 100,
"constraint": "Maximum limit is 50"
},
"timestamp": "2025-07-20T10:30:00Z"
}
}| Code | Status | Description |
|---|---|---|
VALIDATION_ERROR |
400 | Invalid request parameters |
NOT_FOUND |
404 | Resource not found |
RATE_LIMITED |
429 | Too many requests |
SERVER_ERROR |
500 | Internal server error |
DATABASE_ERROR |
500 | Database connection issue |
SYNC_ERROR |
503 | Data sync in progress |
# Rate limit headers in response
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1642694400Limits:
- Public API: 1000 requests/hour per IP
- Sync API: 10 requests/hour per repository
- Maps API: 500 requests/hour per IP
# Get recent activities
curl -X GET "https://your-domain.com/api/activities?limit=5" \
-H "Accept: application/json"
# Get statistics for current year
curl -X GET "https://your-domain.com/api/stats?year=2025" \
-H "Accept: application/json"
# Check map availability
curl -X GET "https://your-domain.com/api/maps/12345" \
-H "Accept: application/json"// Fetch activities with filtering
const response = await fetch('/api/activities?type=running&limit=10');
const data = await response.json();
// Get activity statistics
const stats = await fetch('/api/stats?year=2025');
const statsData = await stats.json();
// Check cache status
const cache = await fetch('/api/cache/stats');
const cacheData = await cache.json();import { RunningPageAPI } from '@running-page/sdk';
const api = new RunningPageAPI('https://your-domain.com');
// Get activities
const activities = await api.activities.list({ type: 'running', limit: 10 });
// Get statistics
const stats = await api.stats.get({ year: 2025 });Need help with the API? Check out our Troubleshooting guide or open an issue! π‘