Gamers Lab Docs

4.2 Game Auth Keys (X-Game-Key)

Section 4 — API & Game Key Management

4.2 Game Auth Keys (X-Game-Key)

Game Auth Keys identify a game build or game server that is allowed to send data into Gamers Lab. They are passed in the X-Game-Key request header.

They are used by:

  • game servers
  • game clients
  • backend ingestion pipelines for games

They are never used by dashboards or analytics.

What they can do:

  • Authenticate a game to Gamers Lab
  • Create login events
  • Create match sessions
  • Add players to matches
  • Submit match-scoped event records
  • Submit player-scoped event records
  • Submit match results

Trust level: High. If a Game Auth Key is compromised, attackers can inject fake matches and poison analytics. These keys must be handled like secrets.

Security characteristics:

  • Stored as key_hash
  • Scoped implicitly by purpose (write-only)
  • Bound to tenant_id and environment (development, production)
  • Rate limited (Redis Lua-based atomic minute/hour counters)
  • Subject to quota enforcement (approximate hard-stop on the write path)
  • Carries billing context per request (billed workspace, quota bucket, billable units)
  • Optional origin restrictions (web clients)

Write key rate limits (per key):

  • Free plan default: 10,000 requests/minute, 46,000 requests/hour.
  • Per-tenant overrides available; overrides are clamped to a minimum of 1.
  • Plan changes propagate to existing keys.

Rate limit behavior:

  • Write rate limiting is fail-open — if Redis is unavailable, requests are allowed.
  • Exceeding limits returns HTTP 429 with Retry-After and X-RateLimit-Reset headers.

Key count limits:

  • Default max write keys (game auth keys): 3 per tenant (plan-driven).

Key format: Development keys use the gk_dev_ prefix. Production keys use the gk_live_ prefix.

Key lifecycle: create, list, get, get limits, update, rotate, revoke, and delete. Operations require a SaaS JWT with owner or admin role on the tenant.

OperationEffect
CreateGenerates a new key; plaintext returned once; hash stored
ListReturns all game auth keys for the tenant; plaintext never included
GetReturns a single game auth key by ID; prefix and metadata only
Get limitsReturns persisted per-key minute/hour limits plus warning and critical thresholds
UpdateUpdates mutable fields (name, description, environment, allowedOrigins, isActive)
RotateGenerates a new secret in-place on the same key ID; old secret immediately invalidated; new plaintext returned once
RevokeSoft-deactivates the key and records revoked metadata. Re-enabling through update clears revoked metadata.
DeleteHard-deletes the key row from the database

4.2.1 Game Key Analytics

Every request that passes through GameKeyUsageTrackingMiddleware is recorded post-response to bus_game_key_usage. The middleware identifies the game key by reading GameKeyTenantId and GameKeyId from HttpContext.Items. If either is absent, the request is not recorded.

Unlike tenant API key tracking, game key tracking has no SkipUsageTracking opt-out — every authenticated game key request is always recorded.

Fields recorded per request:

FieldDescription
endpointRoute template
pathActual request path
methodHTTP method
request_kindread (GET/HEAD/OPTIONS) or write (all others)
status_codeHTTP response status code
response_time_msElapsed milliseconds from request start to response completion
request_bytesContent-Length of the request body (if present)
response_bytesContent-Length of the response body (if present)
ip_addressClient IP address
user_agentUser-Agent header value
is_throttledtrue if the request was rate-limited (429)
quota_bucketWhich quota bucket the request was charged against
billing_outcomeHow the request was classified for billing
billable_unitsNumber of units charged (0 for non-accepted outcomes)
billed_workspace_idCompany workspace the usage is attributed to
occurred_atUTC timestamp of the request

Hourly rollup: Game key usage is rolled up into bus_game_key_usage_hourly by a background worker. Each hourly row aggregates: hour_start, request_count, throttled_count, request_bytes. The hourly table backs the hourly analytics query. Daily queries read from the raw table and bucket by day in the service layer.

Billing classification: Game key requests use the same UsageBillingClassifier as tenant API key requests. Bucket is resolved by request_kind: writes use tenant_write_requests, reads use tenant_read_requests. Billing outcomes are identical: only accepted requests consume billable units.

Analytics queries: All endpoints require a SaaS JWT with owner or admin role on the tenant. Daily, hourly, and series endpoints accept an optional keyId parameter to filter to a single game auth key. The ingest-bytes endpoint is tenant-wide and does not accept keyId.

EndpointGranularityDefault rangeKey filter
/analytics/dailyPer dayLast 90 daysOptional keyId
/analytics/hourlyPer hourLast 24 hoursOptional keyId
/analytics/seriesPer day or hour (bucket=day|hour)Last 90 days (bucket=day by default)Optional keyId
/analytics/ingest-bytesAggregate over rangeLast 90 daysNot supported

Daily usage response — one bucket per day:

FieldDescription
dateUTC day
readCountGET/HEAD/OPTIONS request count
writeCountPOST/PUT/PATCH/DELETE request count
readBytesTotal inbound bytes for reads
writeBytesTotal inbound bytes for writes

Hourly usage response — one bucket per hour (contiguous range, zeros included for inactive hours):

FieldDescription
hourStartUTC start of the hour
requestCountTotal requests in that hour
throttledCountNumber of rate-limited requests
requestBytesTotal inbound bytes

Series usage response — one bucket per day or hour:

FieldDescription
bucketStartUTC start of the bucket
readCountGET/HEAD/OPTIONS request count
writeCountPOST/PUT/PATCH/DELETE request count
throttledCountNumber of rate-limited requests
readBytesTotal inbound bytes for reads
writeBytesTotal inbound bytes for writes
estimatedWriteBytesWrite bytes with missing sizes imputed
totalCountTotal request count
totalBytesTotal inbound bytes
estimatedTotalBytesTotal bytes with missing write sizes imputed

Ingest bytes estimate — tenant-wide only, no keyId filter:

FieldDescription
estimatedBytesTotal estimated inbound bytes (actual + imputed)
requestCountTotal number of requests in the range
imputedRequestCountNumber of requests whose byte size was imputed (no Content-Length)

Requests with a null request_bytes are imputed using the median of observed byte sizes for that tenant and period.

Date/time parameters (from / to, both optional):

  • /daily truncates to date boundaries (time component is ignored).
  • /hourly, /series, and /ingest-bytes use full timestamps.
  • /series defaults to bucket=day and a 90-day range. Hour series supports at most 24 buckets, so callers using bucket=hour must provide a range within that limit.
  • to must be on or after from — returns 400 otherwise.

Relationship to quota and rate limits: Game key hourly analytics read from rolled-up summary tables. Daily, series, and ingest-byte analytics read or aggregate from recorded usage rows. They reflect the same request stream that drives quota evaluation and alert thresholds, but they are not real-time; rollup lag applies to hourly rollups (up to 10 minutes).

Differences from Tenant API Key Analytics:

Game Key AnalyticsTenant API Key Analytics
Auth headerX-Game-KeyX-API-Key
Raw tablebus_game_key_usagebus_api_key_usage
Hourly rollup tablebus_game_key_usage_hourly
Hourly query sourceRollup tableRaw table (windowed)
Per-key detail viewNoYes — endpoint breakdown, IP list, status distribution
Tenant-wide aggregateNoYes
Ingest bytes estimateYes — with imputationNo
Tracking opt-outNot availableSkipApiKeyUsageTracking flag

Limitations:

  • No per-key detail view. Game key analytics only expose time-series (daily/hourly/series) and the ingest bytes estimate.
  • Hourly rollup lag. Very recent requests may not appear in hourly results until the next rollup cycle completes.
  • Ingest bytes imputation is an estimate. imputedRequestCount in the response shows how many requests were estimated.
  • Post-response only. Usage records are best-effort.

Code references:

  • Middleware: GamersLabRestAPI/Saas/ApiKeys/Middleware/GameKeyUsageTrackingMiddleware.cs
  • Usage model: GamersLabRestAPI/PlayerAuth/Models/GameKeyUsage.cs
  • Hourly rollup model: GamersLabRestAPI/PlayerAuth/Models/GameKeyUsageHourly.cs
  • Usage service: GamersLabRestAPI/PlayerAuth/Services/GameKeyUsageService.cs
  • Rollup worker: GamersLabRestAPI/PlayerAuth/Services/GameKeyUsageRollupWorkerService.cs
  • Analytics controller: GamersLabRestAPI/PlayerAuth/Controllers/GameKeyAnalyticsController.cs
  • Usage repository: GamersLabRestAPI/PlayerAuth/Repositories/NpgsqlGameKeyUsageRepository.cs

On this page