curl --request GET \
--url https://web-api.soxai.site/api/groups/{group_id}/reactions \
--header 'Authorization: Bearer <token>'import requests
url = "https://web-api.soxai.site/api/groups/{group_id}/reactions"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://web-api.soxai.site/api/groups/{group_id}/reactions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"day": "2026-10-14",
"members": {
"user456": [
{
"id": "muscle",
"emoji": "💪",
"count": 2,
"mine": true,
"uids": [
"user123",
"user789"
]
},
{
"id": "party",
"emoji": "🎉",
"count": 1,
"mine": false,
"uids": [
"user789"
]
}
]
}
}{
"error": "bad-request",
"error_msg": "Invalid day_str format. Use 'YYYY-MM-DD'."
}{
"error": "http-error",
"error_msg": "Invalid authentication credentials. <reason>"
}{
"error": "forbidden",
"error_msg": "Not enough permission"
}{
"error": "unprocessable-entity",
"error_msg": "body.<field>: <validation message>"
}{
"error": "rate-limited",
"error_msg": "Rate limit exceeded. Retry after <n> seconds."
}{
"error": "internal-server-error",
"error_msg": "Failed to fetch data: <error_message>"
}Get every member's reactions in a group
The reactions currently held on each member of the group (SOX-116).
GroupView already carries the same summaries on its cards, so this endpoint is for refreshing them on their own — it reads Firestore only and skips the InfluxDB fan-out a full GroupView call pays for.
Reactions are per day: every day starts from zero, and a
reaction belongs to the day it was sent on. count is therefore “how many members
hold this reaction on this person on day”. Omit day_str for today; pass an
earlier day_str to read (or amend) that day’s reactions, which stay stored.
“Today” is the JST calendar day (UTC+09:00) for every member of the group, not
each member’s own local day, so a reaction lands in the same bucket whoever sends
or reads it. A client that wants its own local day passes it as day_str. The
response echoes the resolved day as day.
Reactions are not health data and are not masked. A member who has hidden
their metrics (masterHidden) shows an empty data card and still sends and
receives reactions — the same line joinedAt sits on: sharing settings govern
health values, while who is in a group and what they send each other is already
visible to everyone in it. Nothing here is written to the group’s audit log,
because nothing here reads a health value.
uids lists the members currently holding that reaction. Every one of them is a
member of this group, whose roster the caller can already read in full, so this
discloses nothing new — it is what lets a client draw “Dad and Mom cheered you”
without a second call. Actors who have since left the group are filtered out, so
a count never includes somebody who is no longer here.
The list is ordered by the catalog, not by count: ordering by count makes the
row of icons jump under the user’s finger at the moment they tap one. An emoji
nobody holds is omitted, and a member with no reactions at all gets [].
Parameters
group_id(path, required) - the group whose reactions are returned.day_str(query, optional) - the day to read,YYYY-MM-DD. Defaults to today (JST).
Response
200returnsday, the day that was read, andmembers, a map of member uid to that member’s reaction list on that day. Members holding no reactions are omitted from the map.
Errors
| Status | Condition |
|---|---|
| 400 | day_str is not a YYYY-MM-DD date |
A group that does not exist is not a 404 here: the answer is built from the caller’s
own membership record, which is absent either way, so both cases are the 403 named
under Authorization.
Authorization
- Scheme:
Authorization: Bearer <idToken>orsoxai-api-key: <api key>. - Authority inside a group comes from the caller’s own membership record, never from a SOXAI
role: an
Admin,PartnerAdminorOrgAdminclaim grants nothing here. - Required: an active member of the group. A caller who is not one receives
403 not a member of this group, whether or not the group exists.
curl --request GET \
--url https://web-api.soxai.site/api/groups/{group_id}/reactions \
--header 'Authorization: Bearer <token>'import requests
url = "https://web-api.soxai.site/api/groups/{group_id}/reactions"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://web-api.soxai.site/api/groups/{group_id}/reactions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"day": "2026-10-14",
"members": {
"user456": [
{
"id": "muscle",
"emoji": "💪",
"count": 2,
"mine": true,
"uids": [
"user123",
"user789"
]
},
{
"id": "party",
"emoji": "🎉",
"count": 1,
"mine": false,
"uids": [
"user789"
]
}
]
}
}{
"error": "bad-request",
"error_msg": "Invalid day_str format. Use 'YYYY-MM-DD'."
}{
"error": "http-error",
"error_msg": "Invalid authentication credentials. <reason>"
}{
"error": "forbidden",
"error_msg": "Not enough permission"
}{
"error": "unprocessable-entity",
"error_msg": "body.<field>: <validation message>"
}{
"error": "rate-limited",
"error_msg": "Rate limit exceeded. Retry after <n> seconds."
}{
"error": "internal-server-error",
"error_msg": "Failed to fetch data: <error_message>"
}Authorizations
Path Parameters
Query Parameters
Response
A map of member uid to that member's reactions. Members with none are omitted.