Events & Analytics API
Use these endpoints to log user events and query analytics data such as streak performance and event statistics.
- Authentication: All endpoints require a valid JWT Bearer token.
- Versioning: Paths support
/v0,/v1,/v2,/v3. The version prefix is stripped internally.
See JWT Authentication for details on obtaining and using tokens.
Endpoints Overview
POST /event– Log eventGET /event– List eventsGET /event/{eventId}– Get event by IDGET /analytics/streak– Streak analyticsGET /stats/event– Event stats
POST /event – Log Event
Log a user event that can award points, update challenges, streaks, and leaderboards.
- Method:
POST - Path:
/v1/event - Auth:
Authorization: Bearer <JWT_TOKEN>(or API key for selected events)
Request Body
{
"eventId": "purchase_completed",
"userId": "user-123",
"metadata": {
"amount": 49.99,
"currency": "EUR",
"usergroup": ["default"],
"source": "web"
}
}- eventId
string(required): Identifier of the configured event in the dashboard. - userId
string(required): User identifier used across the loyalty system. - metadata
object(optional):- Arbitrary key/value pairs used for conditions, transaction rewards (e.g.
amount), usergroups, or analytics.
- Arbitrary key/value pairs used for conditions, transaction rewards (e.g.
If the event is configured as transactional, the reward is calculated based on a configured rewardValueField in the event definition that is read from metadata.
If the event requires an API key, the system will:
- Inspect the host and event configuration.
- Return 403 if the request is not authenticated via API key.
Responses
-
200 OK
{ "statusCode": 200, "message": "Event erfolgreich geloggt", "data": { "userId": "user-123", "eventId": "purchase_completed", "points": 50, "type": "TRANSACTION", "title": "Purchase completed", "limit": 10, "maximumReward": 1000, "metadata": { "amount": 49.99, "currency": "EUR", "usergroup": ["default"], "source": "web" }, "conditionReached": true, "limitReached": false, "userGroupId": "default" } }messagecan be"Event erfolgreich geloggt"or"Event Limit erreicht"depending on the configured limit.
-
400 Bad Request
- Missing or invalid
eventId - Missing or invalid
userId - Invalid JSON body
- Event is not active
- Missing or invalid
-
401 / 403 Unauthorized / Forbidden
- User is not authenticated or is not allowed to act on the given
userId. - API key required for specific events but not provided.
- User is not authenticated or is not allowed to act on the given
-
404 Not Found
- User could not be found in the project.
- Event does not exist.
-
500 Internal Server Error
- Unexpected DynamoDB or internal processing error.
GET /event – List Events
Retrieve a list of configured events for the current project.
- Method:
GET - Path:
/v1/event - Auth:
Authorization: Bearer <JWT_TOKEN>
Query Parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| showAll | string | no | "true" | "true" returns all events, "false" only returns events with ACTIVE status. |
Response
-
200 OK
[ { "eventId": "purchase_completed", "title": "Purchase completed", "description": "Tracks completed purchases", "status": "ACTIVE", "limit": 10, "maximumReward": 1000, "reward": { "default": 2 }, "conditions": { "type": "AND", "conditions": [ { "field": "amount", "operator": "greater_than", "value": 0 } ] }, "metadataFields": [ { "key": "amount", "type": "number", "required": true } ], "type": "TRANSACTION" } ] -
204 No Content
- No events are configured for the project.
-
500 Internal Server Error
- Error querying events.
GET /event/{eventId} – Get Event by ID
Retrieve the full configuration of a single event.
- Method:
GET - Path:
/v1/event/{eventId} - Auth:
Authorization: Bearer <JWT_TOKEN>
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| eventId | string | yes | Event identifier from dashboard. |
Response
-
200 OK
{ "eventId": "purchase_completed", "title": "Purchase completed", "description": "Tracks completed purchases", "status": "ACTIVE", "limit": 10, "maximumReward": 1000, "reward": { "default": 2 }, "conditions": { "type": "AND", "conditions": [ { "field": "amount", "operator": "greater_than", "value": 0 } ] }, "metadataFields": [ { "key": "amount", "type": "number", "required": true } ], "type": "TRANSACTION" } -
400 Bad Request
eventIdis missing.
-
404 Not Found
- Event does not exist in the project.
-
500 Internal Server Error
- Error loading the event configuration.
GET /analytics/streak – Streak Analytics
Return aggregated analytics for a configured streak definition.
- Method:
GET - Path:
/v1/analytics/streak - Auth:
Authorization: Bearer <JWT_TOKEN>
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| streakId | string | yes | Identifier of the configured streak. |
Response
-
200 OK
{ "streakId": "daily_login", "totalParticipants": 1240, "activeParticipants": 830, "averageStreakLength": 6.2, "longestUserStreak": 45, "completionRate": 0.67 } -
200 OK with
nullbody- Streak analytics are not yet available for the given
streakId.
- Streak analytics are not yet available for the given
-
500 Internal Server Error
- Error loading analytics from DynamoDB.
GET /stats/event – Event Stats
Return global or event-specific analytics for a given period.
- Method:
GET - Path:
/v1/stats/event - Auth:
Authorization: Bearer <JWT_TOKEN>
Query Parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| period | string | no | 7d | Time window: 1d, 7d, 30d, 90d, current_month, ytd, or all. |
| eventId | string | no | If provided, returns event-specific analytics; otherwise global. | |
| timeframe | string | no | When set to month and month is provided, uses monthly aggregates. | |
| month | string | no | In YYYY-MM format, e.g. 2025-08. Used together with timeframe=month. |
Response – Global Analytics Example
-
200 OK
{ "period": "7d", "eventId": null, "startDate": "2025-08-01", "endDate": "2025-08-07", "data": { "totalEvents": 6120, "uniqueUsers": 1420, "totalPoints": 81230, "eventBreakdown": { "purchase_completed": { "count": 4210, "users": 980, "points": 71230 }, "login": { "count": 1910, "users": 1240, "points": 10000 } }, "topEvents": ["purchase_completed", "login"], "dailyData": { "2025-08-01": { "events": 900, "users": 320, "points": 11000, "hourlyDistribution": [] } }, "_metadata": { "uniqueUsersCalculationMethod": "daily_exact", "uniqueUsersNote": null } } }
Response – Event-Specific Analytics Example
{
"period": "30d",
"eventId": "purchase_completed",
"startDate": "2025-08-01",
"endDate": "2025-08-30",
"data": {
"totalCount": 4100,
"uniqueUsers": 950,
"pointsAwarded": 71000,
"conditionMet": 4050,
"conditionFailed": 50,
"limitReached": 20,
"dailyData": {
"2025-08-01": {
"count": 200,
"users": 120,
"points": 3400,
"hourlyDistribution": []
}
}
}
}Error Responses
-
400 Bad Request
- Invalid
monthformat (notYYYY-MM) whentimeframe=month.
- Invalid
-
500 Internal Server Error
- Error retrieving analytics data or aggregations.