diff --git a/.gitignore b/.gitignore
index b512c09..28f1ba7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
-node_modules
\ No newline at end of file
+node_modules
+.DS_Store
\ No newline at end of file
diff --git a/admin-api/endpoints/points/archive-a-boost.mdx b/admin-api/endpoints/points/archive-a-boost.mdx
new file mode 100644
index 0000000..e80a6fd
--- /dev/null
+++ b/admin-api/endpoints/points/archive-a-boost.mdx
@@ -0,0 +1,9 @@
+---
+openapi: delete /points/boosts/{id}
+---
+
+import { RateLimitBadge } from "/snippets/rate-limit-badge.jsx";
+
+**Rate Limits**
+
+
diff --git a/admin-api/endpoints/points/archive-boosts-batch.mdx b/admin-api/endpoints/points/archive-boosts-batch.mdx
new file mode 100644
index 0000000..1a54ad0
--- /dev/null
+++ b/admin-api/endpoints/points/archive-boosts-batch.mdx
@@ -0,0 +1,9 @@
+---
+openapi: delete /points/boosts
+---
+
+import { RateLimitBadge } from "/snippets/rate-limit-badge.jsx";
+
+**Rate Limits**
+
+
diff --git a/admin-api/endpoints/points/create-boosts.mdx b/admin-api/endpoints/points/create-boosts.mdx
new file mode 100644
index 0000000..34f2532
--- /dev/null
+++ b/admin-api/endpoints/points/create-boosts.mdx
@@ -0,0 +1,9 @@
+---
+openapi: post /points/boosts
+---
+
+import { RateLimitBadge } from "/snippets/rate-limit-badge.jsx";
+
+**Rate Limits**
+
+
diff --git a/api-reference/endpoints/points/get-points-boosts.mdx b/api-reference/endpoints/points/get-points-boosts.mdx
new file mode 100644
index 0000000..1e06e1f
--- /dev/null
+++ b/api-reference/endpoints/points/get-points-boosts.mdx
@@ -0,0 +1,9 @@
+---
+openapi: get /points/{key}/boosts
+---
+
+import { RateLimitBadge } from "/snippets/rate-limit-badge.jsx";
+
+**Rate Limits**
+
+
\ No newline at end of file
diff --git a/api-reference/endpoints/users/get-a-users-points-boosts.mdx b/api-reference/endpoints/users/get-a-users-points-boosts.mdx
new file mode 100644
index 0000000..1c91874
--- /dev/null
+++ b/api-reference/endpoints/users/get-a-users-points-boosts.mdx
@@ -0,0 +1,9 @@
+---
+openapi: get /users/{id}/points/{key}/boosts
+---
+
+import { RateLimitBadge } from "/snippets/rate-limit-badge.jsx";
+
+**Rate Limits**
+
+
\ No newline at end of file
diff --git a/api-reference/openapi.yml b/api-reference/openapi.yml
index d1b7c23..f9855d2 100644
--- a/api-reference/openapi.yml
+++ b/api-reference/openapi.yml
@@ -1805,6 +1805,95 @@ paths:
summary: Get a user's points data
security:
- ApiKeyAuth: []
+ /users/{id}/points/{key}/boosts:
+ servers:
+ - url: https://api.trophy.so/v1
+ description: Application API
+ get:
+ description: Get active points boosts for a user in a specific points system. Returns both global boosts the user is eligible for and user-specific boosts.
+ operationId: users_points_boosts
+ x-fern-server-name: api
+ tags:
+ - Users
+ x-codeSamples:
+ - lang: javascript
+ source: |
+ import { TrophyApiClient } from '@trophyso/node';
+
+ const trophy = new TrophyApiClient({
+ apiKey: 'YOUR_API_KEY'
+ });
+
+ const response = await trophy.users.pointsBoosts("user-id", "points-system-key");
+ - lang: python
+ source: |
+ from trophy import TrophyApi
+
+ client = TrophyApi(api_key='YOUR_API_KEY')
+
+ response = client.users.points_boosts(id="user-id", key="points-system-key")
+ parameters:
+ - name: id
+ in: path
+ description: ID of the user.
+ required: true
+ schema:
+ type: string
+ example: userId
+ - name: key
+ in: path
+ description: Key of the points system.
+ required: true
+ schema:
+ type: string
+ example: points-system-key
+ responses:
+ '200':
+ description: Successful operation
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/PointsBoost'
+ examples:
+ Successful operation:
+ value:
+ - id: 0040fe51-6bce-4b44-b0ad-bddc4e123534
+ name: Double XP Weekend
+ status: active
+ start: '2025-01-01'
+ end: '2025-01-03'
+ multiplier: 2
+ rounding: 'down'
+ - id: 0040fe51-6bce-4b44-b0ad-bddc4e123535
+ name: VIP Bonus
+ status: active
+ start: '2025-01-01'
+ end: null
+ multiplier: 1.5
+ rounding: 'nearest'
+ '401':
+ description: 'Unauthorized'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErrorBody'
+ '404':
+ description: 'Not Found'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErrorBody'
+ '422':
+ description: 'Unprocessible Entity'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErrorBody'
+ summary: Get a user's active points boosts
+ security:
+ - ApiKeyAuth: []
/users/{id}/points/{key}/event-summary:
servers:
- url: https://api.trophy.so/v1
@@ -2409,7 +2498,7 @@ paths:
- url: https://api.trophy.so/v1
description: Application API
get:
- description: Get a points system with all its triggers.
+ description: Get a points system with its triggers.
operationId: points_system
x-fern-server-name: api
tags:
@@ -2505,16 +2594,107 @@ paths:
summary: Get a points system with its triggers
security:
- ApiKeyAuth: []
+ /points/{key}/boosts:
+ servers:
+ - url: https://api.trophy.so/v1
+ description: Application API
+ get:
+ description: Get all global boosts for a points system. Finished boosts are excluded by default.
+ operationId: points_boosts
+ x-fern-server-name: api
+ tags:
+ - Points
+ x-codeSamples:
+ - lang: javascript
+ source: |
+ import { TrophyApiClient } from '@trophyso/node';
+
+ const trophy = new TrophyApiClient({
+ apiKey: 'YOUR_API_KEY'
+ });
+
+ const response = await trophy.points.boosts("points-system-key");
+ - lang: python
+ source: |
+ from trophy import TrophyApi
+
+ client = TrophyApi(api_key='YOUR_API_KEY')
+
+ response = client.points.boosts(key="points-system-key")
+ parameters:
+ - name: key
+ in: path
+ description: Key of the points system.
+ required: true
+ schema:
+ type: string
+ example: points-system-key
+ - name: includeFinished
+ in: query
+ description: When set to 'true', boosts that have finished (past their end date) will be included in the response. By default, finished boosts are excluded.
+ required: false
+ schema:
+ type: boolean
+ default: false
+ responses:
+ '200':
+ description: Successful operation
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/PointsBoost'
+ examples:
+ Successful operation:
+ value:
+ - id: 0040fe51-6bce-4b44-b0ad-bddc4e123537
+ name: Double XP Weekend
+ status: active
+ start: '2025-01-01'
+ end: '2025-01-03'
+ multiplier: 2
+ rounding: 'down'
+ - id: 0040fe51-6bce-4b44-b0ad-bddc4e123538
+ name: Holiday Bonus
+ status: finished
+ start: '2024-12-25'
+ end: '2024-12-31'
+ multiplier: 1.5
+ rounding: 'nearest'
+ '401':
+ description: 'Unauthorized'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErrorBody'
+ '404':
+ description: 'Points system not found'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErrorBody'
+ summary: Get boosts for a points system
+ security:
+ - ApiKeyAuth: []
/leaderboards:
servers:
- url: https://api.trophy.so/v1
description: Application API
get:
- description: Get all active leaderboards for your organization.
+ description: Get all leaderboards for your organization. Finished leaderboards are excluded by default.
operationId: leaderboards_all
x-fern-server-name: api
tags:
- Leaderboards
+ parameters:
+ - name: includeFinished
+ in: query
+ description: When set to 'true', leaderboards with status 'finished' will be included in the response. By default, finished leaderboards are excluded.
+ required: false
+ schema:
+ type: boolean
+ default: false
x-codeSamples:
- lang: javascript
source: |
@@ -2594,7 +2774,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
- summary: Get all active leaderboards
+ summary: Get all leaderboards
security:
- ApiKeyAuth: []
/leaderboards/{key}:
@@ -2972,15 +3152,322 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
- '422':
- description: 'Unprocessible Entity'
+ '422':
+ description: 'Unprocessible Entity'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErrorBody'
+ summary: Restore streaks for multiple users
+ security:
+ - ApiKeyAuth: []
+
+ /points/boosts:
+ servers:
+ - url: https://admin.trophy.so/v1
+ description: Admin API
+ post:
+ description: Create points boosts for multiple users.
+ operationId: admin_points_boosts_create
+ x-fern-server-name: admin
+ x-fern-sdk-group-name:
+ - admin
+ - points
+ - boosts
+ x-fern-sdk-method-name: create
+ tags:
+ - Admin
+ x-codeSamples:
+ - lang: javascript
+ source: |
+ import { TrophyApiClient } from '@trophyso/node';
+
+ const trophy = new TrophyApiClient({
+ apiKey: 'YOUR_API_KEY'
+ });
+
+ const response = await trophy.admin.points.boosts.create({
+ systemKey: 'xp',
+ boosts: [
+ {
+ userId: 'user-123',
+ name: 'Double XP Weekend',
+ start: '2024-01-01',
+ end: '2024-01-03',
+ multiplier: 2
+ },
+ {
+ userId: 'user-456',
+ name: 'Holiday Bonus',
+ start: '2024-12-25',
+ multiplier: 1.5,
+ rounding: 'up'
+ }
+ ]
+ });
+ - lang: python
+ source: |
+ from trophy import TrophyApi
+
+ client = TrophyApi(api_key='YOUR_API_KEY')
+
+ response = client.admin.points.boosts.create({
+ "systemKey": "xp",
+ "boosts": [
+ {
+ "userId": "user-123",
+ "name": "Double XP Weekend",
+ "start": "2024-01-01",
+ "end": "2024-01-03",
+ "multiplier": 2
+ },
+ {
+ "userId": "user-456",
+ "name": "Holiday Bonus",
+ "start": "2024-12-25",
+ "multiplier": 1.5,
+ "rounding": "up"
+ }
+ ]
+ })
+ requestBody:
+ description: The points system key and array of boosts to create
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CreatePointsBoostsRequest'
+ examples:
+ Create boosts for multiple users:
+ value:
+ systemKey: xp
+ boosts:
+ - userId: user-123
+ name: Double XP Weekend
+ start: '2024-01-01'
+ end: '2024-01-03'
+ multiplier: 2
+ - userId: user-456
+ name: Holiday Bonus
+ start: '2024-12-25'
+ multiplier: 1.5
+ rounding: up
+ responses:
+ '200':
+ description: Successful operation (no boosts created)
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CreatePointsBoostsResponse'
+ examples:
+ All requests had errors:
+ value:
+ created: []
+ issues:
+ - userId: non-existent-user
+ level: error
+ reason: User does not exist
+ '201':
+ description: Created (at least one boost created)
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CreatePointsBoostsResponse'
+ examples:
+ Success with no issues:
+ value:
+ created:
+ - id: '550e8400-e29b-41d4-a716-446655440000'
+ name: Double XP Weekend
+ status: active
+ start: '2024-01-01'
+ end: '2024-01-03'
+ multiplier: 2
+ rounding: down
+ userId: user-123
+ issues: []
+ Mixed success and errors:
+ value:
+ created:
+ - id: '550e8400-e29b-41d4-a716-446655440001'
+ name: Valid Boost
+ status: active
+ start: '2024-01-15'
+ end: null
+ multiplier: 1.5
+ rounding: down
+ userId: user-456
+ issues:
+ - userId: non-existent-user
+ level: error
+ reason: User does not exist
+ '400':
+ description: 'Bad Request'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErrorBody'
+ '401':
+ description: 'Unauthorized'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErrorBody'
+ '404':
+ description: 'Not Found (points system not found)'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErrorBody'
+ '422':
+ description: 'Unprocessible Entity'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErrorBody'
+ summary: Create points boosts for multiple users
+ security:
+ - ApiKeyAuth: []
+ delete:
+ description: Archive multiple points boosts by ID.
+ operationId: admin_points_boosts_batch_archive
+ x-fern-server-name: admin
+ x-fern-sdk-group-name:
+ - admin
+ - points
+ - boosts
+ x-fern-sdk-method-name: batchArchive
+ tags:
+ - Admin
+ x-codeSamples:
+ - lang: javascript
+ source: |
+ import { TrophyApiClient } from '@trophyso/node';
+
+ const trophy = new TrophyApiClient({
+ apiKey: 'YOUR_API_KEY'
+ });
+
+ const response = await trophy.admin.points.boosts.batchArchive({
+ ids: ['boost-uuid-1', 'boost-uuid-2', 'boost-uuid-3']
+ });
+
+ console.log(`Archived ${response.archivedCount} boosts`);
+ - lang: python
+ source: |
+ from trophy import TrophyApi
+
+ client = TrophyApi(api_key='YOUR_API_KEY')
+
+ response = client.admin.points.boosts.batch_archive(
+ ids=['boost-uuid-1', 'boost-uuid-2', 'boost-uuid-3']
+ )
+
+ print(f"Archived {response.archived_count} boosts")
+ parameters:
+ - name: ids
+ in: query
+ description: A list of up to 100 boost IDs.
+ required: true
+ schema:
+ type: array
+ items:
+ type: string
+ minItems: 1
+ maxItems: 100
+ example: 'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11,b1ffcd00-0d1c-4ef9-cc7e-7cc0ce491b22'
+ responses:
+ '200':
+ description: Successful operation
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ArchivePointsBoostsResponse'
+ examples:
+ All boosts archived:
+ value:
+ archivedCount: 3
+ Some boosts not found:
+ value:
+ archivedCount: 1
+ No boosts found:
+ value:
+ archivedCount: 0
+ '400':
+ description: 'Bad Request (no IDs provided or invalid UUID format)'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErrorBody'
+ '401':
+ description: 'Unauthorized'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErrorBody'
+ summary: Archive multiple points boosts
+ security:
+ - ApiKeyAuth: []
+
+ /points/boosts/{id}:
+ servers:
+ - url: https://admin.trophy.so/v1
+ description: Admin API
+ delete:
+ description: Archive a points boost by ID.
+ operationId: admin_points_boosts_archive
+ x-fern-server-name: admin
+ x-fern-sdk-group-name:
+ - admin
+ - points
+ - boosts
+ x-fern-sdk-method-name: archive
+ tags:
+ - Admin
+ x-codeSamples:
+ - lang: javascript
+ source: |
+ import { TrophyApiClient } from '@trophyso/node';
+
+ const trophy = new TrophyApiClient({
+ apiKey: 'YOUR_API_KEY'
+ });
+
+ await trophy.admin.points.boosts.archive('boost-uuid-here');
+ - lang: python
+ source: |
+ from trophy import TrophyApi
+
+ client = TrophyApi(api_key='YOUR_API_KEY')
+
+ client.admin.points.boosts.archive('boost-uuid-here')
+ parameters:
+ - name: id
+ in: path
+ required: true
+ description: The UUID of the points boost to archive
+ schema:
+ type: string
+ format: uuid
+ responses:
+ '204':
+ description: Successfully archived the points boost
+ '401':
+ description: 'Unauthorized'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
- summary: Restore streaks for multiple users
+ '404':
+ description: 'Not Found'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErrorBody'
+ summary: Archive a points boost
security:
- ApiKeyAuth: []
+
webhooks:
achievement.completed:
post:
@@ -3297,8 +3784,8 @@ webhooks:
$ref: '#/components/schemas/User'
description: The user whose points increased or decreased.
points:
- $ref: '#/components/schemas/GetUserPointsResponse'
- description: The user's points after the event.
+ $ref: '#/components/schemas/MetricEventPointsResponse'
+ description: The user's points after the event (includes added amount for this event).
required:
- type
- user
@@ -3325,6 +3812,7 @@ webhooks:
badgeUrl: null
maxPoints: null
total: 100
+ added: 10
awards:
- id: 0040fe51-6bce-4b44-b0ad-bddc4e123534
awarded: 10
@@ -3339,6 +3827,98 @@ webhooks:
responses:
'200':
description: Return a 200 status to indicate the webhook was received and processed.
+ points.boost_started:
+ post:
+ summary: Points boost started
+ operationId: webhooks_points_boost_started
+ description: Triggered when a points boost goes live (its start time has been reached).
+ requestBody:
+ description: The webhook event.
+ content:
+ application/json:
+ schema:
+ properties:
+ type:
+ type: string
+ enum: ['points.boost_started']
+ description: The webhook event type.
+ timestamp:
+ type: string
+ format: date-time
+ description: When the event occurred (ISO 8601).
+ boost:
+ $ref: '#/components/schemas/PointsBoostWebhookPayload'
+ description: The points boost that started.
+ required:
+ - type
+ - timestamp
+ - boost
+ examples:
+ Points boost started:
+ value:
+ type: points.boost_started
+ timestamp: '2025-01-15T00:00:00Z'
+ boost:
+ id: 0040fe51-6bce-4b44-b0ad-bddc4e123534
+ name: Double XP Weekend
+ status: active
+ userId: null
+ pointsSystemId: 0040fe51-6bce-4b44-b0ad-bddc4e123535
+ pointsSystemKey: xp
+ pointsSystemName: XP
+ start: '2025-01-15'
+ end: '2025-01-17'
+ multiplier: 2
+ rounding: down
+ responses:
+ '200':
+ description: Return a 200 status to indicate the webhook was received and processed.
+ points.boost_finished:
+ post:
+ summary: Points boost finished
+ operationId: webhooks_points_boost_finished
+ description: Triggered when a points boost ends (its end time has been reached).
+ requestBody:
+ description: The webhook event.
+ content:
+ application/json:
+ schema:
+ properties:
+ type:
+ type: string
+ enum: ['points.boost_finished']
+ description: The webhook event type.
+ timestamp:
+ type: string
+ format: date-time
+ description: When the event occurred (ISO 8601).
+ boost:
+ $ref: '#/components/schemas/PointsBoostWebhookPayload'
+ description: The points boost that finished.
+ required:
+ - type
+ - timestamp
+ - boost
+ examples:
+ Points boost finished:
+ value:
+ type: points.boost_finished
+ timestamp: '2025-01-17T23:59:59Z'
+ boost:
+ id: 0040fe51-6bce-4b44-b0ad-bddc4e123534
+ name: Double XP Weekend
+ status: finished
+ userId: null
+ pointsSystemId: 0040fe51-6bce-4b44-b0ad-bddc4e123535
+ pointsSystemKey: xp
+ pointsSystemName: XP
+ start: '2025-01-15'
+ end: '2025-01-17'
+ multiplier: 2
+ rounding: down
+ responses:
+ '200':
+ description: Return a 200 status to indicate the webhook was received and processed.
leaderboard.started:
post:
summary: Leaderboard started
@@ -3766,6 +4346,106 @@ components:
description: The user's total points after this award occurred.
trigger:
$ref: '#/components/schemas/PointsTrigger'
+ boosts:
+ type: array
+ description: Array of points boosts that applied to this award.
+ items:
+ $ref: '#/components/schemas/PointsBoost'
+ PointsBoost:
+ title: PointsBoost
+ type: object
+ properties:
+ id:
+ type: string
+ description: The ID of the points boost
+ name:
+ type: string
+ description: The name of the points boost
+ status:
+ type: string
+ enum: ['active', 'scheduled', 'finished']
+ description: The status of the points boost
+ start:
+ type: string
+ description: The start date of the points boost
+ end:
+ type:
+ - string
+ - 'null'
+ description: The end date of the points boost
+ multiplier:
+ type: number
+ description: The multiplier of the points boost
+ rounding:
+ type: string
+ enum: ['down', 'up', 'nearest']
+ description: The rounding method of the points boost
+ required:
+ - id
+ - name
+ - status
+ - start
+ - end
+ - multiplier
+ - rounding
+ PointsBoostWebhookPayload:
+ title: PointsBoostWebhookPayload
+ type: object
+ description: Points boost payload sent in points.boost_started and points.boost_finished webhook events.
+ properties:
+ id:
+ type: string
+ description: The ID of the points boost.
+ name:
+ type: string
+ description: The name of the points boost.
+ status:
+ type: string
+ enum: ['active', 'finished']
+ description: The status of the points boost.
+ userId:
+ type:
+ - string
+ - 'null'
+ description: The customer-facing user ID that the boost is scoped to, or null for global boosts.
+ pointsSystemId:
+ type: string
+ description: The ID of the points system this boost applies to.
+ pointsSystemKey:
+ type: string
+ description: The key of the points system this boost applies to.
+ pointsSystemName:
+ type: string
+ description: The name of the points system this boost applies to.
+ start:
+ type: string
+ format: date
+ description: The start date of the points boost (YYYY-MM-DD).
+ end:
+ type:
+ - string
+ - 'null'
+ format: date
+ description: The end date of the points boost (YYYY-MM-DD), or null if open-ended.
+ multiplier:
+ type: number
+ description: The multiplier applied to points during the boost.
+ rounding:
+ type: string
+ enum: ['down', 'up', 'nearest']
+ description: The rounding method applied to boosted points.
+ required:
+ - id
+ - name
+ - status
+ - userId
+ - pointsSystemId
+ - pointsSystemKey
+ - pointsSystemName
+ - start
+ - end
+ - multiplier
+ - rounding
GetUserPointsResponse:
title: GetUserPointsResponse
type: object
@@ -3926,16 +4606,54 @@ components:
MetricEventPointsResponse:
title: MetricEventPointsResponse
type: object
- allOf:
- - $ref: '#/components/schemas/GetUserPointsResponse'
- - type: object
- properties:
- added:
- type: integer
- description: The points added by this event.
- example: 10
- required:
- - added
+ description: Points system response for metric events.
+ properties:
+ id:
+ type: string
+ description: The ID of the points system
+ key:
+ type: string
+ description: The key of the points system
+ name:
+ type: string
+ description: The name of the points system
+ description:
+ type:
+ - string
+ - 'null'
+ description: The description of the points system
+ badgeUrl:
+ type:
+ - string
+ - 'null'
+ description: The URL of the badge image for the points system
+ maxPoints:
+ type:
+ - number
+ - 'null'
+ description: The maximum number of points a user can be awarded in this points system
+ total:
+ type: integer
+ description: The user's total points
+ added:
+ type: integer
+ description: The points added by this event.
+ example: 10
+ awards:
+ type: array
+ description: Array of trigger awards that added points.
+ items:
+ $ref: '#/components/schemas/PointsAward'
+ required:
+ - id
+ - key
+ - name
+ - description
+ - badgeUrl
+ - maxPoints
+ - total
+ - added
+ - awards
MetricEventLeaderboardResponse:
title: MetricEventLeaderboardResponse
type: object
@@ -4750,6 +5468,144 @@ components:
description: Array of issues encountered during freeze creation.
required:
- issues
+ CreatePointsBoostsRequest:
+ title: CreatePointsBoostsRequest
+ type: object
+ description: Request body for creating points boosts.
+ properties:
+ systemKey:
+ type: string
+ description: The key of the points system to create boosts for.
+ example: xp
+ boosts:
+ type: array
+ items:
+ type: object
+ properties:
+ userId:
+ type: string
+ description: The ID of the user to create a boost for.
+ example: user-123
+ name:
+ type: string
+ description: The name of the boost.
+ maxLength: 255
+ example: Double XP Weekend
+ start:
+ type: string
+ format: date
+ description: The start date of the boost (YYYY-MM-DD).
+ example: '2024-01-01'
+ end:
+ type:
+ - string
+ - 'null'
+ format: date
+ description: The end date of the boost (YYYY-MM-DD). If null, the boost has no end date.
+ example: '2024-01-03'
+ multiplier:
+ type: number
+ description: The points multiplier. Must be greater than 0, not equal to 1, and less than 100.
+ example: 2
+ exclusiveMinimum: 0
+ exclusiveMaximum: 100
+ rounding:
+ type: string
+ enum:
+ - down
+ - up
+ - nearest
+ default: down
+ description: How to round the boosted points. Defaults to 'down'.
+ example: down
+ required:
+ - userId
+ - name
+ - start
+ - multiplier
+ description: Array of boosts to create. Maximum 1,000 boosts per request.
+ maxItems: 1000
+ minItems: 1
+ required:
+ - systemKey
+ - boosts
+ CreatedPointsBoost:
+ title: CreatedPointsBoost
+ type: object
+ description: A successfully created points boost returned from the create endpoint.
+ properties:
+ id:
+ type: string
+ format: uuid
+ description: The UUID of the created boost.
+ name:
+ type: string
+ description: The name of the boost.
+ status:
+ type: string
+ enum: ['active', 'scheduled', 'finished']
+ description: The status of the boost.
+ start:
+ type: string
+ format: date
+ description: The start date (YYYY-MM-DD).
+ end:
+ type:
+ - string
+ - 'null'
+ format: date
+ description: The end date (YYYY-MM-DD) or null if no end date.
+ multiplier:
+ type: number
+ description: The points multiplier.
+ rounding:
+ type: string
+ enum:
+ - down
+ - up
+ - nearest
+ description: How boosted points are rounded.
+ userId:
+ type: string
+ description: The customer ID of the user the boost was created for.
+ required:
+ - id
+ - name
+ - status
+ - start
+ - end
+ - multiplier
+ - rounding
+ - userId
+ CreatePointsBoostsResponse:
+ title: CreatePointsBoostsResponse
+ type: object
+ description: Response containing created boosts and any issues encountered while creating points boosts.
+ properties:
+ created:
+ type: array
+ items:
+ $ref: '#/components/schemas/CreatedPointsBoost'
+ description: Array of successfully created boosts.
+ issues:
+ type: array
+ items:
+ $ref: '#/components/schemas/BulkInsertIssue'
+ description: Array of issues encountered during boost creation.
+ required:
+ - created
+ - issues
+ ArchivePointsBoostsResponse:
+ title: ArchivePointsBoostsResponse
+ type: object
+ description: Response containing the count of archived points boosts.
+ properties:
+ archivedCount:
+ type: integer
+ description: The number of boosts that were archived.
+ example: 3
+ required:
+ - archivedCount
RestoreStreaksRequest:
title: RestoreStreaksRequest
type: object
diff --git a/assets/platform/points/create_points_boost.mp4 b/assets/platform/points/create_points_boost.mp4
new file mode 100644
index 0000000..44edd0d
Binary files /dev/null and b/assets/platform/points/create_points_boost.mp4 differ
diff --git a/assets/platform/points/points_boost_attributes.png b/assets/platform/points/points_boost_attributes.png
new file mode 100644
index 0000000..b48f512
Binary files /dev/null and b/assets/platform/points/points_boost_attributes.png differ
diff --git a/docs.json b/docs.json
index ef13278..472fd0b 100644
--- a/docs.json
+++ b/docs.json
@@ -35,7 +35,13 @@
}
},
"contextual": {
- "options": ["copy", "view", "chatgpt", "claude", "perplexity"]
+ "options": [
+ "copy",
+ "view",
+ "chatgpt",
+ "claude",
+ "perplexity"
+ ]
},
"navigation": {
"tabs": [
@@ -101,7 +107,9 @@
},
{
"group": "Use Cases",
- "pages": ["guides/gamified-study-platform"]
+ "pages": [
+ "guides/gamified-study-platform"
+ ]
}
]
},
@@ -143,6 +151,7 @@
"group": "Points",
"pages": [
"api-reference/endpoints/points/get-points",
+ "api-reference/endpoints/points/get-points-boosts",
"api-reference/endpoints/points/get-points-summary"
]
},
@@ -166,6 +175,7 @@
"api-reference/endpoints/users/get-a-users-completed-achievements",
"api-reference/endpoints/users/get-a-users-streak",
"api-reference/endpoints/users/get-a-users-points",
+ "api-reference/endpoints/users/get-a-users-points-boosts",
"api-reference/endpoints/users/get-a-users-points-summary",
"api-reference/endpoints/users/get-a-users-leaderboard",
"api-reference/endpoints/users/get-a-users-wrapped",
@@ -181,7 +191,9 @@
"groups": [
{
"group": "Overview",
- "pages": ["admin-api/introduction"]
+ "pages": [
+ "admin-api/introduction"
+ ]
},
{
"group": "Streaks",
@@ -189,6 +201,14 @@
"admin-api/endpoints/streaks/grant-freezes",
"admin-api/endpoints/streaks/restore-streaks"
]
+ },
+ {
+ "group": "Points",
+ "pages": [
+ "admin-api/endpoints/points/create-boosts",
+ "admin-api/endpoints/points/archive-boosts-batch",
+ "admin-api/endpoints/points/archive-a-boost"
+ ]
}
]
},
@@ -209,7 +229,9 @@
},
{
"group": "Achievements",
- "pages": ["webhooks/events/achievements/achievement-completed"]
+ "pages": [
+ "webhooks/events/achievements/achievement-completed"
+ ]
},
{
"group": "Streaks",
@@ -223,7 +245,11 @@
},
{
"group": "Points",
- "pages": ["webhooks/events/points/points-changed"]
+ "pages": [
+ "webhooks/events/points/points-changed",
+ "webhooks/events/points/points-boost-started",
+ "webhooks/events/points/points-boost-finished"
+ ]
},
{
"group": "Leaderboards",
@@ -288,4 +314,4 @@
"linkedin": "https://linkedin.com/company/trophylabs"
}
}
-}
+}
\ No newline at end of file
diff --git a/platform/events.mdx b/platform/events.mdx
index 8496681..792a440 100644
--- a/platform/events.mdx
+++ b/platform/events.mdx
@@ -17,9 +17,13 @@ When you [integrate metrics](#tracking-metric-events) into your platform, you're
## Key Attributes
-Events only have one required attribute, `value`. The value of an event is the numerical amount that will be added to the user's total metric count as a result of the user interaction it relates to.
+### Event Value
-The value can be positive or negative, and can be a whole number or a decimal.
+The `value` of an event is the numerical amount that will be added to the user's total metric count as a result of the user interaction it relates to.
+
+
+The value of an event can be positive or negative, and can be a whole number or a decimal.
+
## Custom Event Attributes
diff --git a/platform/points.mdx b/platform/points.mdx
index d53c890..fcad4f1 100644
--- a/platform/points.mdx
+++ b/platform/points.mdx
@@ -76,23 +76,23 @@ You can add as many triggers as you like to each points system you set up, allow
There are multiple types of triggers in Trophy that can be used to award or deduct points in different ways.
-**Metric Triggers**
+#### Metric Triggers
Points can be awarded or deducted continually as users increment [Metrics](/platform/metrics). You can choose to award or deduct any arbitrary number of points at any arbitrary metric threshold, for example "award 10 points for every 3 tasks completed".
-**Streak Triggers**
+#### Streak Triggers
Points can be awarded or deducted for reaching any arbitrary length of a [Streak](/platform/streaks), for example "award 50 points for every 7 days streak".
-**Achievement Triggers**
+#### Achievement Triggers
Points can be awarded or deducted when users unlock specific [Achievements](/platform/achievements), for example "award 100 points when users completed the `profile-completed` achievement".
-**Time-based Triggers**
+#### Time-based Triggers
Points can be awarded or deducted at repeating time intervals, every hour or every day. For example "award 10 points every 3 hours".
-**User Identification Triggers**
+#### User Identification Triggers
Points can be awarded when users are first identified in Trophy, useful for granting an initial amount of points when they sign up to your product.
@@ -175,15 +175,120 @@ Trophy's preview tool can model different scenarios to help you determine how fr
>
+## Points Boosts
+
+Points boosts are multipliers that you can use to increase the number of points awarded to users during a specific time period.
+
+This section explains how boosts work and how they can be used to increase your application's retention and engagement.
+
+### Boost Targeting
+
+There are a few different ways you can use boosts in Trophy.
+
+- **Global boosts** multiply points earned by all users during the boost window, or can be scoped to a specific user cohort by using [custom user attributes](/platform/users#custom-user-attributes).
+- **User-specific boosts** only multiply points earned by a single user within the boost window.
+
+Typically, global boosts are used to increase platform-wide engagement during key calendar events like Black Friday/Cyber Monday in e-commerce, New Year in fitness and exam season in ed-tech platforms.
+
+Conversely, user-specific boosts are commonly used to provide additional incentives for users to take actions that are correlated with higher retention.
+
+### Creating Boosts
+
+
+User-specific boosts can only be created programmatically through the [Admin API](/admin-api/endpoints/points/create-boosts).
+
+
+To create a global points boost in the Trophy dashboard, follow the steps below.
+
+
+
+
+
+
+
+ Go to the [points page](https://app.trophy.so/points) and click on the points system you want to create a boost for. Then navigate to the Boosts tab and click the *New Boost* button.
+
+
+ Choose a name for your boost that clearly describes what it's for. For example "2X Boost - All Users - Christmas 2026".
+
+
+ Set the numeric value that the boost will multiply points earned by. If you choose a decimal multiplier, you'll have the option to choose the [rounding behavior](#boost-rounding) the boost should use.
+
+
+ Choose a start and (optionally) an end date for your boost. If you choose a future start date, Trophy will schedule the boost to go active on your chosen date. Similarly if you set an end date, Trophy will take care of stopping your boost for you.
+
+
+
+
+ This feature requires [custom user attributes](/platform/users#custom-user-attributes) which are available on the [Pro](/account/billing#pro-plan) plan.
+
+
+ If you want your boost to only affect a specific user cohort, set user attribute conditions that match those of your target cohort. Trophy will take care of only applying the boost to points earned by users with matching user attribute values.
+
+
+
+
+
+
+ Click *Save Boost* to save your new boost to your account. The boost will be in the inactive state by default. To activate it, click the dropdown to the right of the boost name on the Boosts page and click Activate.
+
+
+
+### Boost Multipliers
+
+Every boost has a single multiplier value that increases the total points earned by users affected by that boost.
+
+Boost multipliers must be positive numbers, but can be decimals to support scenarios where percentage boosts like '50% more points' may be required.
+
+### Boost Stacking
+
+Points boosts in Trophy stack through [multiplication](#boost-multipliers). This is to support allowing users to benefit from multiple boosts simultaneously.
+
+To demonstrate stacking consider a 2X, 1.5X and a 3X boost all active within the same time period. The resulting boost multiplier for a user that qualifies for all three boosts would be as follows:
+
+```txt Boost Stacking Example
+Overall Multiplier (3 boosts) = 2X * 1.5X * 3X = 9X
+```
+
+### Boost Rounding
+
+Trophy supports [floating point metric event values](/platform/events#event-value), but takes care of rounding points to integers automatically.
+
+However, when using decimal [boost multipliers](#boost-multipliers), there may be some scenarios where this default rounding is not enough to always produce integer points values.
+
+Therefore Trophy offers three rounding modes to provide additional control on rounding behavior specifically when boosts are involved in points calculations.
+
+- **Round Down**: By default, Trophy will round points down to the nearest integer when boost multiplication results in a decimal.
+- **Round Up**: Trophy rounds decimal points up to the nearest integer after boost multiplication.
+- **Round Nearest**: Trophy will round points to the nearest integer, up or down, based on the final value after boost multiplication. For example `1.2` is rounded to `1` and `1.7` is rounded to `2`.
+
+
+In scenarios where points are used to mimic platform credit mechanics, it's recommended to use the default rounding down behavior to protect against slippage.
+
+
+Simply choose your preferred rounding mode when [creating boosts](/platform/points#creating-boosts) through the Trophy dashboard.
+
## Displaying Points
There are a few ways to use Trophy to fetch and display points in your app.
-
- Check out our guides on adding an [XP
+
+ For working examples check out our guides on adding an [XP
feature](/guides/how-to-build-an-xp-feature) or an [energy
feature](/guides/how-to-build-an-energy-feature) to your web or mobile app.
-
+