Like Groups API
| Status | Implementation |
|---|---|
| ✅ Shipped | src/feats/groups/ |
A like group is how users apply to attend an event. The group is formed by
one user plus optional friends. It starts as waiting while invited friends
answer. The creator sends it with /send; only then does it become pending
and visible to organizers. Once enough event authors approve it, a private
chat is created for the participants.
See also: Approval algorithm, Like-groups model.
All endpoints require Authorization: Bearer <supabase-access-token>.
Endpoints
| Method | Path | Description |
|---|---|---|
| GET | /groups | List my groups (as creator or member) |
| GET | /groups/:id | Get a group |
| POST | /groups/:id/members | Add a friend to the group |
| DELETE | /groups/:id/members/:userId | Remove a member |
| GET | /groups/:id/approvals | List approvals for the group |
| POST | /groups/:id/approve | Approve the group (event author only) |
| POST | /groups/:id/reject | Reject the group (event author only) |
| POST | /groups/:id/invite/accept | Accept an invited member position |
| POST | /groups/:id/invite/refuse | Refuse an invited member position |
| POST | /groups/:id/send | Send a waiting group to event organizers |
| DELETE | /groups/:id | Delete a waiting invitation |
Group creation happens via POST /events/:id/like.
Get group
GET /groups/:id
Authorization: Bearer <token>
{
"id": "uuid",
"eventId": "uuid",
"creatorId": "uuid",
"status": "waiting",
"memberIds": ["uuid", "uuid"],
"createdAt": "2026-04-01T00:00:00Z"
}
Visibility: members of the group, the event creator, and event authors.
Manage members
POST /groups/:id/members
{ "userId": "friend-uuid" }
Rules:
- Caller must be the group creator.
- The user being added must be a friend of the group creator.
- The user must not already be in another
pendinggroup for the same event. - Group is in
pending(cannot mutate afterapproved/rejected).
| Limit | Value |
|---|---|
| Members per group | 10 (including creator) |
DELETE /groups/:id/members/:userId
Removing members before approval recalculates the approval threshold; existing approvals still count. See Approval algorithm → edge cases.
Approvals
GET /groups/:id/approvals
{
"data": [
{
"id": "uuid",
"groupId": "uuid",
"authorId": "uuid",
"decision": "consent",
"createdAt": "2026-04-01T00:00:00Z"
}
]
}
The decision field is either consent (approve) or refuse (reject).
POST /groups/:id/approve
POST /groups/:id/reject
Authorization: caller must be a current author of the group's event. Each author can only vote once per group.
Approve — consensus algorithm
The threshold formula:
effectiveT = min(group_members, eligible_organizers)
Where eligible_organizers = accepted event authors who haven't refused yet.
Status transitions:
- approved:
consents >= effectiveT - rejected:
eligible - refuses < effectiveT(threshold can no longer be reached) - pending: otherwise
When approved:
- Group
status → approved. - A
chatof typeapproved_groupis created with all members + all authors as participants. - Response includes the new
chatId.
{
"id": "group-uuid",
"status": "approved",
"approved": true,
"chatId": "new-chat-uuid"
}
Reject
When a single author refuses and the threshold becomes unreachable,
status → rejected. No chat is created.
Errors
| Status | Reason |
|---|---|
400 | Group not in pending state |
403 | Caller is not group creator / event author / member |
404 | Group not found |
409 | Member already in another pending group for this event |
Constants
| Constant | Value |
|---|---|
MAX_MEMBERS | 10 (including creator) |
EXPIRATION_HOURS | 24 |
DEFAULT_PAGE_SIZE | 20 |
MAX_PAGE_SIZE | 100 |
Implementation notes
Source:
src/feats/groups/.
- The consensus algorithm uses
min(group_members, eligible_organizers); see Approval algorithm for the rationale. memberKeyis a canonical sorted string of member IDs, ensuring unique pending group compositions per event via a partial unique index.- Group lifecycle and chat creation are wrapped in a single Drizzle transaction so partial state cannot escape.
- Approval decisions are recorded in an append-only
like_group_audittable.