> ## Documentation Index
> Fetch the complete documentation index at: https://docs.trophy.so/llms.txt
> Use this file to discover all available pages before exploring further.

# How To Build An Energy Feature

> Learn how to use Trophy to add an energy feature to your web or mobile app.

The guide outlines the full process of adding an energy feature to your web or mobile app using Trophy.

For illustration purposes we'll use the example of a study platform that uses energy to meter the rate at which users can view flashcards.

<Tip>
  To see a fully working example of this in practice, check out the [live
  demo](https://examples.trophy.so) or [github
  repo](https://github.com/trophyso/example-study-platform/tree/demo).
</Tip>

<h2 id="pre-requisites">
  Pre-requisites
</h2>

* A [Trophy](https://app.trophy.so/sign-up) account
* About 10 minutes

<h2 id="trophy-setup">
  Trophy Setup
</h2>

In Trophy, [Metrics](/features/metrics) are the building blocks of gamification and model the different interactions users make with your product.

In this guide the interaction we're interested in is `flashcards-viewed`, but you can create any number of metrics that best represents the interactions you want to grant and consume energy from.

In the Trophy dashboard, head to the [metrics page](https://app.trophy.so/metrics) and create a metric.

<Frame>
  <video autoPlay muted loop playsInline className="w-full aspect-video" src="https://mintcdn.com/trophy/2khPIyZFxPyE7xgA/assets/guides/achievements-feature/create_new_metric.mp4?fit=max&auto=format&n=2khPIyZFxPyE7xgA&q=85&s=8e66d7276d9648d449c4556340febf45" data-path="assets/guides/achievements-feature/create_new_metric.mp4" />
</Frame>

Once you've created your metric, head to the [points page](https://app.trophy.so/points) and create a new points system called 'Energy'.

<Frame>
  <video autoPlay muted loop playsInline className="w-full aspect-video" src="https://mintcdn.com/trophy/2khPIyZFxPyE7xgA/assets/guides/xp-feature/create_system.mp4?fit=max&auto=format&n=2khPIyZFxPyE7xgA&q=85&s=95e4d131e3a694719a536227c9f8fc61" data-path="assets/guides/xp-feature/create_system.mp4" />
</Frame>

Once created, you'll be taken to the configure page for the energy system where you can create [points triggers](/features/points#types-of-triggers) for each of the ways you want to grant or consume energy.

<Frame>
  <video autoPlay muted loop playsInline className="w-full aspect-video" src="https://mintcdn.com/trophy/2khPIyZFxPyE7xgA/assets/guides/xp-feature/create_trigger.mp4?fit=max&auto=format&n=2khPIyZFxPyE7xgA&q=85&s=493a23cbed41c5636992827448c366c0" data-path="assets/guides/xp-feature/create_trigger.mp4" />
</Frame>

Use 'time' triggers to grant users with new energy on an hourly or daily basis, and use [other types](/features/points#types-of-triggers) of triggers with negative values to consume energy from the different user interactions you want.

In Trophy you track user interactions by sending [Events](/features/events) from your code to Trophy APIs against a specific metric.

When events are recorded for a specific user, Trophy will automatically check if any of the triggers set up against your energy system should be triggered, and process them accordingly.

Trophy also takes care of automatically granting new energy to users over time in accordance with any 'time' triggers you've set up.

This is what makes building gamified experiences with Trophy so easy, it does all the work for you behind the scenes.

<h2 id="installing-trophy-sdk">
  Installing Trophy SDK
</h2>

To interact with Trophy from your code you'll use the Trophy SDK available in most major [programming languages](/api-reference/client-libraries).

Install the Trophy SDK:

<CodeGroup>
  ```bash Node theme={null}
  npm install @trophyso/node
  ```

  ```bash Ruby theme={null}
  gem install trophy_api_client
  ```

  ```bash Python theme={null}
  pip install trophy
  ```

  ```bash PHP theme={null}
  composer require trophyso/php
  ```

  ```bash Java (Gradle) theme={null}
  implementation 'so.trophy:trophy-java:1.0.0'
  ```

  ```bash Java (Maven) theme={null}
  <dependency>
    <groupId>so.trophy</groupId>
    <artifactId>trophy-java</artifactId>
    <version>1.0.0</version>
  </dependency>
  ```

  ```bash Go theme={null}
  go get github.com/trophy-so/trophy-go
  ```

  ```bash .NET (C#) theme={null}
  // .NET Core CLI
  dotnet add package Trophy

  // Nuget Package Manager
  nuget install Trophy

  // Visual Studio
  Install-Package Trophy
  ```
</CodeGroup>

Next, grab your API key from the Trophy [integration page](https://app.trophy.so/integration) and add this as a **server-side only** environment variable.

```bash theme={null}
TROPHY_API_KEY='*******'
```

<Warning>
  Make sure you **don't** expose your API key in client-side code.
</Warning>

<h2 id="tracking-user-interactions">
  Tracking User Interactions
</h2>

To track an event (user interaction) against your metric, use the [metric change API](/api-reference/endpoints/metrics/send-a-metric-change-event).

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://app.trophy.so/api/metrics/flashcards-flipped/event \
       -H "X-API-KEY: <apiKey>" \
       -H "Content-Type: application/json" \
       -d '{
    "user": {
      "id": "18",
      "email": "user@example.com",
      "tz": "Europe/London"
    },
    "value": 750
  }'
  ```

  ```typescript Node theme={null}
  trophy.metrics.event("flashcards-flipped", {
    user: {
      id: "18",
      email: "user@example.com",
      tz: "Europe/London",
    },
    value: 750,
  });
  ```

  ```python Python theme={null}
  client.metrics.event(
      key="flashcards-flipped",
      user=EventRequestUser(
          id="18",
          email="user@example.com",
          tz="Europe/London",
      ),
      value=750.0,
  )
  ```

  ```php PHP theme={null}
  $user = new EventRequestUser([
      'id' => '18',
      'email' => 'user@example.com'
  ]);

  $request = new MetricsEventRequest([
      'user' => $user,
      'value' => 750
  ]);

  $trophy->metrics->event("flashcards-flipped", $request);
  ```

  ```java Java theme={null}
  MetricsEventRequest request = MetricsEventRequest.builder()
        .user(
          EventRequestUser.builder()
            .id("18")
            .email("user@example.com")
            .build()
        )
        .value(750)
        .build();

  EventResponse response = client.metrics().event("flashcards-flipped", request);
  ```

  ```go Go theme={null}
  response, err := client.Metrics.Event(
      "flashcards-flipped",
      &api.MetricsEventRequest{
          User: &api.EventRequestUser{
              Id: "18",
              Email: "user@example.com",
          },
          Value: 750,
      },
  )
  ```

  ```csharp C# theme={null}
  var user = new EventRequestUser {
     Id = "18",
     Email = "user@example.com"
  };

  var request = new MetricsEventRequest {
     User = user,
     Value = 750
  };

  await trophy.Metrics.EventAsync("flashcards-flipped", request);
  ```

  ```ruby Ruby theme={null}
  result = client.metrics.event(
    :key => 'flashcards-flipped',
    :user => {
      :id => '18',
      :email => 'user@example.com'
    },
    :value => 750
  )
  ```
</CodeGroup>

The response to this API call is the complete set of changes to any features you've built with Trophy, including any changes in energy as a result of the event, and from what triggers energy was consumed.

```json Response [expandable] theme={null}
{
  "metricId": "d01dcbcb-d51e-4c12-b054-dc811dcdc623",
  "eventId": "0040fe51-6bce-4b44-b0ad-bddc4e123534",
  "total": 750,
  ...,
  "points": {
    "energy": {
      "id": "0040fe51-6bce-4b44-b0ad-bddc4e123534",
      "name": "Energy",
      "description": null,
      "badgeUrl": null,
      "total": 9,
      "added": -1,
      "awards": [
        {
          "id": "0040fe51-6bce-4b44-b0ad-bddc4e123534",
          "awarded": -1,
          "date": "2021-01-01T00:00:00Z",
          "total": 9,
          "trigger": {
            "id": "0040fe51-6bce-4b44-b0ad-bddc4e123534",
            "type": "metric",
            "metricName": "Flashcards Flipped",
            "metricThreshold": 1,
            "points": -1
          }
        }
      ]
    }
  },
  ...
}
```

Validate this is working by checking the Trophy [dashboard](https://app.trophy.so).

<h2 id="metering-usage">
  Metering Usage
</h2>

To prevent users from taking actions in your product based on energy, use the [user points API](/api-reference/endpoints/users/get-a-users-points) to fetch their current total energy.

<CodeGroup>
  ```bash cURL theme={null}
  curl --request GET \
    --url https://api.trophy.so/v1/users/{id}/points/{key} \
    --header 'X-API-KEY: <api-key>'
  ```

  ```typescript Node theme={null}
  trophy.users.points("user-id", "points-system-key");
  ```

  ```python Python theme={null}
  client.users.points(
      id="user-id",
      key="points-system-key",
  )
  ```

  ```php PHP theme={null}
  $trophy->users->points("user-id", "points-system-key");
  ```

  ```java Java theme={null}
  client.users().points("user-id","points-system-key");
  ```

  ```go Go theme={null}
  response, err := client.Users.Points(
      "user-id",
      "points-system-key"
  )
  ```

  ```csharp C# theme={null}
  trophy.Users.PointsAsync("user-id", "points-system-key");
  ```

  ```ruby Ruby theme={null}
  result = client.users.points(
    :id => 'user-id',
    :key => "points-system-key"
  )
  ```
</CodeGroup>

This returns data on the total energy the user has, allowing you to use the `total` property to control what actions a user can perform:

```json Response [expandable] theme={null}
{
  "id": "0040fe51-6bce-4b44-b0ad-bddc4e123534",
  "name": "Energy",
  "description": null,
  "badgeUrl": null,
  "total": 10,
  "awards": [
    {
      "id": "0040fe51-6bce-4b44-b0ad-bddc4e123534",
      "awarded": 1,
      "date": "2021-01-01T00:00:00Z",
      "total": 10,
      "trigger": {
        "id": "0040fe51-6bce-4b44-b0ad-bddc4e123534",
        "type": "time",
        "points": 1,
        "timeUnit": "day",
        "timeInterval": 1
      }
    },
    {
      "id": "0040fe51-6bce-4b44-b0ad-bddc4e123534",
      "awarded": -1,
      "date": "2021-01-01T00:00:00Z",
      "total": 9,
      "trigger": {
        "id": "0040fe51-6bce-4b44-b0ad-bddc4e123534",
        "type": "metric",
        "points": -1,
        "metricName": "Flashcards Flipped",
        "metricThreshold": 1
      }
    }
  ]
}
```

Here's an example where a user is only allowed to view a flashcard if `total > 0`

```ts theme={null}
const energy = await trophy.users.points("user-id", "energy");

if (!energy) {
  return;
}

if (energy.total > 0) {
  showNextFlashcard();
}
```

You can then modify your trigger setup in Trophy and control the rate at which users can interact with your product right from the Trophy dashboard without needing to make any code changes.

<h2 id="displaying-energy">
  Displaying Energy
</h2>

To fetch a users energy use the [user points API](/api-reference/endpoints/users/get-a-users-points).

<CodeGroup>
  ```bash cURL theme={null}
  curl --request GET \
    --url https://api.trophy.so/v1/users/{id}/points/{key} \
    --header 'X-API-KEY: <api-key>'
  ```

  ```typescript Node theme={null}
  trophy.users.points("user-id", "points-system-key");
  ```

  ```python Python theme={null}
  client.users.points(
      id="user-id",
      key="points-system-key",
  )
  ```

  ```php PHP theme={null}
  $trophy->users->points("user-id", "points-system-key");
  ```

  ```java Java theme={null}
  client.users().points("user-id","points-system-key");
  ```

  ```go Go theme={null}
  response, err := client.Users.Points(
      "user-id",
      "points-system-key"
  )
  ```

  ```csharp C# theme={null}
  trophy.Users.PointsAsync("user-id", "points-system-key");
  ```

  ```ruby Ruby theme={null}
  result = client.users.points(
    :id => 'user-id',
    :key => "points-system-key"
  )
  ```
</CodeGroup>

This API returns data on the user's total energy but can be configured to also return between 1 and 100 of the user's most recent energy changes by using the `awards` query parameter.

```json Response [expandable] theme={null}
{
  "id": "0040fe51-6bce-4b44-b0ad-bddc4e123534",
  "name": "Energy",
  "description": null,
  "badgeUrl": null,
  "total": 10,
  "awards": [
    {
      "id": "0040fe51-6bce-4b44-b0ad-bddc4e123534",
      "awarded": 1,
      "date": "2021-01-01T00:00:00Z",
      "total": 10,
      "trigger": {
        "id": "0040fe51-6bce-4b44-b0ad-bddc4e123534",
        "type": "time",
        "points": 1,
        "timeUnit": "day",
        "timeInterval": 1
      }
    },
    {
      "id": "0040fe51-6bce-4b44-b0ad-bddc4e123534",
      "awarded": -1,
      "date": "2021-01-01T00:00:00Z",
      "total": 9,
      "trigger": {
        "id": "0040fe51-6bce-4b44-b0ad-bddc4e123534",
        "type": "metric",
        "points": -1,
        "metricName": "Flashcards Flipped",
        "metricThreshold": 1
      }
    }
  ]
}
```

The [user points summary API](/api-reference/endpoints/users/get-a-users-points-summary) can also be used to drive chart-based UI, like showing users their energy usage over time.

<CodeGroup>
  ```bash cURL theme={null}
  curl --request GET \
    --url https://api.trophy.so/v1/users/{id}/points/{key}/event-summary \
    --header 'X-API-KEY: <api-key>'
  ```

  ```typescript Node theme={null}
  trophy.users.pointsEventSummary("user-id", "points-system-key", {
    aggregation: "daily",
    start_date: "2025-01-01",
    end_date: "2025-01-07"
  });
  ```

  ```python Python theme={null}
  client.users.points_event_summary(
    id="user-id",
    key="points-system-key",
    aggregation="daily",
    start_date="2025-01-01",
    end_date="2025-01-07"
  )
  ```

  ```php PHP theme={null}
  $trophy->users->pointsEventSummary("user-id", "points-system-key");
  ```

  ```java Java theme={null}
  client.users().pointsEventSummary("user-id","points-system-key");
  ```

  ```go Go theme={null}
  response, err := client.Users.PointsEventSummary(
      "user-id",
      "points-system-key"
  )
  ```

  ```csharp C# theme={null}
  trophy.Users.PointsEventSummaryAsync("user-id", "points-system-key");
  ```

  ```ruby Ruby theme={null}
  result = client.users.pointsEventSummary(
    :id => 'user-id',
    :key => "points-system-key"
  )
  ```
</CodeGroup>

Here's an example of a UI that shows users their current energy, a chart showing their usage over time, and a list of their most recent changes in energy.

<Frame>
  <img height="200" width="100%" noZoom src="https://mintcdn.com/trophy/2khPIyZFxPyE7xgA/assets/guides/energy-feature/ui.png?fit=max&auto=format&n=2khPIyZFxPyE7xgA&q=85&s=1f99a7d8cb5ab3e8976bed03f175d027" data-path="assets/guides/energy-feature/ui.png" />
</Frame>

<h2 id="analytics">
  Analytics
</h2>

In Trophy your [energy system page](https://app.trophy.so/points), includes analytics charts that shows data on total energy awarded/consumed and a breakdown of exactly what triggers cause the most frequent changes in energy.

<Frame>
  <img height="200" width="100%" noZoom src="https://mintcdn.com/trophy/2khPIyZFxPyE7xgA/assets/guides/energy-feature/analytics.png?fit=max&auto=format&n=2khPIyZFxPyE7xgA&q=85&s=9b91a39df9fe94f23d0eecd42e2013b0" data-path="assets/guides/energy-feature/analytics.png" />
</Frame>

<h2 id="get-support">
  Get Support
</h2>

Want to get in touch with the Trophy team? Reach out to us via [email](mailto:support@trophy.so). We're here to help!
