Skip to content

Powered by Grav + Helios

Configuration

Configuration

Endpoints for reading, updating and reverting Grav configuration scopes including system, site, media, security, plugins, themes and site-authored custom scopes, plus the Flex accounts configuration. Reads need api.config.read and writes need api.config.write; writes to system, security and...

Endpoints for reading, updating and reverting Grav configuration scopes including system, site, media, security, plugins, themes and site-authored custom scopes, plus the Flex accounts configuration. Reads need api.config.read and writes need api.config.write; writes to system, security and plugins/api, and any access to the tool-managed scheduler and backups scopes, also need an API super user. The accounts configuration is super-user only.

List Config Sections

GET /config
List the configuration scopes the admin shows as tabs. Requires `api.config.read`.
JSON
{"data": ["system", "site", "media", "security", "info"]}

Response Codes

200 Success
401 Unauthorized
403 Missing `api.config.read` permission

The list always starts with system and site and ends with info, which is a client-side system information tab rather than a readable scope. In between, sorted by name, come the core scopes media and security plus any site-, plugin- or theme-authored custom scopes (a user/config/<name>.yaml with a matching config blueprint). backups is included for super users only, and scheduler is never listed. Plugin and theme settings are not listed here; read them as plugins/{name} and themes/{name} scopes.

Get Config

GET /config/{scope}
Get the effective configuration for a scope, with secret values masked. Requires `api.config.read`.

Parameters

Name Type Description
scope required string Configuration scope: system, site, media, security, backups, scheduler, plugins/{name}, themes/{name}, or a custom scope from `user/config/<name>.yaml`
X-Config-Environment optional string Request header. Environment layer to read. Empty, `default` or `base` targets the base `user/config`; when the header is absent, the active environment is used if it has a config folder. An invalid name returns 422.
JSON
{"data": {"title": "My Site", "author": {"name": "Admin", "email": "[email protected]"}}, "meta": {"overrides": ["title"], "fallback": {"title": "Grav"}}}

Response Codes

200 Success. The `ETag` header holds the value to send as `If-Match` on the next update.
401 Unauthorized
403 Missing `api.config.read`, or the `scheduler` / `backups` scope without API super user access
404 Scope not found
422 Invalid `X-Config-Environment` header

The body is the full configuration for the selected layer, recomputed from the YAML files, so reading with X-Config-Environment: default shows the base configuration even while an environment overlay is active. Passwords, API keys and tokens come back masked. meta.overrides lists the dotted leaf paths the selected layer overrides, and meta.fallback gives the value each of those would revert to (see Revert Config).

The ETag is computed from the stored overrides, not from the full body, so it stays valid across a save and reload.

Update Config

PATCH /config/{scope}
Update configuration values with deep merge. Requires `api.config.write`.

Parameters

Name Type Description
scope required string Configuration scope: system, site, media, security, backups, scheduler, plugins/{name}, themes/{name}, or a custom scope from `user/config/<name>.yaml`
X-Config-Environment optional string Request header. Environment layer to write. Empty, `default` or `base` targets the base `user/config`; when the header is absent, the active environment is used if it has a config folder. A name that is invalid or has no folder returns 422.
JSON
{"title": "Updated Site Title"}
JSON
{"data": {"title": "Updated Site Title", "author": {"name": "Admin", "email": "[email protected]"}}, "meta": {"overrides": ["title"], "fallback": {"title": "Grav"}}}

Response Codes

200 Configuration updated
401 Unauthorized
403 Missing `api.config.write`, or a write to `system`, `security`, `plugins/api`, `scheduler` or `backups` without API super user access
404 Scope not found
409 Conflict (ETag mismatch)
422 Empty body, a changed field that fails blueprint validation, or an invalid or missing environment

The request body is deep-merged into the existing configuration, using the scope's blueprint so fields such as file lists are replaced rather than merged. Only fields whose values changed are validated against the blueprint. Only the values that differ from the parent layer are written to disk, and values supplied through GRAV_CONFIG__* environment variables are never persisted. A masked secret sent back unchanged keeps its stored value.

The response has the same structure as Get Config and carries an X-Invalidates header (config:update:<scope>, plus plugins:update:<name> and plugins:list for plugin scopes). A successful save fires onAdminSave, onAdminAfterSave and onApiConfigUpdated.

Supports optimistic concurrency control via the If-Match header.

Revert Config

POST /config/{scope}/revert
Drop overrides from a configuration layer so the values fall back to the layer beneath. Requires `api.config.write`.

Parameters

Name Type Description
scope required string Configuration scope, as for [Get Config](#get-config)
keys optional array Dotted paths of the overrides to drop. Required unless `reset` is true.
reset optional boolean Delete the layer's file for this scope, dropping every override at once. Takes precedence over `keys`.
X-Config-Environment optional string Request header. Environment layer to revert. Empty, `default` or `base` targets the base `user/config`; when the header is absent, the active environment is used if it has a config folder.
JSON
{"keys": ["pages.theme", "debugger.enabled"]}
JSON
{"data": {"pages": {"theme": "quark"}, "debugger": {"enabled": false}}, "meta": {"overrides": ["pages.markdown.extra"], "fallback": {"pages.markdown.extra": false}, "reverted": true}}

Response Codes

200 Effective configuration after the revert
401 Unauthorized
403 Missing `api.config.write`, or a write to `system`, `security`, `plugins/api`, `scheduler` or `backups` without API super user access
404 Scope not found
409 Conflict (ETag mismatch)
422 Neither a non-empty `keys` array nor `reset: true` was sent, or the environment is invalid

Reverting a key in the base layer lets the core or plugin default take over; reverting it in an environment layer lets the base value take over. If nothing remains in the layer's file after the revert, the file is removed.

The response is the effective configuration after the revert, with secrets masked, in the same structure as Get Config. meta.overrides lists the paths that still override the parent layer, and meta.reverted says whether anything on disk changed. Reverting something the layer does not override (for example reset: true when the layer has no file) still returns 200, but meta.reverted is false and onApiConfigUpdated does not fire, so no config.updated webhook is sent.

Supports optimistic concurrency control via the If-Match header, using the same ETag as Get Config.

Get Accounts Config

GET /config/accounts
Get the Flex accounts configuration (`flex.accounts`, stored in `user/config/flex/accounts.yaml`), the Configuration tab under Users. Requires `admin.super`.
JSON
{"data": {"object": {"compat": {"events": true}}}}

Response Codes

200 Success. The `ETag` header holds the value to send as `If-Match` on the next update.
401 Unauthorized
403 Not a super user

This route takes precedence over GET /config/{scope}, so accounts is never read as a generic scope.

Update Accounts Config

PATCH /config/accounts
Deep-merge the body into the Flex accounts configuration and write it to `user/config/flex/accounts.yaml`. Requires `admin.super`.
JSON
{"object": {"compat": {"events": false}}}
JSON
{"data": {"object": {"compat": {"events": false}}}}

Response Codes

200 Configuration updated
401 Unauthorized
403 Not a super user
409 Conflict (ETag mismatch)
422 Empty body

Nested maps merge and lists are replaced whole. The file is always written to the base user/config, never an environment layer, and values supplied through GRAV_CONFIG__* environment variables are not written to disk. The response carries an X-Invalidates: config:update:flex/accounts header, and the save fires onApiConfigUpdated with scope flex/accounts.

Supports optimistic concurrency control via the If-Match header.