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_IDADMIN_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):
| Service | Example Base URL | Purpose |
|---|---|---|
| Ingestion API | https://ingestion-gateway.staging.phoenix-gamification.io | Accepts gameplay/engagement events |
| Admin API | https://admin-gateway.staging.phoenix-gamification.io | Manages leaderboards and reward rules |
| Query API | https://query-gateway.staging.phoenix-gamification.io | Serves leaderboard data to clients |
| WebSocket (live) | wss://query-gateway.staging.phoenix-gamification.io/ws | Streams 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/wsConsumer 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
| Surface | Required Headers / Params | Canonical 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.
JWT Authentication (Recommended for Frontend Apps)
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 JWTTenant 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
- Create a leaderboard (or confirm one exists) via Admin API.
- Publish an event to the ingestion endpoint using
curlor your backend service. - 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
| Symptom | Likely Cause | Fix |
|---|---|---|
401 Unauthorized | Missing/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 Forbidden | Tenant attempting to access another tenant’s data | Double-check X-Tenant-Id and ensure the resource (leaderboard, reward config, websocket path) belongs to your tenant. |
400 Bad Request on ingestion | JSON schema mismatch | Validate required fields (tenant_id, leaderboard_id, user_id, score_delta) and ensure numbers are encoded as integers/floats. |
| Event accepted but no leaderboard update | Leaderboard not active or wrong timeframe window | Confirm 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.