Challenges
Time-boxed challenges — goal type, goal value, reward XP, optional reward achievement.
Challenges are time-bounded goals (start_at → end_at) that users join and make progress against. Per-user join records track each user's progress and completion state.
Endpoints
| Method | Path | Description |
|---|---|---|
| POST | /admin/projects/:projectId/challenges | Create a challenge. |
| GET | /admin/projects/:projectId/challenges | List challenges, optionally filtered by ?status=active|upcoming|ended. |
| GET | /admin/projects/:projectId/challenges/:challengeId | Fetch a challenge. |
| PATCH | /admin/projects/:projectId/challenges/:challengeId | Partial update. |
| DELETE | /admin/projects/:projectId/challenges/:challengeId | Delete. |
| GET | /admin/projects/:projectId/challenges/:challengeId/participants | Paginated participants, ordered by progress. |
POST /admin/projects/:projectId/challenges
Request
| Field | Type | Required |
|---|---|---|
name | string | yes |
description | string | no |
start_at | ISO-8601 | yes |
end_at | ISO-8601 | yes |
goal_type | string | yes: event_count, xp_earned, or streak_maintained |
goal_value | number | yes |
event_name | string | yes for event_count; rejected on the other goal types |
reward_xp | number | no (default 0) |
reward_achievement_id | uuid | no |
event_name is the name of the event an event_count challenge counts. A
participant's progress is the number of events they tracked with exactly that
name between start_at and end_at. It is 1 to 255 characters, with no
leading or trailing whitespace.
Response 201
Errors
400 VALIDATION_ERRORwithdetails.field: "event_name": anevent_countchallenge withoutevent_name, a malformedevent_name, orevent_nameon another goal type.503 TENANT_MIGRATION_PENDING: the project is still being updated to store challenge event names. Retry in a few minutes.
Try it:
/admin/projects/%7B%7BprojectId%7D%7D/challengescurl -X POST 'https://api.amba.dev/v1/admin/projects/%7B%7BprojectId%7D%7D/challenges' \
-H 'Content-Type: application/json' \
-d '{
"name": "Five workouts this week",
"start_at": "2030-01-07T00:00:00Z",
"end_at": "2030-01-14T00:00:00Z",
"goal_type": "event_count",
"goal_value": 5,
"event_name": "workout_completed"
}'Curl:
GET /admin/projects/:projectId/challenges
Query
| Param | Values | Description |
|---|---|---|
status | active, upcoming, ended | Optional filter. Omit for all. |
Response 200
Try it:
/admin/projects/%7B%7BprojectId%7D%7D/challengescurl -X GET 'https://api.amba.dev/v1/admin/projects/%7B%7BprojectId%7D%7D/challenges'Curl:
GET /admin/projects/:projectId/challenges/:challengeId
Errors
404 NOT_FOUND.
Try it:
/admin/projects/%7B%7BprojectId%7D%7D/challenges/%7B%7BchallengeId%7D%7Dcurl -X GET 'https://api.amba.dev/v1/admin/projects/%7B%7BprojectId%7D%7D/challenges/%7B%7BchallengeId%7D%7D'Curl:
PATCH /admin/projects/:projectId/challenges/:challengeId
Allowed fields: name, description, start_at, end_at, goal_type, goal_value, event_name, reward_xp, reward_achievement_id, is_active.
event_name follows the same rules as on create, applied to the challenge
the update produces:
- Set
event_nameon anevent_countchallenge that has none to turn it on. Anevent_countchallenge created before event names existed hasevent_name: null; it is skipped and never completes until you set one. - An
event_countchallenge keeps itsevent_name:event_name: nullis rejected. Setis_active: falseto stop the challenge instead. - Changing
goal_typetoevent_countrequires anevent_name, in the same request or already stored. - Changing
goal_typeto another type clearsevent_name.
Errors
400 VALIDATION_ERRORwithdetails.field: "event_name".404 NOT_FOUND.503 TENANT_MIGRATION_PENDINGwhen the update stores anevent_nameand the project is still being updated. Retry in a few minutes.
Try it:
/admin/projects/%7B%7BprojectId%7D%7D/challenges/%7B%7BchallengeId%7D%7Dcurl -X PATCH 'https://api.amba.dev/v1/admin/projects/%7B%7BprojectId%7D%7D/challenges/%7B%7BchallengeId%7D%7D'Curl:
DELETE /admin/projects/:projectId/challenges/:challengeId
Try it:
/admin/projects/%7B%7BprojectId%7D%7D/challenges/%7B%7BchallengeId%7D%7Dcurl -X DELETE 'https://api.amba.dev/v1/admin/projects/%7B%7BprojectId%7D%7D/challenges/%7B%7BchallengeId%7D%7D'Curl:
GET /admin/projects/:projectId/challenges/:challengeId/participants
Paginated list of participants, ordered by progress DESC.
Query
| Param | Default |
|---|---|
limit | 50 |
offset | 0 |
Response 200
Try it:
/admin/projects/%7B%7BprojectId%7D%7D/challenges/%7B%7BchallengeId%7D%7D/participantscurl -X GET 'https://api.amba.dev/v1/admin/projects/%7B%7BprojectId%7D%7D/challenges/%7B%7BchallengeId%7D%7D/participants'Curl: