curl --request PUT \
--url http://localhost:3000/api/notification-prefs \
--header 'Content-Type: application/json' \
--header 'Origin: <api-key>' \
--data '
{
"prefs": {
"labelChanges": true,
"profileMismatch": true,
"policyUpdates": true,
"versionUpdates": true,
"importCompleted": true,
"manualAppsPrompt": true,
"aiTimeout": true,
"jobResumed": true,
"parserFallthrough": true
}
}
'import requests
url = "http://localhost:3000/api/notification-prefs"
payload = { "prefs": {
"labelChanges": True,
"profileMismatch": True,
"policyUpdates": True,
"versionUpdates": True,
"importCompleted": True,
"manualAppsPrompt": True,
"aiTimeout": True,
"jobResumed": True,
"parserFallthrough": True
} }
headers = {
"Origin": "<api-key>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Origin: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
prefs: {
labelChanges: true,
profileMismatch: true,
policyUpdates: true,
versionUpdates: true,
importCompleted: true,
manualAppsPrompt: true,
aiTimeout: true,
jobResumed: true,
parserFallthrough: true
}
})
};
fetch('http://localhost:3000/api/notification-prefs', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_PORT => "3000",
CURLOPT_URL => "http://localhost:3000/api/notification-prefs",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'prefs' => [
'labelChanges' => true,
'profileMismatch' => true,
'policyUpdates' => true,
'versionUpdates' => true,
'importCompleted' => true,
'manualAppsPrompt' => true,
'aiTimeout' => true,
'jobResumed' => true,
'parserFallthrough' => true
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"Origin: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "http://localhost:3000/api/notification-prefs"
payload := strings.NewReader("{\n \"prefs\": {\n \"labelChanges\": true,\n \"profileMismatch\": true,\n \"policyUpdates\": true,\n \"versionUpdates\": true,\n \"importCompleted\": true,\n \"manualAppsPrompt\": true,\n \"aiTimeout\": true,\n \"jobResumed\": true,\n \"parserFallthrough\": true\n }\n}")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("Origin", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.put("http://localhost:3000/api/notification-prefs")
.header("Origin", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"prefs\": {\n \"labelChanges\": true,\n \"profileMismatch\": true,\n \"policyUpdates\": true,\n \"versionUpdates\": true,\n \"importCompleted\": true,\n \"manualAppsPrompt\": true,\n \"aiTimeout\": true,\n \"jobResumed\": true,\n \"parserFallthrough\": true\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("http://localhost:3000/api/notification-prefs")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Put.new(url)
request["Origin"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"prefs\": {\n \"labelChanges\": true,\n \"profileMismatch\": true,\n \"policyUpdates\": true,\n \"versionUpdates\": true,\n \"importCompleted\": true,\n \"manualAppsPrompt\": true,\n \"aiTimeout\": true,\n \"jobResumed\": true,\n \"parserFallthrough\": true\n }\n}"
response = http.request(request)
puts response.read_body{
"prefs": {
"label_changes": true,
"policy_updates": false,
"accessibility_changes": false,
"new_privacy_types": true,
"labelChanges": true,
"profileMismatch": true,
"policyUpdates": false,
"versionUpdates": true,
"importCompleted": true,
"manualAppsPrompt": true,
"aiTimeout": true,
"jobResumed": true,
"parserFallthrough": true
},
"stored": {},
"defaults": {
"labelChanges": true,
"profileMismatch": true,
"policyUpdates": false,
"versionUpdates": true,
"importCompleted": true,
"manualAppsPrompt": true,
"aiTimeout": true,
"jobResumed": true,
"parserFallthrough": true
}
}{
"error": "Admin token required"
}Update notification preferences
curl --request PUT \
--url http://localhost:3000/api/notification-prefs \
--header 'Content-Type: application/json' \
--header 'Origin: <api-key>' \
--data '
{
"prefs": {
"labelChanges": true,
"profileMismatch": true,
"policyUpdates": true,
"versionUpdates": true,
"importCompleted": true,
"manualAppsPrompt": true,
"aiTimeout": true,
"jobResumed": true,
"parserFallthrough": true
}
}
'import requests
url = "http://localhost:3000/api/notification-prefs"
payload = { "prefs": {
"labelChanges": True,
"profileMismatch": True,
"policyUpdates": True,
"versionUpdates": True,
"importCompleted": True,
"manualAppsPrompt": True,
"aiTimeout": True,
"jobResumed": True,
"parserFallthrough": True
} }
headers = {
"Origin": "<api-key>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Origin: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
prefs: {
labelChanges: true,
profileMismatch: true,
policyUpdates: true,
versionUpdates: true,
importCompleted: true,
manualAppsPrompt: true,
aiTimeout: true,
jobResumed: true,
parserFallthrough: true
}
})
};
fetch('http://localhost:3000/api/notification-prefs', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_PORT => "3000",
CURLOPT_URL => "http://localhost:3000/api/notification-prefs",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'prefs' => [
'labelChanges' => true,
'profileMismatch' => true,
'policyUpdates' => true,
'versionUpdates' => true,
'importCompleted' => true,
'manualAppsPrompt' => true,
'aiTimeout' => true,
'jobResumed' => true,
'parserFallthrough' => true
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"Origin: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "http://localhost:3000/api/notification-prefs"
payload := strings.NewReader("{\n \"prefs\": {\n \"labelChanges\": true,\n \"profileMismatch\": true,\n \"policyUpdates\": true,\n \"versionUpdates\": true,\n \"importCompleted\": true,\n \"manualAppsPrompt\": true,\n \"aiTimeout\": true,\n \"jobResumed\": true,\n \"parserFallthrough\": true\n }\n}")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("Origin", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.put("http://localhost:3000/api/notification-prefs")
.header("Origin", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"prefs\": {\n \"labelChanges\": true,\n \"profileMismatch\": true,\n \"policyUpdates\": true,\n \"versionUpdates\": true,\n \"importCompleted\": true,\n \"manualAppsPrompt\": true,\n \"aiTimeout\": true,\n \"jobResumed\": true,\n \"parserFallthrough\": true\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("http://localhost:3000/api/notification-prefs")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Put.new(url)
request["Origin"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"prefs\": {\n \"labelChanges\": true,\n \"profileMismatch\": true,\n \"policyUpdates\": true,\n \"versionUpdates\": true,\n \"importCompleted\": true,\n \"manualAppsPrompt\": true,\n \"aiTimeout\": true,\n \"jobResumed\": true,\n \"parserFallthrough\": true\n }\n}"
response = http.request(request)
puts response.read_body{
"prefs": {
"label_changes": true,
"policy_updates": false,
"accessibility_changes": false,
"new_privacy_types": true,
"labelChanges": true,
"profileMismatch": true,
"policyUpdates": false,
"versionUpdates": true,
"importCompleted": true,
"manualAppsPrompt": true,
"aiTimeout": true,
"jobResumed": true,
"parserFallthrough": true
},
"stored": {},
"defaults": {
"labelChanges": true,
"profileMismatch": true,
"policyUpdates": false,
"versionUpdates": true,
"importCompleted": true,
"manualAppsPrompt": true,
"aiTimeout": true,
"jobResumed": true,
"parserFallthrough": true
}
}{
"error": "Admin token required"
}Authorizations
Same-origin CSRF check. The Origin header must match the request host;
enforced for every mutating verb (POST, PUT, PATCH, DELETE).
Body
null clears the overrides on all four
flag.notifications.types.* flags and empties
notification_prefs. An object sets each flag's override
from its snake_case key (true for on, false for off),
or, if that key is missing, from its camelCase name:
labelChanges for label_changes, policyUpdates for
policy_updates. When both spellings are sent, the
snake_case one wins. A flag with neither key has its
override cleared, so it falls back to its default.
accessibility_changes and new_privacy_types have no
camelCase name, so a Settings save, which sends only the
nine camelCase keys, clears their overrides. The
camelCase keys with boolean values are also saved to
notification_prefs, and anything else is dropped.
Show child attributes
Show child attributes
{
"labelChanges": true,
"profileMismatch": true,
"policyUpdates": true,
"versionUpdates": true,
"importCompleted": true,
"manualAppsPrompt": true,
"aiTimeout": true,
"jobResumed": true,
"parserFallthrough": true
}
Response
The resolved preferences after the write.
Per-type notification switches under two sets of names. The four
snake_case keys are the flag.notifications.types.* feature flags.
The nine camelCase keys are the types the Settings view and the bell
use. Two types are in both sets: labelChanges is the same switch as
label_changes, and policyUpdates the same as policy_updates.
The other seven camelCase types are stored in the
notification_prefs setting. Privacy-policy text changes are opt-in: policy_updates and
policyUpdates stay false until
flag.notifications.types.policy_updates is on.
Every switch's current value, in this order: the four snake_case
flag keys, each resolved through the flag cascade (your override,
then the focus default, then the hard default), then all nine
camelCase keys. labelChanges and policyUpdates repeat their
flags' values. The other seven come from notification_prefs,
with defaults filling any type that was never saved. If the flag
resolver fails, prefs holds only the camelCase keys saved in
notification_prefs.
Show child attributes
Show child attributes
Same values as prefs.
Show child attributes
Show child attributes
The Settings view's defaults, keyed by its own type names. Fixed values, not the flags' resolved state.
Show child attributes
Show child attributes
{
"labelChanges": true,
"profileMismatch": true,
"policyUpdates": false,
"versionUpdates": true,
"importCompleted": true,
"manualAppsPrompt": true,
"aiTimeout": true,
"jobResumed": true,
"parserFallthrough": true
}