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.

1. Prerequisites

  • Tenant credentials issued by Phoenix Ops:
    • TENANT_ID
    • ADMIN_API_KEY (signing key for admin + query gateways)
    • INGESTION_HMAC_SECRET (signing key for ingestion events)
  • Base URLs for each service (example values shown below):
ServiceExample Base URLPurpose
Ingestion APIhttps://ingestion-gateway.staging.phoenix-gamification.ioAccepts gameplay/engagement events
Admin APIhttps://admin-gateway.staging.phoenix-gamification.ioManages leaderboards and reward rules
Query APIhttps://query-gateway.staging.phoenix-gamification.ioServes leaderboard data to clients
WebSocket (live)wss://query-gateway.staging.phoenix-gamification.io/wsStreams real-time leaderboard updates

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_HMAC_SECRET= your-hmac-secret

INGESTION_BASE_URL= https://ingestion-gateway.staging.phoenix-gamification.io
ADMIN_BASE_URL= https://admin-gateway.staging.phoenix-gamification.io
QUERY_BASE_URL= https://query-gateway.staging.phoenix-gamification.io
WEBSOCKET_URL= wss://query-gateway.staging.phoenix-gamification.io/ws

Consumer services (mobile/web) typically need only the query gateway URL plus the API key; ingestion workflows run from your servers or secure game backend.

3. Authentication Summary

Phoenix exposes three complementary auth options:

  • JWT (JSON Web Tokens) - Recommended for frontend-to-backend communication via a proxy
  • API Keys for privileged server-to-server calls (admin & query gateways)
  • Tenant HMAC for multi-tenant or ingestion traffic
SurfaceRequired Headers / ParamsCanonical String & Signature
Admin & Query REST (API key)X-API-Key: <ADMIN_API_KEY> or Authorization: Bearer <ADMIN_API_KEY>No additional signing—possession of the key is sufficient.
Admin & Query REST (Tenant HMAC)X-Tenant-Id, X-Timestamp (Unix seconds), X-Signature (hmac-sha256=<hex digest>). Timestamp must be within ±300 s of server time.METHOD\nPATH\nTIMESTAMP\nBODY (PATH excludes domain & query; BODY is exact JSON or empty string for GET). Sign with the tenant’s shared secret.
Ingestion API (Tenant HMAC)Same headers as above (X-Tenant-Id, X-Timestamp, X-Signature).Same canonical format: METHOD\nPATH\nTIMESTAMP\nBODY. Typical path is /v1/events or /v1/events/bulk.
Query Gateway WebSocket (/ws endpoint)Path parameters include the tenant and leaderboard IDs. Query params: timestamp=<unix> and signature=hmac-sha256%3D<hex>.WebSocket canonical string omits the body: WS\n/v1/leaderboards/{tenant_id}/{leaderboard_id}/ws\nTIMESTAMP. Sign with the same tenant secret and send via the signature query parameter.

Detailed examples appear in later sections; for now ensure you can generate SHA256 HMACs in your preferred language, including the exact canonical string shown above.

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

TIMESTAMP=$(date -u +%s)
BODY='{
  "tenant_id": "'"$TENANT_ID"'",
  "leaderboard_id": "xp-weekly",
  "user_id": "user-123",
  "score_delta": 50,
  "metadata": {"source": "smoke-test"}
}'

CANONICAL="POST
/v1/events
$TIMESTAMP
$BODY"
SIGNATURE_HEX=$(printf "%s" "$CANONICAL" | openssl dgst -binary -sha256 -hmac "$INGESTION_HMAC_SECRET" | xxd -p -c 256)
SIGNATURE="hmac-sha256=$SIGNATURE_HEX"

curl -X POST "$INGESTION_BASE_URL/v1/events" \
  -H "Content-Type: application/json" \
  -H "X-Tenant-Id: $TENANT_ID" \
  -H "X-Timestamp: $TIMESTAMP" \
  -H "X-Signature: $SIGNATURE" \
  -d "$BODY"

A 202 Accepted response indicates the event entered the pipeline. Within a few seconds the associated leaderboard should reflect the new score. Reuse the same signing pattern for PUT/PATCH requests; GET calls simply use an empty string for the body segment of the canonical string.

6. Common Issues

SymptomLikely CauseFix
401 UnauthorizedMissing/incorrect headers (X-Tenant-Id, X-Timestamp, X-Signature, X-API-Key)Confirm spelling/casing, recalculate the HMAC (hmac-sha256=<hex>), and ensure the timestamp is within ±5 minutes of server time.
403 ForbiddenTenant attempting to access another tenant’s dataDouble-check X-Tenant-Id and ensure the resource (leaderboard, reward config, websocket path) belongs to your tenant.
400 Bad Request on ingestionJSON schema mismatchValidate required fields (tenant_id, leaderboard_id, user_id, score_delta) and ensure numbers are encoded as integers/floats.
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.