Intents and Challenges: Klariti's Unified Goal Model
Learn how Klariti’s intents and challenges share one data model, how the group pause threshold works, and how invitations gate private challenge access.
Use this file to discover all available pages before exploring further.
Intents and challenges are the core building blocks of Klariti. An intent is a goal bundled with rules for the Gray Engine — something you toggle on or off at any time, privately, with no deadline. A challenge is that same intent with social commitment layered on top: a deadline, friends, and a group pause condition that ties everyone’s focus sessions together. The distinction is purely UX framing. Under the hood, both are the same Challenge data shape — a solo intent is just a challenge with one participant and no ends_at value set.
The model deliberately separates challenge-level status from participant-level status.Challenge.status describes the lifecycle of the challenge itself:
Value
Meaning
active
Challenge is running
paused
Challenge-level pause (e.g. triggered by threshold)
completed
Challenge has ended
ChallengeParticipant.status describes one user’s state within the challenge:
Value
Meaning
active
User is actively participating
paused
User has paused their own participation
completed
User has completed the challenge
Keeping these separate prevents “paused challenge” and “paused participant” from colliding in search results, UI rendering, and automation logic.
The pause_threshold field is what turns a group challenge into an accountability mechanism with shared weight. It is a float between 0.0 and 1.0 representing the fraction of participants who must choose to pause before the challenge itself pauses for everyone.Setting pause_threshold: 0.5 means the challenge enters a group pause once at least 50% of participants have individually paused their participation. This makes stepping back a collective decision rather than a solo one.
Solo intents leave pause_threshold unset. The field is only meaningful with more than one participant.
The challenge creator invites friends to private challenges. Each invitation is a separate row — you can invite the same person to multiple challenges independently.
Accepting an invitation automatically creates a ChallengeParticipant row for the recipient. The join call handles both the invitation acceptance path and the open join path.
GET /api/challenges — search public challengesPOST /api/challenges — create a challenge or intentPATCH /api/challenges/:id — update (creator only)DELETE /api/challenges/:id — delete (creator only)
Participation
POST /api/challenges/:id/joinPOST /api/challenges/:id/leavePATCH /api/challenges/:id/statusGET /api/challenges/:id/participants
My Challenges
GET /api/users/me/challenges — your active challengesGET /api/users/:userId/challenges — another user’s challenges
Invitations
POST /api/challenges/:id/invitations — invite a friendGET /api/challenges/:id/invitations — list invitations (creator)GET /api/users/me/challenges/invitations — your pending invites