Settings API
Settings are stored server-side at three scopes and follow your login across browsers and devices.
| Scope | Applies to | Write permission |
|---|---|---|
user | Just you | Any authenticated user (writes your own) |
workspace | Everyone in the workspace | tenant:update |
tenant | The whole tenant | tenant:update |
Read all three scopes
GET /api/v1/tenants/{tenantID}/settings/effective
{
"user": {
"theme": "dark",
"enabled_frameworks": ["nist80053", "fedramp_moderate"]
},
"workspace": {
"risk_thresholds": { "critical": 80, "high": 60 }
},
"tenant": {
"require_mfa": false
}
}
Despite the name, no precedence is applied and no single flattened object is returned. You get the three scopes side by side and decide which wins for your use case. If you expect a merged result, you must merge client-side.
Per-scope endpoints
GET /api/v1/tenants/{tenantID}/settings/user PUT (same path)
GET /api/v1/tenants/{tenantID}/settings/workspace PUT (same path, needs tenant:update)
GET /api/v1/tenants/{tenantID}/settings/tenant-prefs PUT (same path, needs tenant:update)
Each GET returns that scope's settings object directly — not wrapped in an envelope:
{ "theme": "dark", "enabled_frameworks": ["nist80053"] }
The user scope always reads and writes your own settings, resolved from your token. There is
no way to read another user's settings through this API.
Writing settings
PUT accepts a flat JSON object and applies it as a partial update — each key is upserted
individually, so keys you omit are left untouched:
{ "theme": "light" }
Response:
{ "status": "ok" }
To remove a setting, write an explicit empty value ("", [], null as appropriate). There is no
delete operation.
A scope with nothing stored returns {}, and an individual key that was never written is simply
absent. The API does not inject defaults. Always supply your own fallback when reading:
const theme = settings.theme ?? "dark";
Keys are free-form
Settings are stored as arbitrary key/value pairs; there is no fixed schema and unknown keys are accepted and returned as written. The keys shown here are the ones the Infracast UI uses — treat them as examples, not a contract, and namespace your own keys to avoid collisions.
enabled_frameworks behaves differently
Two behaviours are worth knowing before you set it:
1. It is a user setting. Each user chooses which compliance frameworks they see. Setting it
for one user does not change what teammates see.
2. Empty means nothing is shown. If enabled_frameworks is unset or empty, compliance views
render zero rows — this is filtering, not missing data. A new user who has never opened Settings
sees an empty compliance table until frameworks are selected. If a colleague sees findings and you
do not, compare this setting first.
Updating enabled_frameworks automatically starts a compliance scan so findings appear without
waiting for the next scheduled run. Expect a short delay before results populate.
Related
- API Overview — authentication and common conventions
- First Audit — running a compliance audit