curl --request POST \
--url https://web-api.dev.soxai.site/oauth2/users/totp_required \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"uid_list": [
"user_123"
],
"required": true
}
'import requests
url = "https://web-api.dev.soxai.site/oauth2/users/totp_required"
payload = {
"uid_list": ["user_123"],
"required": 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({uid_list: ['user_123'], required: true})
};
fetch('https://web-api.dev.soxai.site/oauth2/users/totp_required', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"success_count": 1,
"success_uids": [
"user123"
],
"failed_count": 1,
"failed_uids": [
"user789"
],
"out_of_scope_count": 0,
"out_of_scope_uids": []
}{
"error": "bad-request",
"error_msg": "Too many uids. Maximum allowed is 200."
}{
"error": "http-error",
"error_msg": "Invalid authentication credentials. <reason>"
}{
"error": "forbidden",
"error_msg": "Not enough permission"
}{
"error": "not-found",
"error_msg": "Org '<org_id>' not found"
}{
"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>"
}Require or release two-factor for a list of users
A request authenticated with a Sandbox soxai-api-key is answered 403 This endpoint is not available in the sandbox., because it belongs to the separate OAuth2 authentication flow. It is published here because the Sandbox runs the same build; use it in Production. See Sandbox.
[Admin / PartnerAdmin / OrgAdmin] Bulk enable or disable 2FA requirement for a list of users.
When required=True: Sets required=True on /totp_info (creates the document if absent). If the user has never enrolled TOTP, they will be forced to set it up on next login. If the user already has a confirmed TOTP setup, they will continue to use it.
When required=False: Sets required=False and confirmed=False on /totp_info. Both fields must be cleared because the login flow checks confirmed first; leaving confirmed=True would still present the TOTP screen even if required=False. The stored secret is left in place but never reused: the next setup screen rotates it before displaying a QR code.
A uid that belongs to no Firebase Auth user is reported in failed_uids with error USER_NOT_FOUND and is never written.
Returns success_uids and failed_uids with per-uid error details.
Parameters
- Body (
TotpSetRequiredRequest):uid_list(at most 200) andrequired.
Response
200{"success_uids", "failed_uids"}. A uid that was refused by scope or that belongs to no account is infailed_uidswith its reason; the rest are applied.
Errors
| Status | Condition |
|---|---|
| 400 | uid_list holds more than 200 entries |
| 403 | The caller holds none of the three roles below |
| 404 | The caller is an OrgAdmin whose own organization no longer exists. No uid is written |
Authorization
- Scheme:
Authorization: Bearer <idToken>orsoxai-api-key: <api key>. Admin,PartnerAdminorOrgAdmin.- The caller’s scope partitions
uid_listrather than admitting or refusing the whole request: uids the caller cannot reach are reported infailed_uidsand left unwritten, while the rest are applied. A request naming only unreachable uids is therefore still a200. Adminreaches every uid,PartnerAdminthe users registered under its own company,OrgAdminthe members of its own organization, and a caller holding both scoped roles the intersection.
curl --request POST \
--url https://web-api.dev.soxai.site/oauth2/users/totp_required \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"uid_list": [
"user_123"
],
"required": true
}
'import requests
url = "https://web-api.dev.soxai.site/oauth2/users/totp_required"
payload = {
"uid_list": ["user_123"],
"required": 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({uid_list: ['user_123'], required: true})
};
fetch('https://web-api.dev.soxai.site/oauth2/users/totp_required', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"success_count": 1,
"success_uids": [
"user123"
],
"failed_count": 1,
"failed_uids": [
"user789"
],
"out_of_scope_count": 0,
"out_of_scope_uids": []
}{
"error": "bad-request",
"error_msg": "Too many uids. Maximum allowed is 200."
}{
"error": "http-error",
"error_msg": "Invalid authentication credentials. <reason>"
}{
"error": "forbidden",
"error_msg": "Not enough permission"
}{
"error": "not-found",
"error_msg": "Org '<org_id>' not found"
}{
"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
Body
Response
Per-uid outcome. A uid refused by scope or belonging to no account comes back under failed_uids with its reason while the rest are applied.