diff --git a/api-reference/endpoints/users/get-user-preferences.mdx b/api-reference/endpoints/users/get-user-preferences.mdx
new file mode 100644
index 0000000..304d839
--- /dev/null
+++ b/api-reference/endpoints/users/get-user-preferences.mdx
@@ -0,0 +1,3 @@
+---
+openapi: get /users/{id}/preferences
+---
diff --git a/api-reference/endpoints/users/update-user-preferences.mdx b/api-reference/endpoints/users/update-user-preferences.mdx
new file mode 100644
index 0000000..41220f7
--- /dev/null
+++ b/api-reference/endpoints/users/update-user-preferences.mdx
@@ -0,0 +1,3 @@
+---
+openapi: patch /users/{id}/preferences
+---
diff --git a/api-reference/openapi.yml b/api-reference/openapi.yml
index d1b7c23..4e0cea0 100644
--- a/api-reference/openapi.yml
+++ b/api-reference/openapi.yml
@@ -1,7 +1,7 @@
openapi: 3.1.0
info:
title: Trophy
- version: '1.0.39'
+ version: "1.0.39"
paths:
# APPLICATION API -------------------------------------------------------
@@ -41,14 +41,14 @@ paths:
type: string
example: plan-type:premium,region:us-east
responses:
- '200':
+ "200":
description: Successful operation
content:
application/json:
schema:
type: array
items:
- $ref: '#/components/schemas/AchievementWithStatsResponse'
+ $ref: "#/components/schemas/AchievementWithStatsResponse"
examples:
Successful operation:
value:
@@ -89,18 +89,18 @@ paths:
userAttributes:
- key: plan-type
value: premium
- '401':
- description: 'Unauthorized'
+ "401":
+ description: "Unauthorized"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '422':
- description: 'Unprocessible Entity'
+ $ref: "#/components/schemas/ErrorBody"
+ "422":
+ description: "Unprocessible Entity"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
+ $ref: "#/components/schemas/ErrorBody"
summary: Get all achievements and their completion stats
security:
- ApiKeyAuth: []
@@ -146,12 +146,12 @@ paths:
type: string
example: finish-onboarding
responses:
- '201':
+ "201":
description: Successful operation
content:
application/json:
schema:
- $ref: '#/components/schemas/AchievementCompletionResponse'
+ $ref: "#/components/schemas/AchievementCompletionResponse"
examples:
Successful operation:
value:
@@ -163,7 +163,7 @@ paths:
description: Complete the onboarding process.
badgeUrl: https://example.com/badge.png
key: finish-onboarding
- achievedAt: '2021-01-01T00:00:00Z'
+ achievedAt: "2021-01-01T00:00:00Z"
points:
points-system-key:
id: 0040fe51-6bce-4b44-b0ad-bddc4e123534
@@ -175,31 +175,31 @@ paths:
awards:
- id: 0040fe51-6bce-4b44-b0ad-bddc4e123534
awarded: 10
- date: '2021-01-01T00:00:00Z'
+ date: "2021-01-01T00:00:00Z"
total: 10
trigger:
id: 0040fe51-6bce-4b44-b0ad-bddc4e123534
type: achievement
achievementName: Finish onboarding
points: 10
- '401':
- description: 'Unauthorized'
+ "401":
+ description: "Unauthorized"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '404':
- description: 'Achievement Not Found'
+ $ref: "#/components/schemas/ErrorBody"
+ "404":
+ description: "Achievement Not Found"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '422':
- description: 'Unprocessible Entity'
+ $ref: "#/components/schemas/ErrorBody"
+ "422":
+ description: "Unprocessible Entity"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
+ $ref: "#/components/schemas/ErrorBody"
summary: Mark an achievement as completed
security:
- ApiKeyAuth: []
@@ -211,7 +211,7 @@ paths:
type: object
properties:
user:
- $ref: '#/components/schemas/UpsertedUser'
+ $ref: "#/components/schemas/UpsertedUser"
description: The user that completed the achievement.
required:
- user
@@ -303,12 +303,12 @@ paths:
type: string
example: e4296e4b-8493-4bd1-9c30-5a1a9ac4d78f
responses:
- '201':
+ "201":
description: Created event
content:
application/json:
schema:
- $ref: '#/components/schemas/EventResponse'
+ $ref: "#/components/schemas/EventResponse"
examples:
Successful operation:
value:
@@ -323,14 +323,14 @@ paths:
metricValue: 500
name: 500 words written
description: Write 500 words in the app.
- achievedAt: '2020-01-01T00:00:00Z'
+ achievedAt: "2020-01-01T00:00:00Z"
currentStreak:
length: 1
frequency: daily
- started: '2025-04-02'
- periodStart: '2025-03-31'
- periodEnd: '2025-04-05'
- expires: '2025-04-12'
+ started: "2025-04-02"
+ periodStart: "2025-03-31"
+ periodEnd: "2025-04-05"
+ expires: "2025-04-12"
points:
xp:
id: 0040fe51-6bce-4b44-b0ad-bddc4e123534
@@ -342,7 +342,7 @@ paths:
awards:
- id: 0040fe51-6bce-4b44-b0ad-bddc4e123534
awarded: 10
- date: '2021-01-01T00:00:00Z'
+ date: "2021-01-01T00:00:00Z"
total: 10
trigger:
id: 0040fe51-6bce-4b44-b0ad-bddc4e123534
@@ -364,28 +364,28 @@ paths:
metricName: words written
metricKey: words-written
threshold: 10
- start: '2025-01-01'
+ start: "2025-01-01"
end: null
previousRank: null
rank: 100
- '400':
- description: 'Bad Request'
+ "400":
+ description: "Bad Request"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '401':
- description: 'Unauthorized'
+ $ref: "#/components/schemas/ErrorBody"
+ "401":
+ description: "Unauthorized"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '422':
- description: 'Unprocessible Entity'
+ $ref: "#/components/schemas/ErrorBody"
+ "422":
+ description: "Unprocessible Entity"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
+ $ref: "#/components/schemas/ErrorBody"
summary: Send a metric change event
security:
- ApiKeyAuth: []
@@ -397,7 +397,7 @@ paths:
type: object
properties:
user:
- $ref: '#/components/schemas/UpsertedUser'
+ $ref: "#/components/schemas/UpsertedUser"
description: The user that triggered the event.
value:
type: number
@@ -423,7 +423,7 @@ paths:
user:
email: user@example.com
tz: Europe/London
- id: '18'
+ id: "18"
attributes:
department: engineering
role: developer
@@ -485,15 +485,15 @@ paths:
application/json:
schema:
type: object
- $ref: '#/components/schemas/UpsertedUser'
+ $ref: "#/components/schemas/UpsertedUser"
description: The user object.
responses:
- '201':
+ "201":
description: Identified user
content:
application/json:
schema:
- $ref: '#/components/schemas/User'
+ $ref: "#/components/schemas/User"
examples:
Successful operation:
value:
@@ -501,29 +501,29 @@ paths:
email: user@example.com
tz: Europe/London
subscribedToEmails: true
- created: '2021-01-01T00:00:00Z'
- updated: '2021-01-01T00:00:00Z'
+ created: "2021-01-01T00:00:00Z"
+ updated: "2021-01-01T00:00:00Z"
attributes:
department: engineering
role: developer
- '400':
- description: 'Bad Request'
+ "400":
+ description: "Bad Request"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '422':
- description: 'Unprocessible Entity'
+ $ref: "#/components/schemas/ErrorBody"
+ "422":
+ description: "Unprocessible Entity"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '401':
- description: 'Unauthorized'
+ $ref: "#/components/schemas/ErrorBody"
+ "401":
+ description: "Unauthorized"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
+ $ref: "#/components/schemas/ErrorBody"
/users/{id}:
servers:
- url: https://api.trophy.so/v1
@@ -563,12 +563,12 @@ paths:
security:
- ApiKeyAuth: []
responses:
- '200':
+ "200":
description: Found user
content:
application/json:
schema:
- $ref: '#/components/schemas/User'
+ $ref: "#/components/schemas/User"
examples:
Successful operation:
value:
@@ -576,29 +576,29 @@ paths:
email: user@example.com
tz: Europe/London
subscribedToEmails: true
- created: '2021-01-01T00:00:00Z'
- updated: '2021-01-01T00:00:00Z'
+ created: "2021-01-01T00:00:00Z"
+ updated: "2021-01-01T00:00:00Z"
attributes:
department: engineering
role: developer
- '400':
- description: 'Bad Request'
+ "400":
+ description: "Bad Request"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '422':
- description: 'Unprocessible Entity'
+ $ref: "#/components/schemas/ErrorBody"
+ "422":
+ description: "Unprocessible Entity"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '401':
- description: 'Unauthorized'
+ $ref: "#/components/schemas/ErrorBody"
+ "401":
+ description: "Unauthorized"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
+ $ref: "#/components/schemas/ErrorBody"
put:
description: Identify a user.
operationId: users_identify
@@ -654,7 +654,7 @@ paths:
content:
application/json:
schema:
- $ref: '#/components/schemas/UpdatedUser'
+ $ref: "#/components/schemas/UpdatedUser"
description: The user object.
example:
email: user@example.com
@@ -663,12 +663,12 @@ paths:
department: engineering
role: developer
responses:
- '200':
+ "200":
description: Upserted user
content:
application/json:
schema:
- $ref: '#/components/schemas/User'
+ $ref: "#/components/schemas/User"
examples:
Successful operation:
value:
@@ -676,26 +676,26 @@ paths:
email: user@example.com
tz: Europe/London
subscribedToEmails: true
- created: '2021-01-01T00:00:00Z'
- updated: '2021-01-01T00:00:00Z'
- '400':
- description: 'Bad Request'
+ created: "2021-01-01T00:00:00Z"
+ updated: "2021-01-01T00:00:00Z"
+ "400":
+ description: "Bad Request"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '422':
- description: 'Unprocessible Entity'
+ $ref: "#/components/schemas/ErrorBody"
+ "422":
+ description: "Unprocessible Entity"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '401':
- description: 'Unauthorized'
+ $ref: "#/components/schemas/ErrorBody"
+ "401":
+ description: "Unauthorized"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
+ $ref: "#/components/schemas/ErrorBody"
patch:
description: Update a user.
operationId: users_update
@@ -751,7 +751,7 @@ paths:
content:
application/json:
schema:
- $ref: '#/components/schemas/UpdatedUser'
+ $ref: "#/components/schemas/UpdatedUser"
description: The user object.
example:
id: user-id
@@ -761,12 +761,12 @@ paths:
department: engineering
role: developer
responses:
- '200':
+ "200":
description: Updated user
content:
application/json:
schema:
- $ref: '#/components/schemas/User'
+ $ref: "#/components/schemas/User"
examples:
Successful operation:
value:
@@ -774,32 +774,32 @@ paths:
email: user@example.com
tz: Europe/London
subscribedToEmails: true
- created: '2021-01-01T00:00:00Z'
- updated: '2021-01-01T00:00:00Z'
- '400':
- description: 'Bad Request'
+ created: "2021-01-01T00:00:00Z"
+ updated: "2021-01-01T00:00:00Z"
+ "400":
+ description: "Bad Request"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '404':
- description: 'User Not Found'
+ $ref: "#/components/schemas/ErrorBody"
+ "404":
+ description: "User Not Found"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '422':
- description: 'Unprocessible Entity'
+ $ref: "#/components/schemas/ErrorBody"
+ "422":
+ description: "Unprocessible Entity"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '401':
- description: 'Unauthorized'
+ $ref: "#/components/schemas/ErrorBody"
+ "401":
+ description: "Unauthorized"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
+ $ref: "#/components/schemas/ErrorBody"
/users/{id}/preferences:
servers:
- url: https://api.trophy.so/v1
@@ -836,12 +836,12 @@ paths:
type: string
example: user-123
responses:
- '200':
+ "200":
description: Successful operation
content:
application/json:
schema:
- $ref: '#/components/schemas/UserPreferencesResponse'
+ $ref: "#/components/schemas/UserPreferencesResponse"
examples:
Successful operation:
value:
@@ -856,24 +856,24 @@ paths:
streak_reminder:
- email
- push
- '401':
- description: 'Unauthorized'
+ "401":
+ description: "Unauthorized"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '404':
- description: 'User not found'
+ $ref: "#/components/schemas/ErrorBody"
+ "404":
+ description: "User not found"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '422':
- description: 'Unprocessible Entity'
+ $ref: "#/components/schemas/ErrorBody"
+ "422":
+ description: "Unprocessible Entity"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
+ $ref: "#/components/schemas/ErrorBody"
summary: Get a user's preferences
security:
- ApiKeyAuth: []
@@ -920,12 +920,12 @@ paths:
type: string
example: user-123
responses:
- '200':
+ "200":
description: Successful operation
content:
application/json:
schema:
- $ref: '#/components/schemas/UserPreferencesResponse'
+ $ref: "#/components/schemas/UserPreferencesResponse"
examples:
Successful operation:
value:
@@ -939,24 +939,24 @@ paths:
- email
- push
streak_reminder: []
- '401':
- description: 'Unauthorized'
+ "401":
+ description: "Unauthorized"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '404':
- description: 'User not found'
+ $ref: "#/components/schemas/ErrorBody"
+ "404":
+ description: "User not found"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '422':
- description: 'Unprocessible Entity'
+ $ref: "#/components/schemas/ErrorBody"
+ "422":
+ description: "Unprocessible Entity"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
+ $ref: "#/components/schemas/ErrorBody"
summary: Update a user's preferences
security:
- ApiKeyAuth: []
@@ -965,7 +965,7 @@ paths:
content:
application/json:
schema:
- $ref: '#/components/schemas/UpdateUserPreferencesRequest'
+ $ref: "#/components/schemas/UpdateUserPreferencesRequest"
examples:
Disable streak reminders:
value:
@@ -1018,14 +1018,14 @@ paths:
type: string
example: userId
responses:
- '200':
+ "200":
description: Successful operation
content:
application/json:
schema:
type: array
items:
- $ref: '#/components/schemas/MetricResponse'
+ $ref: "#/components/schemas/MetricResponse"
examples:
Successful operation:
value:
@@ -1038,45 +1038,45 @@ paths:
- id: abe3120f-5ca9-4344-92c8-5b891643a04b
trigger: metric
name: Novice Writer
- description: 'null'
+ description: "null"
metricId: d01dcbcb-d51e-4c12-b054-dc811dcdc623
metricValue: 500
- achievedAt: '2021-01-01T00:00:00Z'
+ achievedAt: "2021-01-01T00:00:00Z"
badgeUrl: https://example.com/badge1.png
- id: 8a07f2d0-9c72-4de1-bf92-9530ae82b4b6
trigger: metric
name: Intermediate Writer
- description: 'null'
+ description: "null"
metricId: d01dcbcb-d51e-4c12-b054-dc811dcdc623
metricValue: 1000
- achievedAt: '2021-01-02T00:00:00Z'
+ achievedAt: "2021-01-02T00:00:00Z"
badgeUrl: https://example.com/badge2.png
- id: 2090d038-aa04-4048-ab2e-e2b7bf2d3b9f
trigger: metric
name: Expert Writer
- description: 'null'
+ description: "null"
metricId: d01dcbcb-d51e-4c12-b054-dc811dcdc623
metricValue: 2000
achievedAt: null
- badgeUrl: 'null'
- '401':
- description: 'Unauthorized'
+ badgeUrl: "null"
+ "401":
+ description: "Unauthorized"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '404':
- description: 'User Not Found'
+ $ref: "#/components/schemas/ErrorBody"
+ "404":
+ description: "User Not Found"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '422':
- description: 'Unprocessible Entity'
+ $ref: "#/components/schemas/ErrorBody"
+ "422":
+ description: "Unprocessible Entity"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
+ $ref: "#/components/schemas/ErrorBody"
summary: Get all metrics for a user
security:
- ApiKeyAuth: []
@@ -1123,12 +1123,12 @@ paths:
type: string
example: key
responses:
- '200':
+ "200":
description: Successful operation
content:
application/json:
schema:
- $ref: '#/components/schemas/MetricResponse'
+ $ref: "#/components/schemas/MetricResponse"
examples:
Successful operation:
value:
@@ -1143,13 +1143,13 @@ paths:
name: Novice Writer
metricId: d01dcbcb-d51e-4c12-b054-dc811dcdc623
metricValue: 500
- achievedAt: '2021-01-01T00:00:00Z'
+ achievedAt: "2021-01-01T00:00:00Z"
- id: 8a07f2d0-9c72-4de1-bf92-9530ae82b4b6
trigger: metric
name: Intermediate Writer
metricId: d01dcbcb-d51e-4c12-b054-dc811dcdc623
metricValue: 1000
- achievedAt: '2021-01-02T00:00:00Z'
+ achievedAt: "2021-01-02T00:00:00Z"
- id: 2090d038-aa04-4048-ab2e-e2b7bf2d3b9f
trigger: metric
name: Expert Writer
@@ -1157,24 +1157,24 @@ paths:
metricValue: 2000
achievedAt: null
badgeUrl: https://example.com/badge.png
- '401':
- description: 'Unauthorized'
+ "401":
+ description: "Unauthorized"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '404':
- description: 'Not Found'
+ $ref: "#/components/schemas/ErrorBody"
+ "404":
+ description: "Not Found"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '422':
- description: 'Unprocessible Entity'
+ $ref: "#/components/schemas/ErrorBody"
+ "422":
+ description: "Unprocessible Entity"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
+ $ref: "#/components/schemas/ErrorBody"
summary: Get a single metric for a user
security:
- ApiKeyAuth: []
@@ -1248,7 +1248,7 @@ paths:
schema:
type: string
format: date
- example: '2024-01-01'
+ example: "2024-01-01"
- name: endDate
in: query
description: The end date for the data range in YYYY-MM-DD format. The endDate must be after the startDate, and the date range must not exceed 400 days.
@@ -1256,9 +1256,9 @@ paths:
schema:
type: string
format: date
- example: '2024-01-31'
+ example: "2024-01-31"
responses:
- '200':
+ "200":
description: Successful operation
content:
application/json:
@@ -1271,7 +1271,7 @@ paths:
type: string
format: date
description: The date of the data point. For weekly or monthly aggregations, this is the first date of the period.
- example: '2024-01-01'
+ example: "2024-01-01"
total:
type: number
format: double
@@ -1289,33 +1289,33 @@ paths:
examples:
Successful operation:
value:
- - date: '2024-01-01'
+ - date: "2024-01-01"
total: 100
change: 100
- - date: '2024-01-02'
+ - date: "2024-01-02"
total: 300
change: 200
- - date: '2024-01-03'
+ - date: "2024-01-03"
total: 600
change: 300
- '401':
- description: 'Unauthorized'
+ "401":
+ description: "Unauthorized"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '404':
- description: 'Not Found'
+ $ref: "#/components/schemas/ErrorBody"
+ "404":
+ description: "Not Found"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '422':
- description: 'Unprocessible Entity'
+ $ref: "#/components/schemas/ErrorBody"
+ "422":
+ description: "Unprocessible Entity"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
+ $ref: "#/components/schemas/ErrorBody"
summary: Get a summary of metric events over time
security:
- ApiKeyAuth: []
@@ -1382,17 +1382,17 @@ paths:
required: false
schema:
type: string
- enum: ['true']
- example: 'true'
+ enum: ["true"]
+ example: "true"
responses:
- '200':
+ "200":
description: Successful operation
content:
application/json:
schema:
type: array
items:
- $ref: '#/components/schemas/UserAchievementWithStatsResponse'
+ $ref: "#/components/schemas/UserAchievementWithStatsResponse"
examples:
Successful operation:
value:
@@ -1400,7 +1400,7 @@ paths:
name: Completed Onboarding
trigger: api
key: completed-onboarding
- achievedAt: '2021-01-01T00:00:00Z'
+ achievedAt: "2021-01-01T00:00:00Z"
badgeUrl: https://example.com/badge2.png
completions: 100
rarity: 50
@@ -1411,7 +1411,7 @@ paths:
metricValue: 500
metricName: words written
name: Novice Writer
- achievedAt: '2021-02-01T00:00:00Z'
+ achievedAt: "2021-02-01T00:00:00Z"
badgeUrl: https://example.com/badge1.png
completions: 100
rarity: 50
@@ -1420,28 +1420,28 @@ paths:
key: 3-day-streak
streakLength: 3
name: 3-Day Streak
- achievedAt: '2021-03-01T00:00:00Z'
+ achievedAt: "2021-03-01T00:00:00Z"
badgeUrl: https://example.com/badge2.png
completions: 100
rarity: 50
- '401':
- description: 'Unauthorized'
+ "401":
+ description: "Unauthorized"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '404':
- description: 'Not Found'
+ $ref: "#/components/schemas/ErrorBody"
+ "404":
+ description: "Not Found"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '422':
- description: 'Unprocessible Entity'
+ $ref: "#/components/schemas/ErrorBody"
+ "422":
+ description: "Unprocessible Entity"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
+ $ref: "#/components/schemas/ErrorBody"
summary: Get a user's achievements
security:
- ApiKeyAuth: []
@@ -1491,63 +1491,63 @@ paths:
The number of past streak periods to include in the streakHistory field of the
response.
responses:
- '200':
+ "200":
description: Successful operation
content:
application/json:
schema:
type: object
- $ref: '#/components/schemas/StreakResponse'
+ $ref: "#/components/schemas/StreakResponse"
examples:
Successful operation:
value:
length: 1
frequency: weekly
- started: '2025-04-02'
- periodStart: '2025-03-31'
- periodEnd: '2025-04-05'
- expires: '2025-04-12'
+ started: "2025-04-02"
+ periodStart: "2025-03-31"
+ periodEnd: "2025-04-05"
+ expires: "2025-04-12"
rank: 5
streakHistory:
- - periodStart: '2025-03-30'
- periodEnd: '2025-04-05'
+ - periodStart: "2025-03-30"
+ periodEnd: "2025-04-05"
length: 1
- - periodStart: '2025-04-06'
- periodEnd: '2025-04-12'
+ - periodStart: "2025-04-06"
+ periodEnd: "2025-04-12"
length: 2
- - periodStart: '2025-04-13'
- periodEnd: '2025-04-19'
+ - periodStart: "2025-04-13"
+ periodEnd: "2025-04-19"
length: 3
- - periodStart: '2025-04-20'
- periodEnd: '2025-04-26'
+ - periodStart: "2025-04-20"
+ periodEnd: "2025-04-26"
length: 0
- - periodStart: '2025-04-27'
- periodEnd: '2025-05-03'
+ - periodStart: "2025-04-27"
+ periodEnd: "2025-05-03"
length: 1
- - periodStart: '2025-05-04'
- periodEnd: '2025-05-10'
+ - periodStart: "2025-05-04"
+ periodEnd: "2025-05-10"
length: 2
- - periodStart: '2025-05-11'
- periodEnd: '2025-05-17'
+ - periodStart: "2025-05-11"
+ periodEnd: "2025-05-17"
length: 3
- '401':
- description: 'Unauthorized'
+ "401":
+ description: "Unauthorized"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '404':
- description: 'Not Found'
+ $ref: "#/components/schemas/ErrorBody"
+ "404":
+ description: "Not Found"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '422':
- description: 'Unprocessible Entity'
+ $ref: "#/components/schemas/ErrorBody"
+ "422":
+ description: "Unprocessible Entity"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
+ $ref: "#/components/schemas/ErrorBody"
summary: Get a user's streak status
security:
- ApiKeyAuth: []
@@ -1585,38 +1585,38 @@ paths:
type: array
items:
type: string
- example: 'user-123,user-456,user-789'
+ example: "user-123,user-456,user-789"
responses:
- '200':
+ "200":
description: Successful operation
content:
application/json:
schema:
- $ref: '#/components/schemas/BulkStreakResponse'
+ $ref: "#/components/schemas/BulkStreakResponse"
examples:
Successful operation:
value:
- userId: user-123
streakLength: 15
- extended: '2025-01-01T05:03:00Z'
+ extended: "2025-01-01T05:03:00Z"
- userId: user-456
streakLength: 12
- extended: '2025-01-01T08:43:00Z'
+ extended: "2025-01-01T08:43:00Z"
- userId: user-789
streakLength: 0
extended: null
- '401':
- description: 'Unauthorized'
+ "401":
+ description: "Unauthorized"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '422':
- description: 'Unprocessible Entity'
+ $ref: "#/components/schemas/ErrorBody"
+ "422":
+ description: "Unprocessible Entity"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
+ $ref: "#/components/schemas/ErrorBody"
summary: Get the streak lengths of a list of users
security:
- ApiKeyAuth: []
@@ -1667,18 +1667,18 @@ paths:
required: false
schema:
type: string
- enum: ['active', 'longest']
- default: 'active'
- example: 'active'
+ enum: ["active", "longest"]
+ default: "active"
+ example: "active"
responses:
- '200':
+ "200":
description: Successful operation
content:
application/json:
schema:
type: array
items:
- $ref: '#/components/schemas/StreakRankingUser'
+ $ref: "#/components/schemas/StreakRankingUser"
examples:
Successful operation:
value:
@@ -1691,18 +1691,18 @@ paths:
- userId: user-789
name: Charlie Brown
streakLength: 8
- '401':
- description: 'Unauthorized'
+ "401":
+ description: "Unauthorized"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '422':
- description: 'Unprocessible Entity'
+ $ref: "#/components/schemas/ErrorBody"
+ "422":
+ description: "Unprocessible Entity"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
+ $ref: "#/components/schemas/ErrorBody"
summary: Get top users by streak length
security:
- ApiKeyAuth: []
@@ -1757,12 +1757,12 @@ paths:
maximum: 100
description: The number of recent point awards to return.
responses:
- '200':
+ "200":
description: Successful operation
content:
application/json:
schema:
- $ref: '#/components/schemas/GetUserPointsResponse'
+ $ref: "#/components/schemas/GetUserPointsResponse"
examples:
Successful operation:
value:
@@ -1776,7 +1776,7 @@ paths:
awards:
- id: 0040fe51-6bce-4b44-b0ad-bddc4e123534
awarded: 10
- date: '2021-01-01T00:00:00Z'
+ date: "2021-01-01T00:00:00Z"
total: 100
trigger:
id: 0040fe51-6bce-4b44-b0ad-bddc4e123534
@@ -1784,24 +1784,24 @@ paths:
points: 10
metricName: words written
metricThreshold: 1000
- '401':
- description: 'Unauthorized'
+ "401":
+ description: "Unauthorized"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '404':
- description: 'Not Found'
+ $ref: "#/components/schemas/ErrorBody"
+ "404":
+ description: "Not Found"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '422':
- description: 'Unprocessible Entity'
+ $ref: "#/components/schemas/ErrorBody"
+ "422":
+ description: "Unprocessible Entity"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
+ $ref: "#/components/schemas/ErrorBody"
summary: Get a user's points data
security:
- ApiKeyAuth: []
@@ -1875,7 +1875,7 @@ paths:
schema:
type: string
format: date
- example: '2024-01-01'
+ example: "2024-01-01"
- name: endDate
in: query
description: The end date for the data range in YYYY-MM-DD format. The endDate must be after the startDate, and the date range must not exceed 400 days.
@@ -1883,9 +1883,9 @@ paths:
schema:
type: string
format: date
- example: '2024-01-31'
+ example: "2024-01-31"
responses:
- '200':
+ "200":
description: Successful operation
content:
application/json:
@@ -1898,7 +1898,7 @@ paths:
type: string
format: date
description: The date of the data point. For weekly or monthly aggregations, this is the first date of the period.
- example: '2024-01-01'
+ example: "2024-01-01"
total:
type: number
format: double
@@ -1916,33 +1916,33 @@ paths:
examples:
Successful operation:
value:
- - date: '2024-01-01'
+ - date: "2024-01-01"
total: 100
change: 100
- - date: '2024-01-02'
+ - date: "2024-01-02"
total: 300
change: 200
- - date: '2024-01-03'
+ - date: "2024-01-03"
total: 600
change: 300
- '401':
- description: 'Unauthorized'
+ "401":
+ description: "Unauthorized"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '404':
- description: 'Not Found'
+ $ref: "#/components/schemas/ErrorBody"
+ "404":
+ description: "Not Found"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '422':
- description: 'Unprocessible Entity'
+ $ref: "#/components/schemas/ErrorBody"
+ "422":
+ description: "Unprocessible Entity"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
+ $ref: "#/components/schemas/ErrorBody"
summary: Get a summary of points events over time
security:
- ApiKeyAuth: []
@@ -2001,7 +2001,7 @@ paths:
schema:
type: string
format: date
- example: '2025-01-15'
+ example: "2025-01-15"
- name: numEvents
in: query
description: The number of events to return in the history array.
@@ -2013,12 +2013,12 @@ paths:
maximum: 100
example: 10
responses:
- '200':
+ "200":
description: Successful operation
content:
application/json:
schema:
- $ref: '#/components/schemas/UserLeaderboardResponseWithHistory'
+ $ref: "#/components/schemas/UserLeaderboardResponseWithHistory"
examples:
Successful operation:
value:
@@ -2029,7 +2029,7 @@ paths:
metricKey: words-written
metricName: Words Written
description: Compete weekly to see who writes the most words
- start: '2025-01-01'
+ start: "2025-01-01"
end: null
maxParticipants: 100
breakdownAttribute: null
@@ -2038,39 +2038,39 @@ paths:
rank: 2
value: 4500
history:
- - timestamp: '2025-01-15T10:30:00Z'
+ - timestamp: "2025-01-15T10:30:00Z"
previousRank: null
rank: 5
previousValue: null
value: 1000
- - timestamp: '2025-01-15T14:15:00Z'
+ - timestamp: "2025-01-15T14:15:00Z"
previousRank: 5
rank: 3
previousValue: 1000
value: 3000
- - timestamp: '2025-01-15T18:45:00Z'
+ - timestamp: "2025-01-15T18:45:00Z"
previousRank: 3
rank: 2
previousValue: 3000
value: 4500
- '401':
- description: 'Unauthorized'
+ "401":
+ description: "Unauthorized"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '404':
- description: 'User or leaderboard not found'
+ $ref: "#/components/schemas/ErrorBody"
+ "404":
+ description: "User or leaderboard not found"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '422':
- description: 'Unprocessible Entity'
+ $ref: "#/components/schemas/ErrorBody"
+ "422":
+ description: "Unprocessible Entity"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
+ $ref: "#/components/schemas/ErrorBody"
summary: Get a user's leaderboard data
security:
- ApiKeyAuth: []
@@ -2120,12 +2120,12 @@ paths:
minimum: 1
example: 2024
responses:
- '200':
+ "200":
description: Successful operation
content:
application/json:
schema:
- $ref: '#/components/schemas/WrappedResponse'
+ $ref: "#/components/schemas/WrappedResponse"
examples:
Successful operation:
value:
@@ -2135,8 +2135,8 @@ paths:
name: John Doe
tz: America/New_York
subscribeToEmails: true
- created: '2024-01-15T10:30:00Z'
- updated: '2024-06-20T14:45:00Z'
+ created: "2024-01-15T10:30:00Z"
+ updated: "2024-06-20T14:45:00Z"
control: false
attributes:
plan-type: premium
@@ -2146,7 +2146,7 @@ paths:
weeksActive: 42
monthsActive: 11
mostActiveDay:
- date: '2024-03-15'
+ date: "2024-03-15"
metrics:
words-written:
name: Words Written
@@ -2172,7 +2172,7 @@ paths:
metricId: metric-123
metricValue: 500
metricName: Words Written
- achievedAt: '2024-03-15T14:30:00Z'
+ achievedAt: "2024-03-15T14:30:00Z"
completions: 150
rarity: 15
leaderboards:
@@ -2184,16 +2184,16 @@ paths:
metricKey: words-written
metricName: Words Written
description: Weekly writing competition
- start: '2024-03-11'
- end: '2024-03-17'
+ start: "2024-03-11"
+ end: "2024-03-17"
maxParticipants: 100
runUnit: day
runInterval: 7
rank: 3
value: 2500
mostActiveWeek:
- start: '2024-03-11'
- end: '2024-03-17'
+ start: "2024-03-11"
+ end: "2024-03-17"
metrics:
words-written:
name: Words Written
@@ -2262,34 +2262,34 @@ paths:
metricId: metric-123
metricValue: 500
metricName: Words Written
- achievedAt: '2024-03-15T14:30:00Z'
+ achievedAt: "2024-03-15T14:30:00Z"
completions: 150
rarity: 15
leaderboards: {}
longestStreak:
length: 45
frequency: daily
- periodStart: '2024-02-01'
- periodEnd: '2024-03-17'
- started: '2024-02-01'
- '401':
- description: 'Unauthorized'
+ periodStart: "2024-02-01"
+ periodEnd: "2024-03-17"
+ started: "2024-02-01"
+ "401":
+ description: "Unauthorized"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '404':
- description: 'User not found'
+ $ref: "#/components/schemas/ErrorBody"
+ "404":
+ description: "User not found"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '422':
- description: 'Unprocessible Entity'
+ $ref: "#/components/schemas/ErrorBody"
+ "422":
+ description: "Unprocessible Entity"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
+ $ref: "#/components/schemas/ErrorBody"
summary: Get a user's wrapped data
security:
- ApiKeyAuth: []
@@ -2341,12 +2341,12 @@ paths:
type: string
example: plan-type:premium,region:us-east
responses:
- '200':
+ "200":
description: Successful operation
content:
application/json:
schema:
- $ref: '#/components/schemas/PointsSummaryResponse'
+ $ref: "#/components/schemas/PointsSummaryResponse"
examples:
Successful operation:
value:
@@ -2383,24 +2383,24 @@ paths:
- from: 901
to: 1000
users: 0
- '401':
- description: 'Unauthorized'
+ "401":
+ description: "Unauthorized"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '404':
- description: 'Not Found'
+ $ref: "#/components/schemas/ErrorBody"
+ "404":
+ description: "Not Found"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '422':
- description: 'Unprocessible Entity'
+ $ref: "#/components/schemas/ErrorBody"
+ "422":
+ description: "Unprocessible Entity"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
+ $ref: "#/components/schemas/ErrorBody"
summary: Get a breakdown of users by points
security:
- ApiKeyAuth: []
@@ -2440,12 +2440,12 @@ paths:
type: string
example: points-system-key
responses:
- '200':
+ "200":
description: Successful operation
content:
application/json:
schema:
- $ref: '#/components/schemas/PointsSystemResponse'
+ $ref: "#/components/schemas/PointsSystemResponse"
examples:
Successful operation:
value:
@@ -2470,15 +2470,15 @@ paths:
eventAttribute:
key: source
value: mobile-app
- created: '2021-01-01T00:00:00Z'
- updated: '2021-01-01T00:00:00Z'
+ created: "2021-01-01T00:00:00Z"
+ updated: "2021-01-01T00:00:00Z"
- id: 0040fe51-6bce-4b44-b0ad-bddc4e123536
type: streak
points: 10
status: active
streakLengthThreshold: 7
- created: '2021-01-01T00:00:00Z'
- updated: '2021-01-01T00:00:00Z'
+ created: "2021-01-01T00:00:00Z"
+ updated: "2021-01-01T00:00:00Z"
- id: 0040fe51-6bce-4b44-b0ad-bddc4e123535
type: achievement
points: 50
@@ -2488,20 +2488,20 @@ paths:
userAttributes:
- key: plan-type
value: premium
- created: '2021-01-01T00:00:00Z'
- updated: '2021-01-01T00:00:00Z'
- '401':
- description: 'Unauthorized'
+ created: "2021-01-01T00:00:00Z"
+ updated: "2021-01-01T00:00:00Z"
+ "401":
+ description: "Unauthorized"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '404':
- description: 'Points system not found'
+ $ref: "#/components/schemas/ErrorBody"
+ "404":
+ description: "Points system not found"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
+ $ref: "#/components/schemas/ErrorBody"
summary: Get a points system with its triggers
security:
- ApiKeyAuth: []
@@ -2533,7 +2533,7 @@ paths:
response = client.leaderboards.all()
responses:
- '200':
+ "200":
description: Successful operation
content:
application/json:
@@ -2541,12 +2541,12 @@ paths:
type: array
items:
allOf:
- - $ref: '#/components/schemas/LeaderboardResponse'
+ - $ref: "#/components/schemas/LeaderboardResponse"
- type: object
properties:
status:
type: string
- enum: ['active', 'scheduled', 'finished']
+ enum: ["active", "scheduled", "finished"]
description: The status of the leaderboard.
example: active
required:
@@ -2562,7 +2562,7 @@ paths:
metricName: Words Written
description: Compete weekly to see who writes the most words
status: active
- start: '2025-01-01'
+ start: "2025-01-01"
end: null
maxParticipants: 100
breakdownAttribute: null
@@ -2576,24 +2576,24 @@ paths:
pointsSystemName: Experience Points
description: Overall ranking by XP earned
status: active
- start: '2025-01-01'
+ start: "2025-01-01"
end: null
maxParticipants: 50
breakdownAttribute: null
runUnit: null
runInterval: null
- '401':
- description: 'Unauthorized'
+ "401":
+ description: "Unauthorized"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '422':
- description: 'Unprocessible Entity'
+ $ref: "#/components/schemas/ErrorBody"
+ "422":
+ description: "Unprocessible Entity"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
+ $ref: "#/components/schemas/ErrorBody"
summary: Get all active leaderboards
security:
- ApiKeyAuth: []
@@ -2697,14 +2697,14 @@ paths:
schema:
type: string
format: date
- example: '2025-01-15'
+ example: "2025-01-15"
- name: userId
in: query
description: When provided, offset is relative to this user's position on the leaderboard. If the user is not found in the leaderboard, returns empty rankings array.
required: false
schema:
type: string
- example: 'user-123'
+ example: "user-123"
- name: userAttributes
in: query
description: Attribute key and value to filter the rankings by, separated by a colon. For example, `city:London`. This parameter is required, and only valid for leaderboards with a breakdown attribute.
@@ -2713,12 +2713,12 @@ paths:
type: string
example: city:London
responses:
- '200':
+ "200":
description: Successful operation
content:
application/json:
schema:
- $ref: '#/components/schemas/LeaderboardResponseWithRankings'
+ $ref: "#/components/schemas/LeaderboardResponseWithRankings"
examples:
Successful operation:
value:
@@ -2732,7 +2732,7 @@ paths:
pointsSystemName: null
description: Compete weekly to see who writes the most words
status: active
- start: '2025-01-01'
+ start: "2025-01-01"
end: null
maxParticipants: 100
breakdownAttribute: null
@@ -2751,24 +2751,24 @@ paths:
userName: Charlie Brown
rank: 3
value: 4200
- '401':
- description: 'Unauthorized'
+ "401":
+ description: "Unauthorized"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '404':
- description: 'Leaderboard not found'
+ $ref: "#/components/schemas/ErrorBody"
+ "404":
+ description: "Leaderboard not found"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '422':
- description: 'Unprocessible Entity'
+ $ref: "#/components/schemas/ErrorBody"
+ "422":
+ description: "Unprocessible Entity"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
+ $ref: "#/components/schemas/ErrorBody"
summary: Get a single leaderboard
security:
- ApiKeyAuth: []
@@ -2823,7 +2823,7 @@ paths:
content:
application/json:
schema:
- $ref: '#/components/schemas/CreateStreakFreezesRequest'
+ $ref: "#/components/schemas/CreateStreakFreezesRequest"
examples:
Create freezes for multiple users:
value:
@@ -2832,12 +2832,12 @@ paths:
- userId: user-456
- userId: user-123
responses:
- '200':
+ "200":
description: Successful operation
content:
application/json:
schema:
- $ref: '#/components/schemas/CreateStreakFreezesResponse'
+ $ref: "#/components/schemas/CreateStreakFreezesResponse"
examples:
Success with no issues:
value:
@@ -2857,24 +2857,24 @@ paths:
- userId: user-456
level: warning
reason: Would exceed maximum freeze limit
- '400':
- description: 'Bad Request'
+ "400":
+ description: "Bad Request"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '401':
- description: 'Unauthorized'
+ $ref: "#/components/schemas/ErrorBody"
+ "401":
+ description: "Unauthorized"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '422':
- description: 'Unprocessible Entity'
+ $ref: "#/components/schemas/ErrorBody"
+ "422":
+ description: "Unprocessible Entity"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
+ $ref: "#/components/schemas/ErrorBody"
summary: Create streak freezes for multiple users
security:
- ApiKeyAuth: []
@@ -2920,7 +2920,7 @@ paths:
content:
application/json:
schema:
- $ref: '#/components/schemas/RestoreStreaksRequest'
+ $ref: "#/components/schemas/RestoreStreaksRequest"
examples:
Restore streaks for multiple users:
value:
@@ -2928,12 +2928,12 @@ paths:
- id: user-123
- id: user-456
responses:
- '200':
+ "200":
description: Successful operation
content:
application/json:
schema:
- $ref: '#/components/schemas/RestoreStreaksResponse'
+ $ref: "#/components/schemas/RestoreStreaksResponse"
examples:
Success with no issues:
value:
@@ -2960,24 +2960,24 @@ paths:
- userId: user-789
level: warning
reason: Streak is already at maximum length
- '400':
- description: 'Bad Request'
+ "400":
+ description: "Bad Request"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '401':
- description: 'Unauthorized'
+ $ref: "#/components/schemas/ErrorBody"
+ "401":
+ description: "Unauthorized"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
- '422':
- description: 'Unprocessible Entity'
+ $ref: "#/components/schemas/ErrorBody"
+ "422":
+ description: "Unprocessible Entity"
content:
application/json:
schema:
- $ref: '#/components/schemas/ErrorBody'
+ $ref: "#/components/schemas/ErrorBody"
summary: Restore streaks for multiple users
security:
- ApiKeyAuth: []
@@ -2995,13 +2995,13 @@ webhooks:
properties:
type:
type: string
- enum: ['achievement.completed']
+ enum: ["achievement.completed"]
description: The webhook event type.
user:
- $ref: '#/components/schemas/User'
+ $ref: "#/components/schemas/User"
description: The user who completed the achievement.
achievement:
- $ref: '#/components/schemas/UserAchievementResponse'
+ $ref: "#/components/schemas/UserAchievementResponse"
description: The achievement completion that occurred.
required:
- type
@@ -3016,8 +3016,8 @@ webhooks:
email: user@example.com
tz: Europe/London
subscribedToEmails: true
- created: '2021-01-01T00:00:00Z'
- updated: '2021-01-01T00:00:00Z'
+ created: "2021-01-01T00:00:00Z"
+ updated: "2021-01-01T00:00:00Z"
attributes:
department: engineering
role: developer
@@ -3027,11 +3027,11 @@ webhooks:
trigger: api
description: null
key: completed-onboarding
- achievedAt: '2021-01-01T00:00:00Z'
+ achievedAt: "2021-01-01T00:00:00Z"
badgeUrl: https://example.com/badge2.png
responses:
- '200':
+ "200":
description: Return a 200 status to indicate the webhook was received and processed.
streak.started:
post:
@@ -3046,13 +3046,13 @@ webhooks:
properties:
type:
type: string
- enum: ['streak.started']
+ enum: ["streak.started"]
description: The webhook event type.
user:
- $ref: '#/components/schemas/User'
+ $ref: "#/components/schemas/User"
description: The user who started the streak.
streak:
- $ref: '#/components/schemas/BaseStreakResponse'
+ $ref: "#/components/schemas/BaseStreakResponse"
description: The streak that was started.
required:
- type
@@ -3067,24 +3067,24 @@ webhooks:
email: user@example.com
tz: Europe/London
subscribedToEmails: true
- created: '2021-01-01T00:00:00Z'
- updated: '2021-01-01T00:00:00Z'
+ created: "2021-01-01T00:00:00Z"
+ updated: "2021-01-01T00:00:00Z"
attributes:
department: engineering
role: developer
streak:
length: 1
frequency: daily
- periodStart: '2025-04-02'
- periodEnd: '2025-04-02'
- started: '2025-04-02'
- expires: '2025-04-03'
+ periodStart: "2025-04-02"
+ periodEnd: "2025-04-02"
+ started: "2025-04-02"
+ expires: "2025-04-03"
freezes: 0
maxFreezes: 3
freezeAutoEarnInterval: 7
freezeAutoEarnAmount: 1
responses:
- '200':
+ "200":
description: Return a 200 status to indicate the webhook was received and processed.
streak.extended:
post:
@@ -3099,13 +3099,13 @@ webhooks:
properties:
type:
type: string
- enum: ['streak.extended']
+ enum: ["streak.extended"]
description: The webhook event type.
user:
- $ref: '#/components/schemas/User'
+ $ref: "#/components/schemas/User"
description: The user who extended the streak.
streak:
- $ref: '#/components/schemas/BaseStreakResponse'
+ $ref: "#/components/schemas/BaseStreakResponse"
description: The streak that was extended.
required:
- type
@@ -3120,24 +3120,24 @@ webhooks:
email: user@example.com
tz: Europe/London
subscribedToEmails: true
- created: '2021-01-01T00:00:00Z'
- updated: '2021-01-01T00:00:00Z'
+ created: "2021-01-01T00:00:00Z"
+ updated: "2021-01-01T00:00:00Z"
attributes:
department: engineering
role: developer
streak:
length: 2
frequency: daily
- periodStart: '2025-04-03'
- periodEnd: '2025-04-03'
- started: '2025-04-02'
- expires: '2025-04-05'
+ periodStart: "2025-04-03"
+ periodEnd: "2025-04-03"
+ started: "2025-04-02"
+ expires: "2025-04-05"
freezes: 0
maxFreezes: 3
freezeAutoEarnInterval: 7
freezeAutoEarnAmount: 1
responses:
- '200':
+ "200":
description: Return a 200 status to indicate the webhook was received and processed.
streak.lost:
post:
@@ -3152,10 +3152,10 @@ webhooks:
properties:
type:
type: string
- enum: ['streak.lost']
+ enum: ["streak.lost"]
description: The webhook event type.
user:
- $ref: '#/components/schemas/User'
+ $ref: "#/components/schemas/User"
description: The user who lost the streak.
length:
type: integer
@@ -3173,14 +3173,14 @@ webhooks:
email: user@example.com
tz: Europe/London
subscribedToEmails: true
- created: '2021-01-01T00:00:00Z'
- updated: '2021-01-01T00:00:00Z'
+ created: "2021-01-01T00:00:00Z"
+ updated: "2021-01-01T00:00:00Z"
attributes:
department: engineering
role: developer
length: 7
responses:
- '200':
+ "200":
description: Return a 200 status to indicate the webhook was received and processed.
streak.freeze_consumed:
post:
@@ -3195,10 +3195,10 @@ webhooks:
properties:
type:
type: string
- enum: ['streak.freeze_consumed']
+ enum: ["streak.freeze_consumed"]
description: The webhook event type.
user:
- $ref: '#/components/schemas/User'
+ $ref: "#/components/schemas/User"
description: The user whose streak freeze was consumed.
consumed:
type: integer
@@ -3220,15 +3220,15 @@ webhooks:
email: user@example.com
tz: Europe/London
subscribedToEmails: true
- created: '2021-01-01T00:00:00Z'
- updated: '2021-01-01T00:00:00Z'
+ created: "2021-01-01T00:00:00Z"
+ updated: "2021-01-01T00:00:00Z"
attributes:
department: engineering
role: developer
consumed: 1
freezes: 2
responses:
- '200':
+ "200":
description: Return a 200 status to indicate the webhook was received and processed.
streak.freeze_earned:
post:
@@ -3243,10 +3243,10 @@ webhooks:
properties:
type:
type: string
- enum: ['streak.freeze_earned']
+ enum: ["streak.freeze_earned"]
description: The webhook event type.
user:
- $ref: '#/components/schemas/User'
+ $ref: "#/components/schemas/User"
description: The user who earned streak freezes.
earned:
type: integer
@@ -3268,15 +3268,15 @@ webhooks:
email: user@example.com
tz: Europe/London
subscribedToEmails: true
- created: '2021-01-01T00:00:00Z'
- updated: '2021-01-01T00:00:00Z'
+ created: "2021-01-01T00:00:00Z"
+ updated: "2021-01-01T00:00:00Z"
attributes:
department: engineering
role: developer
earned: 1
freezes: 2
responses:
- '200':
+ "200":
description: Return a 200 status to indicate the webhook was received and processed.
points.changed:
post:
@@ -3291,13 +3291,13 @@ webhooks:
properties:
type:
type: string
- enum: ['points.changed']
+ enum: ["points.changed"]
description: The webhook event type.
user:
- $ref: '#/components/schemas/User'
+ $ref: "#/components/schemas/User"
description: The user whose points increased or decreased.
points:
- $ref: '#/components/schemas/GetUserPointsResponse'
+ $ref: "#/components/schemas/GetUserPointsResponse"
description: The user's points after the event.
required:
- type
@@ -3312,8 +3312,8 @@ webhooks:
email: user@example.com
tz: Europe/London
subscribedToEmails: true
- created: '2021-01-01T00:00:00Z'
- updated: '2021-01-01T00:00:00Z'
+ created: "2021-01-01T00:00:00Z"
+ updated: "2021-01-01T00:00:00Z"
attributes:
department: engineering
role: developer
@@ -3328,7 +3328,7 @@ webhooks:
awards:
- id: 0040fe51-6bce-4b44-b0ad-bddc4e123534
awarded: 10
- date: '2021-01-01T00:00:00Z'
+ date: "2021-01-01T00:00:00Z"
total: 100
trigger:
id: 0040fe51-6bce-4b44-b0ad-bddc4e123534
@@ -3337,7 +3337,7 @@ webhooks:
metricName: words written
metricThreshold: 1000
responses:
- '200':
+ "200":
description: Return a 200 status to indicate the webhook was received and processed.
leaderboard.started:
post:
@@ -3352,10 +3352,10 @@ webhooks:
properties:
type:
type: string
- enum: ['leaderboard.started']
+ enum: ["leaderboard.started"]
description: The webhook event type.
leaderboard:
- $ref: '#/components/schemas/LeaderboardResponseWithRankings'
+ $ref: "#/components/schemas/LeaderboardResponseWithRankings"
description: The leaderboard run that started and its initial rankings.
required:
- type
@@ -3375,7 +3375,7 @@ webhooks:
pointsSystemName: null
description: Compete weekly to see who writes the most words
status: active
- start: '2025-01-01'
+ start: "2025-01-01"
end: null
maxParticipants: 100
breakdownAttribute: null
@@ -3387,7 +3387,7 @@ webhooks:
rank: 1
value: 1
responses:
- '200':
+ "200":
description: Return a 200 status to indicate the webhook was received and processed.
leaderboard.changed:
post:
@@ -3402,10 +3402,10 @@ webhooks:
properties:
type:
type: string
- enum: ['leaderboard.changed']
+ enum: ["leaderboard.changed"]
description: The webhook event type.
leaderboard:
- $ref: '#/components/schemas/LeaderboardResponseWithRankings'
+ $ref: "#/components/schemas/LeaderboardResponseWithRankings"
description: The leaderboard run that changed.
required:
- type
@@ -3425,7 +3425,7 @@ webhooks:
pointsSystemName: null
description: Compete weekly to see who writes the most words
status: active
- start: '2025-01-01'
+ start: "2025-01-01"
end: null
maxParticipants: 100
breakdownAttribute: null
@@ -3445,7 +3445,7 @@ webhooks:
rank: 3
value: 4
responses:
- '200':
+ "200":
description: Return a 200 status to indicate the webhook was received and processed.
leaderboard.finished:
post:
@@ -3460,10 +3460,10 @@ webhooks:
properties:
type:
type: string
- enum: ['leaderboard.finished']
+ enum: ["leaderboard.finished"]
description: The webhook event type.
leaderboard:
- $ref: '#/components/schemas/LeaderboardResponseWithRankings'
+ $ref: "#/components/schemas/LeaderboardResponseWithRankings"
description: The leaderboard run that finished and its final rankings.
required:
- type
@@ -3483,7 +3483,7 @@ webhooks:
pointsSystemName: null
description: Compete weekly to see who writes the most words
status: active
- start: '2025-01-01'
+ start: "2025-01-01"
end: null
maxParticipants: 100
breakdownAttribute: null
@@ -3503,7 +3503,7 @@ webhooks:
rank: 3
value: 4
responses:
- '200':
+ "200":
description: Return a 200 status to indicate the webhook was received and processed.
leaderboard.rank_changed:
post:
@@ -3518,13 +3518,13 @@ webhooks:
properties:
type:
type: string
- enum: ['leaderboard.rank_changed']
+ enum: ["leaderboard.rank_changed"]
description: The webhook event type.
user:
- $ref: '#/components/schemas/User'
+ $ref: "#/components/schemas/User"
description: The user whose rank changed.
leaderboard:
- $ref: '#/components/schemas/WebhookUserLeaderboardResponse'
+ $ref: "#/components/schemas/WebhookUserLeaderboardResponse"
description: The user's leaderboard data that changed.
required:
- type
@@ -3539,8 +3539,8 @@ webhooks:
email: user@example.com
tz: Europe/London
subscribedToEmails: true
- created: '2021-01-01T00:00:00Z'
- updated: '2021-01-01T00:00:00Z'
+ created: "2021-01-01T00:00:00Z"
+ updated: "2021-01-01T00:00:00Z"
attributes:
department: engineering
role: developer
@@ -3552,7 +3552,7 @@ webhooks:
metricKey: words-written
metricName: Words Written
description: Compete weekly to see who writes the most words
- start: '2025-01-01'
+ start: "2025-01-01"
end: null
maxParticipants: 100
breakdownAttribute: null
@@ -3563,7 +3563,7 @@ webhooks:
previousRank: 1
previousValue: 4500
responses:
- '200':
+ "200":
description: Return a 200 status to indicate the webhook was received and processed.
components:
schemas:
@@ -3589,30 +3589,30 @@ components:
type: integer
description: The length of the user's current streak.
frequency:
- $ref: '#/components/schemas/StreakFrequency'
+ $ref: "#/components/schemas/StreakFrequency"
description: The frequency of the streak.
started:
type:
- string
- - 'null'
+ - "null"
format: date
description: The date the streak started.
periodStart:
type:
- string
- - 'null'
+ - "null"
format: date
description: The start date of the current streak period.
periodEnd:
type:
- string
- - 'null'
+ - "null"
format: date
description: The end date of the current streak period.
expires:
type:
- string
- - 'null'
+ - "null"
format: date
description: The date the streak will expire if the user does not increment a metric.
freezes:
@@ -3648,7 +3648,7 @@ components:
extended:
type:
- string
- - 'null'
+ - "null"
description: The timestamp the streak was extended, as a string. Null if the streak is not active.
required:
- userId
@@ -3659,7 +3659,7 @@ components:
type: object
description: An object representing the user's streak after sending a metric event.
allOf:
- - $ref: '#/components/schemas/BaseStreakResponse'
+ - $ref: "#/components/schemas/BaseStreakResponse"
- type: object
properties:
extended:
@@ -3672,7 +3672,7 @@ components:
type: object
description: An object representing the user's streak.
allOf:
- - $ref: '#/components/schemas/BaseStreakResponse'
+ - $ref: "#/components/schemas/BaseStreakResponse"
- type: object
properties:
streakHistory:
@@ -3689,12 +3689,12 @@ components:
type: string
format: date
description: The date this streak period started.
- example: '2025-03-31'
+ example: "2025-03-31"
periodEnd:
type: string
format: date
description: The date this streak period ended.
- example: '2025-04-05'
+ example: "2025-04-05"
length:
type: integer
description: The length of the user's streak during this period.
@@ -3710,7 +3710,7 @@ components:
rank:
type:
- integer
- - 'null'
+ - "null"
description: The user's rank across all users. Null if the user has no active streak.
example: 5
required:
@@ -3725,7 +3725,7 @@ components:
type:
type: string
description: The type of trigger
- enum: ['metric', 'achievement', 'streak', 'time', 'user_creation']
+ enum: ["metric", "achievement", "streak", "time", "user_creation"]
points:
type: integer
description: The points awarded by this trigger.
@@ -3743,7 +3743,7 @@ components:
description: If the trigger has type 'achievement', the name of the achievement
timeUnit:
type: string
- enum: ['hour', 'day']
+ enum: ["hour", "day"]
description: If the trigger has type 'time', the unit of time after which to award points
timeInterval:
type: integer
@@ -3765,7 +3765,7 @@ components:
type: integer
description: The user's total points after this award occurred.
trigger:
- $ref: '#/components/schemas/PointsTrigger'
+ $ref: "#/components/schemas/PointsTrigger"
GetUserPointsResponse:
title: GetUserPointsResponse
type: object
@@ -3782,17 +3782,17 @@ components:
description:
type:
- string
- - 'null'
+ - "null"
description: The description of the points system
badgeUrl:
type:
- string
- - 'null'
+ - "null"
description: The URL of the badge image for the points system
maxPoints:
type:
- number
- - 'null'
+ - "null"
description: The maximum number of points a user can be awarded in this points system
total:
type: integer
@@ -3801,7 +3801,7 @@ components:
type: array
description: Array of trigger awards that added points.
items:
- $ref: '#/components/schemas/PointsAward'
+ $ref: "#/components/schemas/PointsAward"
required:
- id
- key
@@ -3830,13 +3830,13 @@ components:
example: weekly-words
rankBy:
type: string
- enum: ['points', 'streak', 'metric']
+ enum: ["points", "streak", "metric"]
description: What the leaderboard ranks by.
example: metric
breakdownAttribute:
type:
- string
- - 'null'
+ - "null"
description: The key of the attribute to break down this leaderboard by.
example: country
metricKey:
@@ -3858,21 +3858,21 @@ components:
description:
type:
- string
- - 'null'
+ - "null"
description: The user-facing description of the leaderboard.
example: Compete weekly to see who writes the most words
start:
type: string
format: date
description: The start date of the leaderboard in YYYY-MM-DD format.
- example: '2025-01-01'
+ example: "2025-01-01"
end:
type:
- string
- - 'null'
+ - "null"
format: date
description: The end date of the leaderboard in YYYY-MM-DD format, or null if it runs forever.
- example: '2025-12-31'
+ example: "2025-12-31"
maxParticipants:
type: integer
description: The maximum number of participants in the leaderboard.
@@ -3880,14 +3880,14 @@ components:
runUnit:
type:
- string
- - 'null'
- enum: ['day', 'month', 'year', null]
+ - "null"
+ enum: ["day", "month", "year", null]
description: The repetition type for recurring leaderboards, or null for one-time leaderboards.
example: day
runInterval:
type:
- integer
- - 'null'
+ - "null"
description: The interval between repetitions, relative to the start date and repetition type. Null for one-time leaderboards.
example: 7
required:
@@ -3907,19 +3907,19 @@ components:
title: LeaderboardResponseWithRankings
type: object
allOf:
- - $ref: '#/components/schemas/LeaderboardResponse'
+ - $ref: "#/components/schemas/LeaderboardResponse"
- type: object
properties:
status:
type: string
- enum: ['active', 'scheduled', 'finished']
+ enum: ["active", "scheduled", "finished"]
description: The status of the leaderboard.
example: active
rankings:
type: array
description: Array of user rankings for the leaderboard.
items:
- $ref: '#/components/schemas/LeaderboardRanking'
+ $ref: "#/components/schemas/LeaderboardRanking"
required:
- rankings
- status
@@ -3927,7 +3927,7 @@ components:
title: MetricEventPointsResponse
type: object
allOf:
- - $ref: '#/components/schemas/GetUserPointsResponse'
+ - $ref: "#/components/schemas/GetUserPointsResponse"
- type: object
properties:
added:
@@ -3940,31 +3940,31 @@ components:
title: MetricEventLeaderboardResponse
type: object
allOf:
- - $ref: '#/components/schemas/LeaderboardResponse'
+ - $ref: "#/components/schemas/LeaderboardResponse"
- type: object
properties:
start:
type: string
format: date
description: The start date of the current run of the leaderboard.
- example: '2025-01-01'
+ example: "2025-01-01"
end:
type:
- string
- - 'null'
+ - "null"
format: date
description: The end date of the current run of the leaderboard, or null if the run never ends.
- example: '2025-12-31'
+ example: "2025-12-31"
rank:
type:
- integer
- - 'null'
+ - "null"
description: The user's rank in the leaderboard, or null if the user is not on the leaderboard.
example: 100
previousRank:
type:
- integer
- - 'null'
+ - "null"
description: The user's rank in the leaderboard before the event, or null if the user was not on the leaderboard before the event.
example: 100
threshold:
@@ -3993,17 +3993,17 @@ components:
description: The name of this achievement.
trigger:
type: string
- enum: ['metric', 'streak', 'api']
+ enum: ["metric", "streak", "api"]
description: The trigger of the achievement.
description:
type:
- string
- - 'null'
+ - "null"
description: The description of this achievement.
badgeUrl:
type:
- string
- - 'null'
+ - "null"
description: >-
The URL of the badge image for the achievement, if one has been
uploaded.
@@ -4066,13 +4066,13 @@ components:
title: UserAchievementResponse
type: object
allOf:
- - $ref: '#/components/schemas/AchievementResponse'
+ - $ref: "#/components/schemas/AchievementResponse"
- type: object
properties:
achievedAt:
type:
- string
- - 'null'
+ - "null"
format: date-time
description: The date and time the achievement was completed, in ISO 8601 format. Null if the achievement has not been completed.
required:
@@ -4081,13 +4081,13 @@ components:
title: UserAchievementWithStatsResponse
type: object
allOf:
- - $ref: '#/components/schemas/AchievementWithStatsResponse'
+ - $ref: "#/components/schemas/AchievementWithStatsResponse"
- type: object
properties:
achievedAt:
type:
- string
- - 'null'
+ - "null"
format: date-time
description: The date and time the achievement was completed, in ISO 8601 format. Null if the achievement has not been completed.
required:
@@ -4096,7 +4096,7 @@ components:
title: AchievementWithStatsResponse
type: object
allOf:
- - $ref: '#/components/schemas/AchievementResponse'
+ - $ref: "#/components/schemas/AchievementResponse"
- type: object
properties:
completions:
@@ -4126,7 +4126,7 @@ components:
description: The name of the metric.
example: Words written
status:
- $ref: '#/components/schemas/MetricStatus'
+ $ref: "#/components/schemas/MetricStatus"
description: The status of the metric.
current:
type: number
@@ -4136,7 +4136,7 @@ components:
achievements:
type: array
items:
- $ref: '#/components/schemas/UserAchievementResponse'
+ $ref: "#/components/schemas/UserAchievementResponse"
description: >-
A list of the metric's achievements and the user's progress towards
each.
@@ -4163,18 +4163,18 @@ components:
tz:
type:
- string
- - 'null'
+ - "null"
description: The user's timezone (used for email scheduling).
example: Europe/London
deviceTokens:
type:
- array
- - 'null'
+ - "null"
description: The user's device tokens, used for push notifications.
items:
type: string
description: The device token.
- example: ['token1', 'token2']
+ example: ["token1", "token2"]
subscribeToEmails:
type: boolean
default: true
@@ -4193,7 +4193,7 @@ components:
type: object
description: An object with editable user fields.
allOf:
- - $ref: '#/components/schemas/UpdatedUser'
+ - $ref: "#/components/schemas/UpdatedUser"
- type: object
properties:
id:
@@ -4214,30 +4214,30 @@ components:
email:
type:
- string
- - 'null'
+ - "null"
description: The user's email address.
example: user@example.com
name:
type:
- string
- - 'null'
+ - "null"
description: The name of the user.
example: John Doe
tz:
type:
- string
- - 'null'
+ - "null"
description: The user's timezone.
example: Europe/London
deviceTokens:
type:
- array
- - 'null'
+ - "null"
description: The user's device tokens.
items:
type: string
description: The device token.
- example: ['token1', 'token2']
+ example: ["token1", "token2"]
subscribeToEmails:
type: boolean
description: Whether the user is opted into receiving Trophy-powered emails.
@@ -4258,12 +4258,12 @@ components:
type: string
format: date-time
description: The date and time the user was created, in ISO 8601 format.
- example: '2021-01-01T00:00:00Z'
+ example: "2021-01-01T00:00:00Z"
updated:
type: string
format: date-time
description: The date and time the user was last updated, in ISO 8601 format.
- example: '2021-01-01T00:00:00Z'
+ example: "2021-01-01T00:00:00Z"
required:
- id
- email
@@ -4298,22 +4298,22 @@ components:
achievement_completed:
type: array
items:
- $ref: '#/components/schemas/NotificationChannel'
+ $ref: "#/components/schemas/NotificationChannel"
description: Channels to receive achievement completion notifications on.
recap:
type: array
items:
- $ref: '#/components/schemas/NotificationChannel'
+ $ref: "#/components/schemas/NotificationChannel"
description: Channels to receive recap notifications on.
reactivation:
type: array
items:
- $ref: '#/components/schemas/NotificationChannel'
+ $ref: "#/components/schemas/NotificationChannel"
description: Channels to receive reactivation notifications on.
streak_reminder:
type: array
items:
- $ref: '#/components/schemas/NotificationChannel'
+ $ref: "#/components/schemas/NotificationChannel"
description: Channels to receive streak reminder notifications on.
UserPreferencesResponse:
title: UserPreferencesResponse
@@ -4321,7 +4321,7 @@ components:
description: A user's preferences.
properties:
notifications:
- $ref: '#/components/schemas/NotificationPreferences'
+ $ref: "#/components/schemas/NotificationPreferences"
required:
- notifications
UpdateUserPreferencesRequest:
@@ -4330,7 +4330,7 @@ components:
description: Request body for updating user preferences.
properties:
notifications:
- $ref: '#/components/schemas/NotificationPreferences'
+ $ref: "#/components/schemas/NotificationPreferences"
ErrorBody:
title: ErrorBody
type: object
@@ -4348,11 +4348,11 @@ components:
description: The unique ID of the completion.
example: 0040fe51-6bce-4b44-b0ad-bddc4e123534
achievement:
- $ref: '#/components/schemas/UserAchievementResponse'
+ $ref: "#/components/schemas/UserAchievementResponse"
points:
type: object
additionalProperties:
- $ref: '#/components/schemas/MetricEventPointsResponse'
+ $ref: "#/components/schemas/MetricEventPointsResponse"
description: >-
A map of points systems by key that were affected by this achievement completion.
required:
@@ -4379,22 +4379,22 @@ components:
achievements:
type: array
items:
- $ref: '#/components/schemas/UserAchievementResponse'
+ $ref: "#/components/schemas/UserAchievementResponse"
description: Achievements completed as a result of this event.
currentStreak:
- $ref: '#/components/schemas/MetricEventStreakResponse'
+ $ref: "#/components/schemas/MetricEventStreakResponse"
description: >-
The user's current streak.
points:
type: object
additionalProperties:
- $ref: '#/components/schemas/MetricEventPointsResponse'
+ $ref: "#/components/schemas/MetricEventPointsResponse"
description: >-
A map of points systems by key. Only contains points systems that were affected by the event.
leaderboards:
type: object
additionalProperties:
- $ref: '#/components/schemas/MetricEventLeaderboardResponse'
+ $ref: "#/components/schemas/MetricEventLeaderboardResponse"
description: >-
A map of leaderboards by key. Only contains leaderboards that were affected by the event.
idempotencyKey:
@@ -4437,7 +4437,7 @@ components:
to the greatest number of points a user has, rounded up to the nearest
power of 10.
items:
- $ref: '#/components/schemas/PointsRange'
+ $ref: "#/components/schemas/PointsRange"
PointsTriggerResponse:
title: PointsTriggerResponse
type: object
@@ -4447,14 +4447,14 @@ components:
description: The unique ID of the trigger.
type:
type: string
- enum: ['metric', 'achievement', 'streak', 'time', 'user_creation']
+ enum: ["metric", "achievement", "streak", "time", "user_creation"]
description: The type of trigger.
points:
type: integer
description: The points awarded by this trigger.
status:
type: string
- enum: ['active', 'archived']
+ enum: ["active", "archived"]
description: The status of the trigger.
achievementId:
type: string
@@ -4476,7 +4476,7 @@ components:
description: The name of the achievement associated with this trigger, if the trigger is an achievement.
timeUnit:
type: string
- enum: ['hour', 'day']
+ enum: ["hour", "day"]
description: The time unit of the trigger, if the trigger is a time interval.
timeInterval:
type: integer
@@ -4541,23 +4541,23 @@ components:
description:
type:
- string
- - 'null'
+ - "null"
description: The description of the points system.
badgeUrl:
type:
- string
- - 'null'
+ - "null"
description: The URL of the badge image for the points system, if one has been uploaded.
maxPoints:
type:
- number
- - 'null'
+ - "null"
description: The maximum number of points a user can be awarded in this points system
triggers:
type: array
description: Array of active triggers for this points system.
items:
- $ref: '#/components/schemas/PointsTriggerResponse'
+ $ref: "#/components/schemas/PointsTriggerResponse"
required:
- id
- name
@@ -4577,7 +4577,7 @@ components:
name:
type:
- string
- - 'null'
+ - "null"
description: The name of the user. May be null if no name is set.
example: Alice Johnson
streakLength:
@@ -4600,7 +4600,7 @@ components:
userName:
type:
- string
- - 'null'
+ - "null"
description: The name of the user. May be null if no name is set.
example: Alice Johnson
rank:
@@ -4625,29 +4625,29 @@ components:
type: string
format: date-time
description: The timestamp when the event occurred.
- example: '2025-01-15T10:30:00Z'
+ example: "2025-01-15T10:30:00Z"
previousRank:
type:
- integer
- - 'null'
+ - "null"
description: The user's rank before this event, or null if they were not on the leaderboard.
example: 5
rank:
type:
- integer
- - 'null'
+ - "null"
description: The user's rank after this event, or null if they are no longer on the leaderboard.
example: 3
previousValue:
type:
- integer
- - 'null'
+ - "null"
description: The user's value before this event, or null if they were not on the leaderboard.
example: 1000
value:
type:
- integer
- - 'null'
+ - "null"
description: The user's value after this event, or null if they are no longer on the leaderboard.
example: 3000
required:
@@ -4661,19 +4661,19 @@ components:
type: object
description: A user's data for a specific leaderboard including rank, value, and history.
allOf:
- - $ref: '#/components/schemas/LeaderboardResponse'
+ - $ref: "#/components/schemas/LeaderboardResponse"
- type: object
properties:
rank:
type:
- integer
- - 'null'
+ - "null"
description: The user's current rank in this leaderboard. Null if the user is not on the leaderboard.
example: 2
value:
type:
- integer
- - 'null'
+ - "null"
description: The user's current value in this leaderboard. Null if the user is not on the leaderboard.
example: 4500
required:
@@ -4684,13 +4684,13 @@ components:
type: object
description: A user's data for a specific leaderboard including rank, value, and history.
allOf:
- - $ref: '#/components/schemas/UserLeaderboardResponse'
+ - $ref: "#/components/schemas/UserLeaderboardResponse"
- type: object
properties:
history:
type: array
items:
- $ref: '#/components/schemas/LeaderboardEvent'
+ $ref: "#/components/schemas/LeaderboardEvent"
description: An array of events showing the user's rank and value changes over time.
required:
- history
@@ -4699,19 +4699,19 @@ components:
type: object
description: A user's data for a specific leaderboard including rank, value, and history.
allOf:
- - $ref: '#/components/schemas/UserLeaderboardResponse'
+ - $ref: "#/components/schemas/UserLeaderboardResponse"
- type: object
properties:
previousRank:
type:
- integer
- - 'null'
+ - "null"
description: The user's rank before this event, or null if they were not on the leaderboard.
example: 5
previousValue:
type:
- integer
- - 'null'
+ - "null"
description: The user's value before this event, or null if they were not on the leaderboard.
example: 1000
required:
@@ -4746,7 +4746,7 @@ components:
issues:
type: array
items:
- $ref: '#/components/schemas/BulkInsertIssue'
+ $ref: "#/components/schemas/BulkInsertIssue"
description: Array of issues encountered during freeze creation.
required:
- issues
@@ -4790,7 +4790,7 @@ components:
issues:
type: array
items:
- $ref: '#/components/schemas/BulkInsertIssue'
+ $ref: "#/components/schemas/BulkInsertIssue"
description: Array of issues encountered during streak restoration.
required:
- restoredUsers
@@ -4831,7 +4831,7 @@ components:
units:
type:
- string
- - 'null'
+ - "null"
description: The units of the metric.
example: words
currentTotal:
@@ -4863,7 +4863,7 @@ components:
units:
type:
- string
- - 'null'
+ - "null"
description: The units of the metric.
currentTotal:
type: number
@@ -4896,7 +4896,7 @@ components:
description:
type:
- string
- - 'null'
+ - "null"
description: The description of the points system.
example: Points earned through activity
currentTotal:
@@ -4930,29 +4930,29 @@ components:
description: The length of the streak.
example: 45
frequency:
- $ref: '#/components/schemas/StreakFrequency'
+ $ref: "#/components/schemas/StreakFrequency"
description: The frequency of the streak.
periodStart:
type:
- string
- - 'null'
+ - "null"
format: date
description: The start date of the streak period.
- example: '2024-02-01'
+ example: "2024-02-01"
periodEnd:
type:
- string
- - 'null'
+ - "null"
format: date
description: The end date of the streak period.
- example: '2024-03-17'
+ example: "2024-03-17"
started:
type:
- string
- - 'null'
+ - "null"
format: date
description: The date the streak started.
- example: '2024-02-01'
+ example: "2024-02-01"
required:
- length
- frequency
@@ -4967,22 +4967,22 @@ components:
metrics:
type: object
additionalProperties:
- $ref: '#/components/schemas/WrappedMetric'
+ $ref: "#/components/schemas/WrappedMetric"
description: The user's metrics during this period, keyed by metric key.
points:
type: object
additionalProperties:
- $ref: '#/components/schemas/WrappedPoints'
+ $ref: "#/components/schemas/WrappedPoints"
description: The user's points during this period, keyed by points system key.
achievements:
type: array
items:
- $ref: '#/components/schemas/UserAchievementResponse'
+ $ref: "#/components/schemas/UserAchievementResponse"
description: Achievements completed during this period.
leaderboards:
type: object
additionalProperties:
- $ref: '#/components/schemas/UserLeaderboardResponse'
+ $ref: "#/components/schemas/UserLeaderboardResponse"
description: The user's best leaderboard rankings during this period, keyed by leaderboard key.
required:
- metrics
@@ -4994,14 +4994,14 @@ components:
type: object
description: The user's most active day during the year.
allOf:
- - $ref: '#/components/schemas/WrappedActivityPeriod'
+ - $ref: "#/components/schemas/WrappedActivityPeriod"
- type: object
properties:
date:
type: string
format: date
description: The date of the most active day in YYYY-MM-DD format.
- example: '2024-03-15'
+ example: "2024-03-15"
required:
- date
WrappedMostActiveWeek:
@@ -5009,19 +5009,19 @@ components:
type: object
description: The user's most active week during the year.
allOf:
- - $ref: '#/components/schemas/WrappedActivityPeriod'
+ - $ref: "#/components/schemas/WrappedActivityPeriod"
- type: object
properties:
start:
type: string
format: date
description: The start date of the most active week in YYYY-MM-DD format.
- example: '2024-03-11'
+ example: "2024-03-11"
end:
type: string
format: date
description: The end date of the most active week in YYYY-MM-DD format.
- example: '2024-03-17'
+ example: "2024-03-17"
required:
- start
- end
@@ -5030,7 +5030,7 @@ components:
type: object
description: The user's most active month during the year.
allOf:
- - $ref: '#/components/schemas/WrappedActivityPeriod'
+ - $ref: "#/components/schemas/WrappedActivityPeriod"
- type: object
properties:
month:
@@ -5046,11 +5046,11 @@ components:
type: object
description: The user's activity data for the entire year.
allOf:
- - $ref: '#/components/schemas/WrappedActivityPeriod'
+ - $ref: "#/components/schemas/WrappedActivityPeriod"
- type: object
properties:
longestStreak:
- $ref: '#/components/schemas/WrappedStreak'
+ $ref: "#/components/schemas/WrappedStreak"
description: The user's longest streak during the year.
required:
- longestStreak
@@ -5072,16 +5072,16 @@ components:
description: The number of months the user was active during the year.
example: 11
mostActiveDay:
- $ref: '#/components/schemas/WrappedMostActiveDay'
+ $ref: "#/components/schemas/WrappedMostActiveDay"
description: Data about the user's most active day.
mostActiveWeek:
- $ref: '#/components/schemas/WrappedMostActiveWeek'
+ $ref: "#/components/schemas/WrappedMostActiveWeek"
description: Data about the user's most active week.
mostActiveMonth:
- $ref: '#/components/schemas/WrappedMostActiveMonth'
+ $ref: "#/components/schemas/WrappedMostActiveMonth"
description: Data about the user's most active month.
entireYear:
- $ref: '#/components/schemas/WrappedEntireYear'
+ $ref: "#/components/schemas/WrappedEntireYear"
description: Data about the user's activity for the entire year.
required:
- daysActive
@@ -5097,10 +5097,10 @@ components:
description: A user's year-in-review wrapped data including activity summaries, metrics, points, achievements, streaks, and leaderboard rankings.
properties:
user:
- $ref: '#/components/schemas/User'
+ $ref: "#/components/schemas/User"
description: The user's profile information.
activity:
- $ref: '#/components/schemas/WrappedActivity'
+ $ref: "#/components/schemas/WrappedActivity"
description: The user's activity data for the wrapped year.
required:
- user
diff --git a/docs.json b/docs.json
index a73afa8..ef13278 100644
--- a/docs.json
+++ b/docs.json
@@ -168,7 +168,9 @@
"api-reference/endpoints/users/get-a-users-points",
"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"
+ "api-reference/endpoints/users/get-a-users-wrapped",
+ "api-reference/endpoints/users/get-user-preferences",
+ "api-reference/endpoints/users/update-user-preferences"
]
}
]
diff --git a/platform/emails.mdx b/platform/emails.mdx
index 9b9faae..4543f25 100644
--- a/platform/emails.mdx
+++ b/platform/emails.mdx
@@ -35,6 +35,13 @@ All emails are optional, but all four can be used simultaneously and can be cont
To start sending emails with Trophy, you'll need to verify your domain and enable email triggers.
+
+ Users can control which email notifications they receive through Trophy's
+ [user preferences API](/platform/users#notification-preferences). This allows
+ you to build a preference center in your application where users can opt in or
+ out of specific email types.
+
+
### Domain Verification
Trophy supports sending emails from your own domain out-of-the-box. There are two ways to set this up, Single Sender Verification and DNS Verification.
@@ -812,7 +819,14 @@ All emails that Trophy sends include an unsubscribe link and message. This is im
wish to receive these emails, you can unsubscribe._
-Any recipient that clicks this link will no longer receive any emails from Trophy.
+Any recipient that clicks this link will be taken to a branded page that allows them to control which emails notifications they receive.
+
+
+ As an alternative to the unsubscribe link, you can also build a preference
+ center in your application using Trophy's [user preferences
+ API](/platform/users#notification-preferences). This gives users more granular
+ control over which types of emails they receive.
+
## Email Analytics
diff --git a/platform/push-notifications.mdx b/platform/push-notifications.mdx
index fc3bada..b3aef48 100644
--- a/platform/push-notifications.mdx
+++ b/platform/push-notifications.mdx
@@ -105,6 +105,13 @@ To achieve this you must provide Trophy with a few key details from your Expo ac
Follow the steps below to start sending push notifications using Trophy.
+
+ Users can control which push notifications they receive through Trophy's [user
+ preferences API](/platform/users#notification-preferences). This allows you to
+ build a preference center in your application where users can opt in or out of
+ specific notification types.
+
+
Trophy support sending push notifications via 3 channels, [Apple Push Notification Service (APNs)](#apple-push-notification-service-apns), [Firebase Cloud Messaging (FCM)](#firebase-cloud-messaging-fcm) or [Expo Push Service](#expo-push-service).
@@ -173,6 +180,10 @@ Follow the steps below to start sending push notifications using Trophy.
Once enabled, Trophy will start sending push notifications automatically.
+
+ Users can control which push notification types they receive through Trophy's [user preferences API](/platform/users#notification-preferences). When a user has disabled a notification type in their preferences, Trophy will respect that setting and won't send those notifications to that user.
+
+