| name | api-analytics-proxy |
| description | Transparent HTTP reverse proxy that records every request and response to SQLite and exposes a React dashboard for traffic analytics, latency percentiles, and error inspection |
| triggers | ["api proxy","analytics proxy","http proxy analytics","request logging","api traffic","latency monitoring","proxy analytics"] |
api-analytics-proxy Skill
When to Use
Use this skill when you need to:
- Observe what HTTP traffic is flowing between your application and an upstream API without modifying your application code
- Debug API integration issues by inspecting full request and response headers and bodies
- Measure real latency distribution (p50/p95/p99) for specific endpoints over time
- Identify which endpoints have the highest error rates
- Monitor an upstream API for downtime (502 errors surface immediately in the dashboard)
Prerequisites
- Node.js 20+
- pnpm 9+
- Access to the upstream API URL
Quick Start
cd api-analytics-proxy
cp .env.example .env
pnpm install
pnpm --filter proxy dev
pnpm --filter dashboard dev
Point your HTTP client at http://localhost:8080 instead of the upstream URL. All traffic is forwarded and recorded.
Docker Quick Start
PROXY_UPSTREAM_URL=https://api.example.com docker compose up
Using the Proxy
Replace the upstream base URL with the proxy URL in your application or client:
curl https://api.example.com/users
curl http://localhost:8080/users
The proxy forwards all headers (except Host), all methods, query strings, and bodies transparently. The upstream sees the request as if it came directly from you.
Admin API Reference
The admin API runs on port 8081. All endpoints return JSON.
GET /api/requests
List recorded requests with optional filters.
Query parameters:
| Param | Type | Description |
|---|
page | number | Page number (default 1) |
limit | number | Results per page, max 100 (default 50) |
method | string | Filter by HTTP method |
status_gte | number | Minimum status code |
status_lte | number | Maximum status code |
path_search | string | LIKE match on path |
latency_gte_ms | number | Minimum latency in ms |
latency_lte_ms | number | Maximum latency in ms |
from | string | ISO 8601 start timestamp |
to | string | ISO 8601 end timestamp |
Example:
curl "http://localhost:8081/api/requests?status_gte=500&limit=10"
GET /api/requests/:id
Full request record including complete body content.
GET /api/stats
Aggregate statistics: total requests, error rate, latency percentiles, status code breakdown.
curl http://localhost:8081/api/stats
GET /api/stats/timeseries
Time-bucketed data for charts. Query params: interval (1m, 5m, 1h), from, to.
GET /api/endpoints
Per-endpoint performance summary sorted by call count.
GET /api/errors
Filtered view of 4xx and 5xx responses.
GET /api/live
SSE endpoint for real-time request streaming.
curl -N http://localhost:8081/api/live
Each event:
event: request
data: {"id":1234,"method":"POST","path":"/api/users","status":201,"latency_ms":58}
GET /api/settings
Returns current proxy settings.
POST /api/settings
Update proxy settings. Changes take effect immediately without restart.
curl -X POST http://localhost:8081/api/settings \
-H "Content-Type: application/json" \
-d '{"retention_days": 7, "record_bodies": false}'
DELETE /api/requests
Delete all recorded requests.
curl -X DELETE http://localhost:8081/api/requests
Environment Variables
| Variable | Default | Description |
|---|
PROXY_PORT | 8080 | Port the proxy listens on |
API_PORT | 8081 | Port the admin API listens on |
PROXY_UPSTREAM_URL | required | Base URL of the upstream to proxy |
DB_PATH | ./data/proxy.db | SQLite database file path |
PROXY_RECORD_BODIES | 1 | Set to 0 to skip body recording |
MAX_BODY_BYTES | 65536 | Max bytes to store per body (64 KB) |
PROXY_IGNORE_PATHS | `` | Comma-separated glob patterns to exclude |
PROXY_REDACT_HEADERS | authorization,cookie,set-cookie | Headers to redact |
RETENTION_DAYS | 30 | Days to keep records |
CORS_ORIGIN | http://localhost:5173 | Dashboard CORS origin |
VITE_API_URL | http://localhost:8081 | Dashboard API base URL |
Endpoint Pattern Normalization
The proxy automatically normalizes path params for grouping:
/users/123 groups as /users/:id
/jobs/550e8400-e29b-41d4-a716-446655440000 groups as /jobs/:id
/docs/507f1f77bcf86cd799439011 groups as /docs/:id
This allows the Endpoints page to show aggregate stats across all calls to the same logical endpoint regardless of the specific ID.
Ignoring Paths
Use PROXY_IGNORE_PATHS to prevent health checks or metrics endpoints from cluttering the log:
PROXY_IGNORE_PATHS=/health,/healthz,/metrics,/favicon.ico
Matching requests are still forwarded to the upstream but not recorded in the database.
Header Redaction
Sensitive headers are replaced with [REDACTED] before storing. Default redacted headers:
authorization
cookie
set-cookie
Add more via PROXY_REDACT_HEADERS:
PROXY_REDACT_HEADERS=authorization,cookie,set-cookie,x-api-key,x-secret-token
Retention
Records older than RETENTION_DAYS days are automatically deleted every hour. Set to 0 to disable automatic deletion.
Troubleshooting
502 errors for all requests
The upstream URL is unreachable. Check PROXY_UPSTREAM_URL and that the upstream service is running. The dashboard shows an alert banner when the upstream is down.
No requests appearing in dashboard
Ensure you are sending requests to port 8080 (the proxy) not 8081 (the admin API). The admin API routes are not recorded.
Bodies not appearing
PROXY_RECORD_BODIES may be set to 0, or the body exceeded MAX_BODY_BYTES and was truncated. The response_body field shows [truncated] when the limit is exceeded.
Dashboard cannot connect to API
Check VITE_API_URL in the dashboard environment and ensure CORS_ORIGIN on the proxy matches the dashboard origin.
Database growing too large
Lower RETENTION_DAYS or set PROXY_RECORD_BODIES=0. Run DELETE /api/requests to clear all data immediately.