Join a family group with an invite code
curl --request POST \
--url https://web-api.dev.soxai.site/api/groups/join \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"groupId": "group_123",
"code": "ABC123",
"displayName": "Jane",
"sharedFields": {
"sleep_score": true
}
}
'import requests
url = "https://web-api.dev.soxai.site/api/groups/join"
payload = {
"groupId": "group_123",
"code": "ABC123",
"displayName": "Jane",
"sharedFields": { "sleep_score": True }
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
groupId: 'group_123',
code: 'ABC123',
displayName: 'Jane',
sharedFields: {sleep_score: true}
})
};
fetch('https://web-api.dev.soxai.site/api/groups/join', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"uid": "user456",
"groupId": "b7d1f0c9a2e4d6f8b0c1",
"role": "member",
"status": "active",
"displayName": "Dad",
"joinedAt": "2026-08-03T09:30:00+00:00",
"masterHidden": false,
"sharedFields": {
"sleep_score": true,
"health_score": true,
"activity_score": false,
"sleep_total_time_exclude_awake": false,
"activity_steps": true,
"heat_stroke_severity": true,
"last_sync_time": true
},
"sharingScope": "group_only",
"alreadyJoined": false
}{
"error": "bad-request",
"error_msg": "displayName must not be empty"
}{
"error": "http-error",
"error_msg": "Invalid authentication credentials. <reason>"
}{
"error": "forbidden",
"error_msg": "Not enough permission"
}{
"error": "not-found",
"error_msg": "group not found"
}{
"error": "conflict",
"error_msg": "invite code is expired"
}{
"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>"
}Family Groups
Join a family group with an invite code
Not callable with a Sandbox key
A request authenticated with a Sandbox soxai-api-key is answered 403 This endpoint is not available in the sandbox., because it changes state that every Sandbox caller shares. It is published here because the Sandbox runs the same build; use it in Production. See Sandbox.
Join a group using the groupId and code carried by an invite deep
link.
Joining again with the same account is idempotent: the existing membership is returned and no invite use is consumed, so a re-tapped link does not exhaust the code.
Parameters
- Body (
GroupJoin):groupId,codeanddisplayNameare required.sharedFieldsis the initial per-metric sharing selection; omit it to share nothing until the member chooses to.
Response
200returns the caller’s membership in that group, asmember.- Joining again returns the existing membership and consumes no further use of the invite code.
Errors
| Status | Condition |
|---|---|
| 400 | displayName is empty |
| 404 | The group does not exist |
| 409 | The invite code is unknown, expired or exhausted; the caller already belongs to 20 groups; or the group already holds 50 members |
Authorization
- Scheme:
Authorization: Bearer <idToken>orsoxai-api-key: <api key>. - Any authenticated caller. Group membership is not involved, because this call is what creates or joins one.
POST
/
api
/
groups
/
join
Join a family group with an invite code
curl --request POST \
--url https://web-api.dev.soxai.site/api/groups/join \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"groupId": "group_123",
"code": "ABC123",
"displayName": "Jane",
"sharedFields": {
"sleep_score": true
}
}
'import requests
url = "https://web-api.dev.soxai.site/api/groups/join"
payload = {
"groupId": "group_123",
"code": "ABC123",
"displayName": "Jane",
"sharedFields": { "sleep_score": True }
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
groupId: 'group_123',
code: 'ABC123',
displayName: 'Jane',
sharedFields: {sleep_score: true}
})
};
fetch('https://web-api.dev.soxai.site/api/groups/join', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"uid": "user456",
"groupId": "b7d1f0c9a2e4d6f8b0c1",
"role": "member",
"status": "active",
"displayName": "Dad",
"joinedAt": "2026-08-03T09:30:00+00:00",
"masterHidden": false,
"sharedFields": {
"sleep_score": true,
"health_score": true,
"activity_score": false,
"sleep_total_time_exclude_awake": false,
"activity_steps": true,
"heat_stroke_severity": true,
"last_sync_time": true
},
"sharingScope": "group_only",
"alreadyJoined": false
}{
"error": "bad-request",
"error_msg": "displayName must not be empty"
}{
"error": "http-error",
"error_msg": "Invalid authentication credentials. <reason>"
}{
"error": "forbidden",
"error_msg": "Not enough permission"
}{
"error": "not-found",
"error_msg": "group not found"
}{
"error": "conflict",
"error_msg": "invite code is expired"
}{
"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
HTTPBearerSoxaiApiKey
Body
application/json
Response
The caller's membership in that group. Joining again returns the existing membership with alreadyJoined true and consumes no further use of the code.