curl --request GET \
--url https://web-api.dev.soxai.site/api/groups/{group_id}/reactions \
--header 'Authorization: Bearer <token>'import requests
url = "https://web-api.dev.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.dev.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
A request authenticated with a Sandbox soxai-api-key is answered 403 This endpoint is not available in the sandbox., because it is internal or operational, outside the Sandbox surface. It is published here because the Sandbox runs the same build; use it in Production. See Sandbox.
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.dev.soxai.site/api/groups/{group_id}/reactions \
--header 'Authorization: Bearer <token>'import requests
url = "https://web-api.dev.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.dev.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.