Phoenix Gamification

Getting Started

This section walks you through the minimum steps required to connect to Phoenix's public APIs, authenticate requests, and verify your environment by sending a smoke-test event end-to-end. All instructions apply to both staging and production clusters—replace the base URLs and credentials accordingly.

Getting Started

This section walks you through the minimum steps required to connect to Phoenix's public APIs, authenticate requests, and verify your environment by sending a smoke-test event end-to-end. All instructions apply to both staging and production clusters—replace the base URLs and credentials accordingly.

1. Prerequisites

  • Tenant credentials issued by Phoenix Ops:
    • TENANT_ID
    • JWT / Bearer tokens for Ingestion and Query gateways (tenant and user resolved from the token)
    • ADMIN_API_KEY (or Admin JWT) for the Admin Gateway only
  • Base URLs for each service (example values shown below):
ServiceExample Base URLPurpose
Ingestion APIhttps://ingestion.api.yourgame.ggAccepts gameplay/engagement events
Admin APIhttps://admin.api.yourgame.ggManages leaderboards and reward rules
Query APIhttps://query.api.yourgame.ggServes leaderboard data to clients
WebSocket (live)wss://query.api.yourgame.gg/v1/leaderboards/{leaderboard_id}/wsStreams real-time leaderboard updates (auth via Authorization: Bearer <JWT>)

Tip: keep each credential in a secure secret store (Vault, AWS Secrets Manager, GCP Secret Manager) and inject them at runtime. Do not commit keys to source control.

2. Environment Variables

Create an .env file (or equivalent secret injection) that includes at least:

TENANT_ID=tenant-prod-001
ADMIN_API_KEY=your-admin-api-key

INGESTION_BASE_URL=https://ingestion.api.yourgame.gg
ADMIN_BASE_URL=https://admin.api.yourgame.gg
QUERY_BASE_URL=https://query.api.yourgame.gg
WEBSOCKET_URL=wss://query.api.yourgame.gg/v1/leaderboards/{leaderboard_id}/ws

Consumer services (mobile/web) typically need the Query Gateway URL and a JWT (Bearer token); ingestion runs from your servers or secure game backend with a JWT that encodes tenant (and optionally user) context.

3. Authentication Summary

Phoenix exposes three complementary auth options:

  • Ingestion Gateway and Query Gateway use JWT only. Send Authorization: Bearer <JWT>; tenant (and for Query, user) is resolved from the token. Paths do not include tenant_id.
  • Admin Gateway uses API keys or Admin JWT for server-to-server configuration; Admin routes include tenant_id in the path where applicable.
SurfaceRequired AuthNotes
Ingestion APIAuthorization: Bearer <JWT>JWT must encode tenant (e.g. Zitadel org or platform gamer token).
Query API (REST)Authorization: Bearer <JWT>Tenant and user from JWT. Paths do not include tenant_id.
Query Gateway WebSocketAuthorization: Bearer <JWT> on the HTTP upgrade requestPath: /v1/leaderboards/{leaderboard_id}/ws (no tenant in path).
Admin APIX-API-Key: <ADMIN_API_KEY> or Authorization: Bearer <ADMIN_API_KEY>For tenant/leaderboard/rewards configuration.

Detailed examples appear in later sections.

If your architecture uses a proxy server for user authentication, JWT is the cleanest approach:

User → Proxy (login) → Proxy issues JWT → User calls Phoenix directly with JWT

Tenant JWT payload:

{
  "sub": "user_123",
  "sub_type": "tenant",
  "sub_id": "your-tenant-id",
  "iat": 1704067200,
  "exp": 1704070800
}

Sign with: Tenant HMAC secret

Admin JWT payload:

{
  "sub": "admin_user",
  "sub_type": "admin", 
  "sub_id": "api-key-uuid",
  "iat": 1704067200,
  "exp": 1704070800
}

Sign with: API key value (the plaintext key like pk_abc123...)

See the Redeeming Coupons guide for complete JWT creation examples in JavaScript and Python.

4. Smoke Test Checklist

  1. Create a leaderboard (or confirm one exists) via Admin API.
  2. Publish an event to the ingestion endpoint using curl or your backend service.
  3. Verify live data by calling the query API or subscribing to the WebSocket stream.

If all three steps succeed, your environment is ready for deeper integration.

5. Example Requests

5.1 Admin API Health Check

curl -X GET \
  "$ADMIN_BASE_URL/health" \
  -H "X-API-Key: $ADMIN_API_KEY"

A 200 OK response confirms the API key is active. To exercise the tenant HMAC path instead, include the X-Tenant-Id, X-Timestamp, and X-Signature headers using the canonical string GET\n/health\n<TIMESTAMP>\n.

5.2 Ingestion Test Event

Ingestion uses JWT. Obtain a Bearer token that encodes your tenant (e.g. from your IdP or platform gamer-token endpoint), then POST the event:

# Use your JWT (e.g. from $INGESTION_JWT or your auth service)
BODY='{
  "tenant_id": "placeholder",
  "event_id": "evt_smoke_'"$(date +%s)"'",
  "type": "game.completed",
  "actor": { "user_id": "user-123" },
  "occurred_at": "'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'",
  "attrs": { "score_delta": 50, "source": "smoke-test" }
}'

curl -X POST "$INGESTION_BASE_URL/v1/events" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $INGESTION_JWT" \
  -d "$BODY"

A 202 Accepted (or 200 with success body) indicates the event entered the pipeline. The gateway sets tenant_id from your JWT; you can send a placeholder in the body. Event schema details are in Events and Integration.

6. Common Issues

SymptomLikely CauseFix
401 UnauthorizedMissing or invalid Authorization: Bearer <JWT> (Ingestion/Query) or API key (Admin)Ensure the JWT is valid, not expired, and encodes the correct tenant (and for Query, user).
403 ForbiddenTenant or user cannot access the resourceEnsure the JWT's tenant/resource matches the leaderboard or achievement you're querying.
400 Bad Request on ingestionJSON schema mismatchValidate required fields: event_id, type, actor.user_id, occurred_at, attrs. See Events and Integration.
Event accepted but no leaderboard updateLeaderboard not active or wrong timeframe windowConfirm the leaderboard status is active, the timeframe is currently open, and the event timestamp falls inside the active window.

Once you clear these hurdles, proceed to Events and Integration for a deep dive into ingestion payloads and retry patterns.

On this page