diff --git a/api-reference/endpoints/points/get-all-points-triggers.mdx b/api-reference/endpoints/points/get-all-points-triggers.mdx new file mode 100644 index 0000000..6673a6b --- /dev/null +++ b/api-reference/endpoints/points/get-all-points-triggers.mdx @@ -0,0 +1,3 @@ +--- +openapi: get /points/triggers +--- diff --git a/api-reference/endpoints/points/get-points-summary.mdx b/api-reference/endpoints/points/get-points-summary.mdx new file mode 100644 index 0000000..7ac2423 --- /dev/null +++ b/api-reference/endpoints/points/get-points-summary.mdx @@ -0,0 +1,3 @@ +--- +openapi: get /points/summary +--- diff --git a/api-reference/endpoints/users/get-a-users-points-summary.mdx b/api-reference/endpoints/users/get-a-users-points-summary.mdx new file mode 100644 index 0000000..baaa426 --- /dev/null +++ b/api-reference/endpoints/users/get-a-users-points-summary.mdx @@ -0,0 +1,3 @@ +--- +openapi: get /users/{id}/points/event-summary +--- diff --git a/api-reference/endpoints/users/get-a-users-points.mdx b/api-reference/endpoints/users/get-a-users-points.mdx new file mode 100644 index 0000000..578d3b9 --- /dev/null +++ b/api-reference/endpoints/users/get-a-users-points.mdx @@ -0,0 +1,3 @@ +--- +openapi: get /users/{id}/points +--- diff --git a/api-reference/openapi.yml b/api-reference/openapi.yml index d87d17f..49f8f77 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.4' + version: "1.0.4" paths: /achievements: get: @@ -10,14 +10,14 @@ paths: tags: - Achievements 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: @@ -47,24 +47,24 @@ paths: streakLength: 10 completions: 2 completedPercentage: 20 - '401': - description: 'Unauthorized' + "401": + description: "Unauthorized" content: application/json: schema: - $ref: '#/components/schemas/ErrorBody' - '404': - description: 'Achievements not found' + $ref: "#/components/schemas/ErrorBody" + "404": + description: "Achievements 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 achievements and their completion stats security: - ApiKeyAuth: [] @@ -83,12 +83,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: @@ -100,25 +100,25 @@ paths: description: Complete the onboarding process. badgeUrl: https://example.com/badge.png key: finish-onboarding - achievedAt: '2021-01-01T00:00:00Z' - '401': - description: 'Unauthorized' + achievedAt: "2021-01-01T00:00:00Z" + "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: [] @@ -130,7 +130,7 @@ paths: type: object properties: user: - $ref: '#/components/schemas/UpdatedUser' + $ref: "#/components/schemas/UpdatedUser" description: The user that completed the achievement. required: - user @@ -157,12 +157,12 @@ paths: type: string example: words-written responses: - '201': + "201": description: Created event content: application/json: schema: - $ref: '#/components/schemas/EventResponse' + $ref: "#/components/schemas/EventResponse" examples: Successful operation: value: @@ -177,32 +177,32 @@ 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' - '400': - description: 'Bad Request' + started: "2025-04-02" + periodStart: "2025-03-31" + periodEnd: "2025-04-05" + expires: "2025-04-12" + "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: [] @@ -214,7 +214,7 @@ paths: type: object properties: user: - $ref: '#/components/schemas/UpsertedUser' + $ref: "#/components/schemas/UpsertedUser" description: The user that triggered the event. value: type: number @@ -232,7 +232,7 @@ paths: user: email: user@example.com tz: Europe/London - id: '18' + id: "18" value: 750 /users: post: @@ -249,15 +249,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: @@ -265,26 +265,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" /users/{id}: get: description: Get a single user. @@ -303,12 +303,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: @@ -316,26 +316,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 @@ -357,19 +357,19 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/UpdatedUser' + $ref: "#/components/schemas/UpdatedUser" description: The user object. example: id: user-id email: user@example.com tz: Europe/London responses: - '200': + "200": description: Updated user content: application/json: schema: - $ref: '#/components/schemas/User' + $ref: "#/components/schemas/User" examples: Successful operation: value: @@ -377,26 +377,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" /users/{id}/metrics: get: description: Get a single user's progress against all active metrics. @@ -412,14 +412,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: @@ -434,14 +434,14 @@ paths: name: Novice Writer 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 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 @@ -449,24 +449,24 @@ paths: metricId: d01dcbcb-d51e-4c12-b054-dc811dcdc623 metricValue: 2000 achievedAt: null - '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 all metrics for a user security: - ApiKeyAuth: [] @@ -492,12 +492,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: @@ -512,13 +512,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 @@ -526,24 +526,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: [] @@ -586,7 +586,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. @@ -594,9 +594,9 @@ paths: schema: type: string format: date - example: '2024-01-31' + example: "2024-01-31" responses: - '200': + "200": description: Successful operation content: application/json: @@ -609,7 +609,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 @@ -627,33 +627,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: [] @@ -672,14 +672,14 @@ paths: type: string example: userId responses: - '200': + "200": description: Successful operation content: application/json: schema: type: array items: - $ref: '#/components/schemas/CompletedAchievementResponse' + $ref: "#/components/schemas/CompletedAchievementResponse" examples: Successful operation: value: @@ -687,7 +687,7 @@ paths: trigger: api key: completed-onboarding name: Completed Onboarding - achievedAt: '2021-01-01T00:00:00Z' + achievedAt: "2021-01-01T00:00:00Z" badgeUrl: https://example.com/badge2.png - id: d01dcbcb-d51e-4c12-b054-dc811dcdc623 trigger: metric @@ -696,33 +696,33 @@ 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 - id: d01dcbcb-d51e-4c12-b054-dc811dcdc624 trigger: streak 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 - '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 completed achievements security: - ApiKeyAuth: [] @@ -749,62 +749,62 @@ 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" 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: [] @@ -831,12 +831,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: @@ -850,24 +850,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: [] @@ -903,7 +903,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. @@ -911,9 +911,9 @@ paths: schema: type: string format: date - example: '2024-01-31' + example: "2024-01-31" responses: - '200': + "200": description: Successful operation content: application/json: @@ -926,7 +926,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 @@ -944,33 +944,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: [] @@ -981,12 +981,12 @@ paths: tags: - Points responses: - '200': + "200": description: Successful operation content: application/json: schema: - $ref: '#/components/schemas/PointsSummaryResponse' + $ref: "#/components/schemas/PointsSummaryResponse" examples: Successful operation: value: @@ -1023,18 +1023,18 @@ 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' + $ref: "#/components/schemas/ErrorBody" summary: Get a breakdown of users by points security: - ApiKeyAuth: [] @@ -1045,14 +1045,14 @@ paths: tags: - Points responses: - '200': + "200": description: Successful operation content: application/json: schema: type: array items: - $ref: '#/components/schemas/PointsTriggerResponse' + $ref: "#/components/schemas/PointsTriggerResponse" examples: Successful operation: value: @@ -1063,29 +1063,29 @@ paths: metricId: 0040fe51-6bce-4b44-b0ad-bddc4e123534 metricName: words written metricThreshold: 1000 - 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 status: active achievementId: 0040fe51-6bce-4b44-b0ad-bddc4e123535 achievementName: finish onboarding - 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' + $ref: "#/components/schemas/ErrorBody" summary: Get all points triggers security: - ApiKeyAuth: [] @@ -1114,7 +1114,7 @@ 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 @@ -1140,7 +1140,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: @@ -1151,7 +1151,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: @@ -1168,12 +1168,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. @@ -1192,7 +1192,7 @@ components: type: type: string description: The type of trigger - enum: ['metric', 'achievement', 'streak'] + enum: ["metric", "achievement", "streak"] points: type: number description: The points awarded by this trigger. @@ -1219,7 +1219,7 @@ components: type: number description: The points awarded by this trigger trigger: - $ref: '#/components/schemas/PointsTrigger' + $ref: "#/components/schemas/PointsTrigger" GetUserPointsResponse: title: GetUserPointsResponse type: object @@ -1231,12 +1231,12 @@ components: type: array description: Array of trigger awards that added points. items: - $ref: '#/components/schemas/PointsAward' + $ref: "#/components/schemas/PointsAward" MetricEventPointsResponse: title: MetricEventPointsResponse type: object allOf: - - $ref: '#/components/schemas/GetUserPointsResponse' + - $ref: "#/components/schemas/GetUserPointsResponse" - type: object properties: added: @@ -1255,7 +1255,7 @@ 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 @@ -1283,7 +1283,7 @@ components: type: string description: The name of the metric associated with this achievement (only applicable if trigger = 'metric') currentStreak: - $ref: '#/components/schemas/MetricEventStreakResponse' + $ref: "#/components/schemas/MetricEventStreakResponse" description: >- The user's current streak for the metric, if the metric has streaks enabled. @@ -1295,7 +1295,7 @@ components: title: CompletedAchievementResponse type: object allOf: - - $ref: '#/components/schemas/AchievementResponse' + - $ref: "#/components/schemas/AchievementResponse" - type: object properties: achievedAt: @@ -1306,7 +1306,7 @@ components: title: AchievementWithStatsResponse type: object allOf: - - $ref: '#/components/schemas/AchievementResponse' + - $ref: "#/components/schemas/AchievementResponse" - type: object properties: completions: @@ -1333,7 +1333,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 @@ -1343,7 +1343,7 @@ components: achievements: type: array items: - $ref: '#/components/schemas/CompletedAchievementResponse' + $ref: "#/components/schemas/CompletedAchievementResponse" description: >- A list of the metric's achievements and the user's progress towards each. @@ -1381,7 +1381,7 @@ components: type: object description: An object with editable user fields. allOf: - - $ref: '#/components/schemas/UpdatedUser' + - $ref: "#/components/schemas/UpdatedUser" - type: object properties: id: @@ -1395,7 +1395,7 @@ components: type: object description: A user of your application. allOf: - - $ref: '#/components/schemas/UpsertedUser' + - $ref: "#/components/schemas/UpsertedUser" - type: object properties: control: @@ -1406,12 +1406,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" ErrorBody: title: ErrorBody type: object @@ -1429,7 +1429,7 @@ components: description: The unique ID of the completion. example: 0040fe51-6bce-4b44-b0ad-bddc4e123534 achievement: - $ref: '#/components/schemas/CompletedAchievementResponse' + $ref: "#/components/schemas/CompletedAchievementResponse" required: - completionId - achievement @@ -1453,15 +1453,15 @@ components: achievements: type: array items: - $ref: '#/components/schemas/CompletedAchievementResponse' + $ref: "#/components/schemas/CompletedAchievementResponse" description: Achievements completed as a result of this event. currentStreak: - $ref: '#/components/schemas/MetricEventStreakResponse' + $ref: "#/components/schemas/MetricEventStreakResponse" description: >- The user's current streak for the metric, if the metric has streaks enabled. points: - $ref: '#/components/schemas/PointsAward' + $ref: "#/components/schemas/PointsAward" description: >- The points added by this event, and a breakdown of the points awards that added points. @@ -1491,7 +1491,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 @@ -1501,14 +1501,14 @@ components: description: The unique ID of the trigger. type: type: string - enum: ['metric', 'achievement', 'streak'] + enum: ["metric", "achievement", "streak"] description: The type of trigger. points: type: number 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 diff --git a/assets/og.png b/assets/og.png index 70e42a4..d728382 100644 Binary files a/assets/og.png and b/assets/og.png differ diff --git a/assets/platform/achievements/displaying_trophy_cabinet.mp4 b/assets/platform/achievements/displaying_trophy_cabinet.mp4 new file mode 100644 index 0000000..8806265 Binary files /dev/null and b/assets/platform/achievements/displaying_trophy_cabinet.mp4 differ diff --git a/assets/platform/achievements/user_achievements.png b/assets/platform/achievements/user_achievements.png new file mode 100644 index 0000000..e17609c Binary files /dev/null and b/assets/platform/achievements/user_achievements.png differ diff --git a/assets/platform/points/create_trigger.mp4 b/assets/platform/points/create_trigger.mp4 new file mode 100644 index 0000000..9385ff9 Binary files /dev/null and b/assets/platform/points/create_trigger.mp4 differ diff --git a/assets/platform/points/points_analytics.png b/assets/platform/points/points_analytics.png new file mode 100644 index 0000000..c53d021 Binary files /dev/null and b/assets/platform/points/points_analytics.png differ diff --git a/assets/platform/points/points_preview.mp4 b/assets/platform/points/points_preview.mp4 new file mode 100644 index 0000000..9082eaa Binary files /dev/null and b/assets/platform/points/points_preview.mp4 differ diff --git a/assets/platform/streaks/displaying_streaks.png b/assets/platform/streaks/displaying_streaks.png new file mode 100644 index 0000000..49cd5ec Binary files /dev/null and b/assets/platform/streaks/displaying_streaks.png differ diff --git a/docs.json b/docs.json index 1ae8802..7575d68 100644 --- a/docs.json +++ b/docs.json @@ -25,7 +25,7 @@ }, "seo": { "metatags": { - "og:description": "Trophy is a developer-friendly platform for building gamified product experiences in any mobile or web app. Add features like achievements and streaks in hours, not months.", + "og:description": "Trophy is a developer-friendly platform for building gamified product experiences that retain users in any mobile or web app. Add features like achievements, streaks and points systems and deliver personalized progress report and reactivation emails with no code.", "og:image": "/assets/og.png" } }, @@ -50,6 +50,7 @@ "platform/users", "platform/achievements", "platform/streaks", + "platform/points", "platform/emails" ] }, @@ -123,6 +124,13 @@ "api-reference/endpoints/metrics/send-a-metric-change-event" ] }, + { + "group": "Points", + "pages": [ + "api-reference/endpoints/points/get-points-summary", + "api-reference/endpoints/points/get-all-points-triggers" + ] + }, { "group": "Users", "pages": [ @@ -133,7 +141,9 @@ "api-reference/endpoints/users/get-a-single-metric-for-a-user", "api-reference/endpoints/users/get-a-single-metric-event-summary-for-a-user", "api-reference/endpoints/users/get-a-users-completed-achievements", - "api-reference/endpoints/users/get-a-users-streak" + "api-reference/endpoints/users/get-a-users-streak", + "api-reference/endpoints/users/get-a-users-points", + "api-reference/endpoints/users/get-a-users-points-summary" ] } ] diff --git a/getting-started/introduction.mdx b/getting-started/introduction.mdx index d050799..de7e3f7 100644 --- a/getting-started/introduction.mdx +++ b/getting-started/introduction.mdx @@ -3,9 +3,9 @@ title: Welcome to Trophy description: Trophy documentation for gamification APIs, quickstart guides and tutorials. --- -Trophy is a developer-friendly platform and toolkit for building gamified product experiences in any mobile or web app. +Trophy is a developer-friendly toolkit for building gamified product experiences in any mobile or web app. -It makes adding features like [Achievements](/platform/achievements) and [Streaks](/platform/streaks) simple with just a few lines of code, and can send gamified [Emails](/platform/emails) to increase your retention and engagement. +It makes building features like [Achievements](/platform/achievements), [Streaks](/platform/streaks) and [Points](/platform/points) simple with just a few lines of code, and can send gamified [Emails](/platform/emails) to increase your retention and engagement. - All gamification features, like [Achievements](/platform/achievements), [Streaks](/platform/streaks) and [Emails](/platform/emails), are driven by user interactions. In Trophy, you use [Metrics](/platform/metrics) to define those interactions and [Events](/platform/events) to track them. + All gamification features are driven by user interactions. In Trophy, you use [Metrics](/platform/metrics) to define and model those interactions and [Events](/platform/events) to track them. - Here you'll create your first metric to get started. In thr Trophy dashboard, head into the [metrics page](https://app.trophy.so/metrics) and hit the _New Metric_ button: + Here you'll create your first metric to get started. In the Trophy dashboard, head into the [metrics page](https://app.trophy.so/metrics) and hit the _New Metric_ button: @@ -84,14 +84,17 @@ Here you'll integrate your backend web application with Trophy and start buildin Reward users for continued progress or taking specific actions. - Motivate users to continue using your platform over time. + Motivate users to build regular usage habits. + + + Build sophisticated points systems to reward and retain users. - Encourage and congratulate users to keep them coming back. + Deliver personalized lifecyle emails to users at the perfect moment. - Or, explore our [ready-made APIs](/api-reference/introduction) that support building any in-app gamification UI you want. + Or, explore our [purpose-built APIs](/api-reference/introduction) that support building any in-app gamification UI you want. diff --git a/guides/example-apps/example-study-platform.mdx b/guides/example-apps/example-study-platform.mdx index 887f1a3..666fa78 100644 --- a/guides/example-apps/example-study-platform.mdx +++ b/guides/example-apps/example-study-platform.mdx @@ -43,9 +43,9 @@ The tech stack for this example study platform is as follows: The example app uses Trophy to demonstrate how easy it is to build gamification experiences. Here's a breakdown of the gamification features used: -### Multi-stage Acheivements +### Achievements -The example app features multi-stage [achievements(/platform/achievements)] with the following milestones: +The example app features [achievements(/platform/achievements)] with the following milestones: - 10 flashcards viewed - 50 flashcards viewed diff --git a/guides/tutorials/how-to-build-a-gamified-study-platform.mdx b/guides/tutorials/how-to-build-a-gamified-study-platform.mdx index 7d0c99e..90583db 100644 --- a/guides/tutorials/how-to-build-a-gamified-study-platform.mdx +++ b/guides/tutorials/how-to-build-a-gamified-study-platform.mdx @@ -993,7 +993,7 @@ import Image from "next/image"; interface ToastProps { id: string | number; title: string; - description: string; + description?: string; image?: { src: string; alt: string; @@ -1040,7 +1040,9 @@ export function Toast(props: ToastProps) {

{title}

-

{description}

+ {description && ( +

{description}

+ )}
@@ -1086,7 +1088,7 @@ export default nextConfig; And finally, we update our `` component to read the response from Trophy and display toasts for any unlocked achievements: -```tsx src/app/flashcards.tsx [expandable] {15,33,38-61} +```tsx src/app/flashcards.tsx [expandable] {15,33,38-56} "use client"; import { @@ -1130,23 +1132,17 @@ export default function Flashcards({ flashcards }: Props) { return; } - // Show toast if the user has unlocked any new achievements - if (response.achievements?.length) { - response.achievements.forEach((metricAchievements) => { - if (metricAchievements.completed?.length) { - metricAchievements.completed.forEach((achievement) => { - toast({ - title: achievement.name as string, - description: `Congratulations! You've viewed ${achievement.metricValue} flashcards!`, - image: { - src: achievement.badgeUrl as string, - alt: achievement.name as string, - }, - }); - }); - } + // Show toasts if the user has unlocked any new achievements + response.achievements.forEach((achievement) => { + toast({ + title: achievement.name as string, + description: achievement.description, + image: { + src: achievement.badgeUrl as string, + alt: achievement.name as string, + }, }); - } + }); }); }, [api]); @@ -1193,7 +1189,7 @@ We'll use the same methods to show similar toasts when a user extendeds their st All we need to do is read the `currentStreak.extended` property from Trophy and handle showing another toast with a new `if` statement: -```tsx src/app/flashcards.tsx [expandable] {62-69} +```tsx src/app/flashcards.tsx [expandable] {56-63} "use client"; import { @@ -1237,23 +1233,17 @@ export default function Flashcards({ flashcards }: Props) { return; } - // Show toast if the user has unlocked any new achievements - if (response.achievements?.length) { - response.achievements.forEach((metricAchievements) => { - if (metricAchievements.completed?.length) { - metricAchievements.completed.forEach((achievement) => { - toast({ - title: achievement.name as string, - description: `Congratulations! You've viewed ${achievement.metricValue} flashcards!`, - image: { - src: achievement.badgeUrl as string, - alt: achievement.name as string, - }, - }); - }); - } + // Show toasts if the user has unlocked any new achievements + response.achievements.forEach((achievement) => { + toast({ + title: achievement.name as string, + description: achievement.description, + image: { + src: achievement.badgeUrl as string, + alt: achievement.name as string, + }, }); - } + }); // Show toast if user has extended their streak if (response.currentStreak?.extended) { @@ -1310,7 +1300,7 @@ For this we'll make use of the [HTML5 Audio API](https://developer.mozilla.org/e To load the sound files into our application, we'll create a ref for each one, then we simply call the `play()` method on each when we want to actually play the sound: -```tsx src/app/flashcards.tsx [expandable] {25-31,53-57,77-81} +```tsx src/app/flashcards.tsx [expandable] {25-31,53-57,73-77} "use client"; import { @@ -1370,19 +1360,15 @@ export default function Flashcards({ flashcards }: Props) { } // Show toasts if the user has unlocked any new achievements - response.achievements.forEach((metricAchievements) => { - if (metricAchievements.completed?.length) { - metricAchievements.completed.forEach((achievement) => { - toast({ - title: achievement.name as string, - description: `Congratulations! You've viewed ${achievement.metricValue} flashcards!`, - image: { - src: achievement.badgeUrl as string, - alt: achievement.name as string, - }, - }); - }); - } + response.achievements.forEach((achievement) => { + toast({ + title: achievement.name as string, + description: achievement.description, + image: { + src: achievement.badgeUrl as string, + alt: achievement.name as string, + }, + }); }); } diff --git a/platform/achievements.mdx b/platform/achievements.mdx index 3b5b6fc..503ea97 100644 --- a/platform/achievements.mdx +++ b/platform/achievements.mdx @@ -1,17 +1,25 @@ --- title: Achievements description: Learn how to use Achievements in a gamified product experience with Trophy. -"og:description": Use multi-stage, one-off and streak achievements to rewards users for continued progress and to encourage them to discover new parts of your app. +"og:description": Use metric, standalone and streak achievements to rewards users for continued progress and to encourage them to discover new parts of your app. icon: trophy --- import MetricChangeResponseBlock from "/snippets/metric-change-response-block.mdx"; +import AllAchievementsResponseBlock from "/snippets/all-achievements-response-block.mdx"; ## What Are Achievements? Achievements are rewards that users can unlock as they use your platform. They can be used to reward users for making continued progress along core user journeys, or to motivate users to explore more nascent features. -No matter the type of achievement, they work best when designed to incentivize users to take actions that are likely to lead to increased retention. So before jumping in, have a think about what those actions might be in your context. +Achievements work best when designed to incentivize users to take actions that +are likely to lead to increased retention. + + + Use Trophy's [metric analytics](/platform/metrics#metric-analytics) to compare + the retention of each user interaction, then configure achievements around + these interactions to maximize retention impact. + Here we'll have a look of the types of achievements you can build with Trophy, the different ways to use them, and how to integrate them into your platform. @@ -144,7 +152,9 @@ This will return back a response that contains details of the achievement that w "completionId": "0040fe51-6bce-4b44-b0ad-bddc4e123534", "achievement": { "id": "5100fe51-6bce-6j44-b0hs-bddc4e123682", + "trigger": "api", "name": "Finish onboarding", + "description": "Complete the onboarding process.", "badgeUrl": "https://example.com/badge.png", "key": "finish-onboarding", "achievedAt": "2021-01-01T00:00:00Z" @@ -167,12 +177,14 @@ This will return back a response that contains details of the achievement that w A badge can be uploaded and assigned to any achievement in Trophy. Trophy will host the image for you and return the URL back to you in relevant API responses to be used as the `src` property in `` tags. -```json Response {6} +```json Response {8} { "completionId": "0040fe51-6bce-4b44-b0ad-bddc4e123534", "achievement": { "id": "5100fe51-6bce-6j44-b0hs-bddc4e123682", + "trigger": "api", "name": "Finish onboarding", + "description": "Complete the onboarding process.", "badgeUrl": "https://example.com/badge.png", "key": "finish-onboarding", "achievedAt": "2021-01-01T00:00:00Z" @@ -180,14 +192,56 @@ A badge can be uploaded and assigned to any achievement in Trophy. Trophy will h } ``` -## Achievement Analytics +## Displaying Achievements + +Trophy has a number of APIs that support displaying achievements within your applications. Here we'll look at the different ways to use them and the types of UI's you can build. + + + Take a look at our [examples center](https://examples.trophy.so) for live + demos of APIs in practice. + + +### All Achievements + +To display a high-level overview of all achievements users can complete, use the [all achievements endpoint](/api-reference/endpoints/achievements/all-achievements). Use this data to build UI that gives users an idea of the progression pathways within your application. + + + + + +The all achievements endpoint returns a list of all achievements within your Trophy account along with details of 'rarity' (the percentage of users who have completed each achievement) as follows: + + + +### User Achievements -If you have multi-stage acheivements set up for any of your [Metrics](/platform/metrics), then the metric analytics page displays a chart that shows you the current progress of all Users as follows: +If instead you're building user-specific UI elements, then use the [user achievements endpoint](/api-reference/endpoints/users/get-a-users-completed-achievements) to get only the achievements a specific user has completed. + +Use this data to display achievements against a user's profile for example. + + +## Achievement Analytics + +If you have achievements set up for any of your [Metrics](/platform/metrics), then the metric analytics page displays a chart that shows you the current progress of all Users as follows: + + + @@ -207,8 +261,9 @@ If you have multi-stage acheivements set up for any of your [Metrics](/platform/ Achievements, like all gamification, offer the best retention when tightly aligned to the user's core reason for using your platform. - Only you'll know what's best here. - + Use Trophy's [metric analytics](/platform/metrics#metric-analytics) to compare the retention of each user interaction, then configure achievements around these interactions to maximize retention impact. + + diff --git a/platform/events.mdx b/platform/events.mdx index 75746c6..cb3cf0d 100644 --- a/platform/events.mdx +++ b/platform/events.mdx @@ -1,7 +1,7 @@ --- title: Events -description: Events are data objects that record continual user interactions against metrics in Trophy. -"og:description": Events are data objects that record continual user interactions against metrics in Trophy. +description: Events are data objects that represent individual user interactions against metrics in Trophy. +"og:description": Events are data objects that represent individual user interactions against metrics in Trophy. icon: radio --- @@ -10,7 +10,7 @@ import MetricChangeResponseBlock from "/snippets/metric-change-response-block.md ## What are Events? -Events store information about individual user interactions that are tracked against [Metrics](/platform/metrics) in Trophy. One event corresponds to a single interaction made by a single user. +Events represent individual user interactions against [Metrics](/platform/metrics) in Trophy. One event corresponds to a single interaction made by a single user. When you [integrate metrics](#tracking-metric-events) into your platform, you're setting up your platform to continuously stream events to your Trophy metrics for each user interaction. These interactions then drive all the gamification features you set up around these metrics. @@ -18,7 +18,7 @@ When you [integrate metrics](#tracking-metric-events) into your platform, you're ### Metric-backed -Each event increases or decreases a specific metric that you've configured in Trophy for a specific user. +Each event increases or decreases the total value of a specific metric that you've configured in Trophy for a specific user. ### Value @@ -34,17 +34,25 @@ Here's an example where a fictional book-writing platform is using a metric to t -Any [Achievements](/platform/achievements), [Streaks](/platform/streaks) or other gamification features that have been set up against this metric will be automatically processed, and the response will contain any updates to the users progress that are a direct result of the event occurring: +Any [Achievements](/platform/achievements), [Streaks](/platform/streaks) or [Points](/platform/points) that have been set up against this metric will be automatically processed, and the response will contain any updates to the users progress that are a direct result of the event occurring: -With custom code, this response data can then be used to drive any in-app experience you wish including: +In this example the response includes the following: + +- Newly unlocked achievements as a result of the event +- The users latest streak as result of the event +- Any points awards as a result of the event + +With a little bit of custom code, this response data can be used to drive any in-app experience you wish including: - Triggering in-app notifications - Sound effects - Animations -Watch Charlie integrate metric tracking into a simple NextJS application using the NodeJS SDK: +Additionally, any [Emails](/platform/emails) configured to track the metric will be scheduled automatically by Trophy. + +Watch Charlie integrate metric tracking into a simple NextJS application using the Trophy [NodeJS SDK](/api-reference/client-libraries):