ReqKey.docs
API reference

Analytics

Query aggregated stats, timeseries, breakdowns, and logs across two datasets: api_traffic and key_activity. Rate-limited per customer.

POST/analytics/statsBearer

Aggregate stats

source selects the dataset: api_traffic (full proxy logs) or key_activity (validation events). timeRange defaults to "24h".

Body
source"api_traffic" | "key_activity"required

Which dataset to query.

timeRangestring

1h, 3h, 6h, 12h, 24h, 7d, 30d. Default 24h.

apiIdstring

Filter to a specific API.

filtersobject

Narrow by endpoint, method, statusCode, clientIp, consumer.

Request
curl -X POST "https://api.reqkey.com/analytics/stats" \
  -H "Authorization: Bearer reqkey_xxx..." \
  -H "Content-Type: application/json" \
  -d '{
  "source": "api_traffic",
  "timeRange": "24h",
  "filters": {}
}'
Response
{
  "source": "api_traffic",
  "timeRange": "24h",
  "stats": {
    "totalRequests": 15230,
    "errorRate": 2.45,
    "avgLatencyMs": 128.5
  }
}
Errors
400Invalid or missing parameters
401Invalid or missing auth token
429Rate limited — check Retry-After
POST/analytics/stats/detailsBearer

Stat card drill-down

Timeseries + breakdown for a single stat card.

Body
sourcestringrequired

api_traffic or key_activity.

cardstringrequired

totalRequests, totalApiCalls, errorRate, or latency.

timeRangestring

Default 24h.

filtersobject

Optional dimension filters.

Request
curl -X POST "https://api.reqkey.com/analytics/stats/details" \
  -H "Authorization: Bearer reqkey_xxx..." \
  -H "Content-Type: application/json" \
  -d '{
  "source": "api_traffic",
  "card": "errorRate",
  "timeRange": "24h",
  "filters": {}
}'
Response
{
  "source": "api_traffic",
  "card": "errorRate",
  "timeRange": "24h",
  "details": {
    "errorBreakdown": [
      {
        "code": "404",
        "count": 150,
        "percentage": 60
      },
      {
        "code": "500",
        "count": 80,
        "percentage": 32
      },
      {
        "code": "429",
        "count": 20,
        "percentage": 8
      }
    ]
  }
}
Errors
400Invalid card or parameters
POST/analytics/timeseriesBearer

Timeseries

Time-bucketed requests, errors, and latency for charts.

Body
sourcestringrequired

api_traffic or key_activity.

timeRangestring

Default 24h. Bucket size is chosen automatically.

filtersobject

Optional dimension filters.

Request
curl -X POST "https://api.reqkey.com/analytics/timeseries" \
  -H "Authorization: Bearer reqkey_xxx..." \
  -H "Content-Type: application/json" \
  -d '{
  "source": "api_traffic",
  "timeRange": "24h",
  "filters": {}
}'
Response
{
  "source": "api_traffic",
  "timeRange": "24h",
  "granularity": "1 HOUR",
  "data": [
    {
      "timeBucket": "2026-02-23T12:00:00Z",
      "requests": 500,
      "errors": 25,
      "avgLatencyMs": 125.5
    },
    {
      "timeBucket": "2026-02-23T13:00:00Z",
      "requests": 450,
      "errors": 18,
      "avgLatencyMs": 110.25
    }
  ]
}
Errors
400Invalid parameters
POST/analytics/breakdownBearer

Dimension breakdown

Top values for a dimension, ranked by request count (max 50).

Body
sourcestringrequired

api_traffic or key_activity.

dimensionstringrequired

endpoint, method, statusCode, clientIp, or consumer.

timeRangestring

Default 24h.

filtersobject

Optional dimension filters.

Request
curl -X POST "https://api.reqkey.com/analytics/breakdown" \
  -H "Authorization: Bearer reqkey_xxx..." \
  -H "Content-Type: application/json" \
  -d '{
  "source": "api_traffic",
  "dimension": "endpoint",
  "timeRange": "24h",
  "filters": {}
}'
Response
{
  "source": "api_traffic",
  "dimension": "endpoint",
  "timeRange": "24h",
  "data": [
    {
      "value": "/api/users",
      "count": 5000,
      "percentage": 45.5
    },
    {
      "value": "/api/products",
      "count": 3200,
      "percentage": 29.1
    },
    {
      "value": "/api/orders",
      "count": 2800,
      "percentage": 25.4
    }
  ]
}
  • Filtering by the same dimension you break down on is ignored to prevent self-filtering.
Errors
400Invalid dimension or parameters
POST/analytics/logsBearer

Log list

Returns one page of log rows plus a nextCursor. Omit cursor for the first page, then send each response’s nextCursor back as cursor to fetch the next page — every page is equally fast, no matter how deep. Full request/response data for a row comes from /analytics/logs/detail.

Body
sourcestringrequired

api_traffic or key_activity.

timeRangestring

1h, 3h, 6h, 12h, 24h, 7d, 30d. Default 24h.

pageSizenumber

Results per page (max 200). Default 50.

cursorstring

Opaque cursor from the previous response’s nextCursor. Omit for the first page. Pass it back unchanged — don’t parse or modify it.

statusFilterstring

"all", "success" (200–399), or "error" (400+).

filtersobject

Optional dimension filters.

Request
curl -X POST "https://api.reqkey.com/analytics/logs" \
  -H "Authorization: Bearer reqkey_xxx..." \
  -H "Content-Type: application/json" \
  -d '{
  "source": "api_traffic",
  "timeRange": "24h",
  "pageSize": 50,
  "cursor": "1784050973_req_rLDNyUfIzvKA",
  "statusFilter": "all"
}'
Response
{
  "source": "api_traffic",
  "timeRange": "24h",
  "total": 574122,
  "pageSize": 50,
  "nextCursor": "1784061384_req_tcZZoOkQVMor",
  "rows": [
    {
      "requestId": "req_tcZZoOkQVMor",
      "timestamp": "2026-07-14 20:36:24",
      "tsUnix": 1784061384,
      "method": "GET",
      "endpoint": "/api/users",
      "path": "/api/users?page=1&limit=20",
      "statusCode": 200,
      "latencyMs": 125.5,
      "clientIp": "192.168.1.100",
      "apiKey": "***...abc123",
      "apiId": "api_xyz",
      "apiName": "user-service",
      "consumerId": "consumer_123",
      "consumerName": "Acme Corp",
      "country": "US",
      "region": "us-east-1"
    }
  ]
}
  • nextCursor is null on the last page. total comes back on every page for count displays.
  • Cursors move forward only — “jump to page N” isn’t supported. Keep earlier cursors in memory if you need a back button.
  • Save each row’s timestamp: /analytics/logs/detail needs it for fast lookups.
  • Prefer timeRange strings ("1h", "24h", "30d") over computing exact start/end times per request — identical windows share the server cache.
  • API keys are masked — only the last 6–8 characters are shown.
Errors
400Invalid parameters
POST/analytics/logs/detailBearer

Log detail

Look up one request by its requestId and timestamp, both taken from an /analytics/logs row. The timestamp pins the lookup to the right time slice, which is what makes the query fast — always send it.

Body
requestIdstringrequired

Request ID from a logs list entry.

timestampstringrequired

The row’s timestamp exactly as /analytics/logs returned it (YYYY-MM-DD HH:MM:SS). Unix seconds or milliseconds also work. Pass it through verbatim — don’t reformat it.

sourcestring

Restrict to one table. If omitted, both are searched.

Request
curl -X POST "https://api.reqkey.com/analytics/logs/detail" \
  -H "Authorization: Bearer reqkey_xxx..." \
  -H "Content-Type: application/json" \
  -d '{
  "requestId": "req_abc123xyz",
  "source": "api_traffic",
  "timestamp": "2026-07-14 12:44:58"
}'
Response
{
  "requestId": "req_abc123xyz",
  "keyLog": null,
  "apiLog": {
    "requestId": "req_abc123xyz",
    "timestamp": "2026-07-14 12:44:58",
    "method": "POST",
    "endpoint": "/api/users",
    "statusCode": 201,
    "latencyMs": 150.25,
    "consumerId": "consumer_123",
    "region": "us-east-1",
    "requestBody": "{\"name\":\"John Doe\"}",
    "responseBody": "{\"id\":\"user_123\",\"status\":\"created\"}",
    "requestHeaders": "{\"content-type\":\"application/json\"}",
    "responseHeaders": "{\"content-type\":\"application/json\"}"
  }
}
  • keyLog and apiLog are each null when absent. Bodies are truncated at 2KB.
Errors
404No log found for the given requestId