Skip to main content

Settings API

Settings are stored server-side at three scopes and follow your login across browsers and devices.

ScopeApplies toWrite permission
userJust youAny authenticated user (writes your own)
workspaceEveryone in the workspacetenant:update
tenantThe whole tenanttenant: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
}
}
"Effective" returns three scopes — it does not merge them

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.

Unset keys return nothing — not a default

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.

Changing frameworks triggers a scan

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.