Phoenix Gamification
Streaks

Querying Results

Use the Query Gateway to retrieve user streak progress for profile screens, achievement displays, or analytics dashboards. This guide covers REST endpoints, authentication, and response formats.

1. Authentication

Query endpoints accept the same mechanisms as the Admin Gateway:

  • X-API-Key: <API_KEY> or Authorization: Bearer <API_KEY> for server-to-server integrations.
  • Tenant HMAC headers (X-Tenant-Id, X-Timestamp, X-Signature) for partner integrations.

Most implementations use API keys for backend calls and relay relevant data to clients through your own APIs.

2. Endpoint Overview

Use CaseMethod & Path
List streak definitionsGET /v1/streaks/{tenant_id}/definitions
Get all streaks for a userGET /v1/streaks/{tenant_id}/users/{user_id}
Get specific streak for userGET /v1/streaks/{tenant_id}/users/{user_id}/{definition_id}

3. List Streak Definitions

Retrieve all active streak definitions for a tenant. Useful for displaying available streaks to users.

GET /v1/streaks/{tenant_id}/definitions

Response

{
  "definitions": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "tenant_id": "tenant-prod-001",
      "name": "Daily Login Streak",
      "description": "Track consecutive days users log in",
      "config": {
        "event_types": ["user.login"],
        "window": {
          "type": "calendar",
          "period": "daily",
          "timezone": "UTC",
          "reset_time": "00:00"
        },
        "condition": {
          "type": "count",
          "min": 1
        },
        "milestones": [
          { "threshold": 7, "reward_item_id": null, "repeatable": false },
          { "threshold": 30, "reward_item_id": null, "repeatable": false }
        ]
      },
      "status": "active"
    }
  ]
}

Only active definitions are returned. Use this to populate streak selection UIs or onboarding flows.

4. Get All Streaks for a User

Retrieve all streak progress for a specific user. Ideal for profile pages showing all active streaks.

GET /v1/streaks/{tenant_id}/users/{user_id}

Response

{
    "streaks": [
        {
            "id": "47c81b78-bcad-4ccd-a9a6-98b2f6a2cb9d",
            "definition_id": "a20dfefe-1bca-425c-9534-6e784bb03677",
            "definition_name": "Test Hourly Streak 1838",
            "tenant_id": "streak_test",
            "user_id": "test_user_1838",
            "current_count": 1,
            "current_window_key": "2025-12-23",
            "current_window_progress": {
                "count": 9,
                "distinct": [],
                "sum": 0.0
            },
            "current_window_satisfied": true,
            "last_activity_at": "2025-12-23T14:59:10.276Z",
            "seconds_until_window_close": 40845,
            "next_milestone": 3,
            "earned_milestones": [
                1
            ],
            "window": {
                "period": "daily",
                "reset_time": "00:00",
                "timezone": "UTC",
                "type": "calendar"
            },
            "condition": {
                "min": 4,
                "type": "count"
            },
            "milestones": [
                {
                    "repeatable": false,
                    "reward_item_id": null,
                    "threshold": 1
                },
                {
                    "repeatable": false,
                    "reward_item_id": null,
                    "threshold": 3
                },
                {
                    "repeatable": false,
                    "reward_item_id": null,
                    "threshold": 5
                }
            ]
        }
    ]
}

Response Fields

FieldDescription
current_countConsecutive windows where condition was satisfied
current_window_keyIdentifier for the current time window (e.g., 2025-01-15)
current_window_progressProgress toward satisfying the current window condition
current_window_satisfiedWhether the current window condition is already met
last_activity_atTimestamp of the user's last qualifying event
milestones.thresholdMilestone thresholds configured for this streak
earned_milestonesMilestones the user has already unlocked
milestonnext_milestonesNext milestone threshold to reach (null if all earned)

5. Get Specific Streak for a User

Retrieve detailed progress for a single streak. Use this for dedicated streak detail screens.

GET /v1/streaks/{tenant_id}/users/{user_id}/definitions/{definition_id}

Response

{
    "id": "47c81b78-bcad-4ccd-a9a6-98b2f6a2cb9d",
    "definition_id": "a20dfefe-1bca-425c-9534-6e784bb03677",
    "definition_name": "Test Hourly Streak 1838",
    "tenant_id": "streak_test",
    "user_id": "test_user_1838",
    "current_count": 1,
    "current_window_key": "2025-12-23",
    "current_window_progress": {
        "count": 9,
        "distinct": [],
        "sum": 0.0
    },
    "current_window_satisfied": true,
    "last_activity_at": "2025-12-23T14:59:10.276Z",
    "seconds_until_window_close": 40765,
    "next_milestone": 3,
    "earned_milestones": [
        1
    ],
    "window": {
        "period": "daily",
        "reset_time": "00:00",
        "timezone": "UTC",
        "type": "calendar"
    },
    "condition": {
        "min": 4,
        "type": "count"
    },
    "milestones": [
        {
            "repeatable": false,
            "reward_item_id": null,
            "threshold": 1
        },
        {
            "repeatable": false,
            "reward_item_id": null,
            "threshold": 3
        },
        {
            "repeatable": false,
            "reward_item_id": null,
            "threshold": 5
        }
    ]
}

Returns 404 if the user has no record for the specified streak definition.

6. Understanding Window Progress

The current_window_progress object shows how far along the user is in the current window:

For Count Conditions

{
  "count": 2,
  "sum": 0,
  "distinct": []
}

The user has triggered 2 qualifying events this window. If condition.min is 3, they need one more.

For Sum Conditions

{
  "count": 5,
  "sum": 350.5,
  "distinct": []
}

The user has accumulated 350.5 points from 5 events. If condition.min is 500, they need 149.5 more.

For Distinct Conditions

{
  "count": 3,
  "sum": 0,
  "distinct": ["arcade", "ranked", "casual"]
}

The user has played 3 distinct game modes. If condition.min is 5, they need 2 more unique modes.

7. Displaying Streak Information

Progress Bar Example

Calculate completion percentage for UI progress bars:

function getProgressPercentage(streak) {
  const condition = streak.definition_config.condition;
  const progress = streak.current_window_progress;

  switch (condition.type) {
    case "count":
      return Math.min(100, (progress.count / condition.min) * 100);
    case "sum":
      return Math.min(100, (progress.sum / condition.min) * 100);
    case "distinct":
      return Math.min(100, (progress.distinct.length / condition.min) * 100);
  }
}

Time Remaining

For calendar windows, calculate time until reset based on window.timezone and window.reset_time. Display urgency when approaching the deadline, especially if current_window_satisfied is false.

Milestone Visualization

Show earned milestones as completed, the next milestone as the current goal, and future milestones as locked:

✅ 7 days   ⭐ 30 days   🔒 100 days
   Earned      Current      Locked

8. Error Reference

StatusCodeMeaning
400INVALID_INPUTMalformed parameters (e.g., invalid UUID format).
401UNAUTHORIZEDMissing or incorrect API key/HMAC headers.
403FORBIDDENAPI key lacks access to the tenant.
404NOT_FOUNDStreak definition not found or user has no streak record.
429RATE_LIMITEDRequest volume exceeded plan limits.
500INTERNAL_ERRORUnexpected server issue; retry or contact support.

Standard error envelope:

{
  "error": {
    "code": "NOT_FOUND",
    "message": "Streak not found for user 'user-12345' and definition '550e8400-...'",
    "status": 404
  }
}

9. Integration Tips

  • Cache streak definitions locally; they change infrequently.
  • Poll user streaks periodically (every 30–60 seconds) or after sending qualifying events.
  • Display current_window_satisfied prominently so users know when they're "safe" for the day.
  • Show countdown timers for window resets to create engagement urgency.
  • Celebrate milestone achievements with animations or special notifications.
  • Handle 404 gracefully—users may not have started a streak yet.

10. Real-Time Updates

For live streak updates without polling, subscribe to streak events via your event infrastructure:

Event TypePayload Includes
streak.incrementeduser_id, definition_id, new_count
streak.brokenuser_id, definition_id, final_count
streak.milestone_reacheduser_id, definition_id, threshold, reward_id
streak.at_riskuser_id, definition_id, current_count, window_ends_at

Use these events to push real-time notifications or update UI states instantly without requiring user-initiated refreshes.

With querying in place, your integration now covers streak creation, management, and retrieval. You're ready to build engaging streak experiences for your users.