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
/config
{"data": ["system", "site", "media", "security", "info"]}
Response Codes
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
/config/{scope}
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. |
{"data": {"title": "My Site", "author": {"name": "Admin", "email": "[email protected]"}}, "meta": {"overrides": ["title"], "fallback": {"title": "Grav"}}}
Response Codes
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
/config/{scope}
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. |
{"title": "Updated Site Title"}
{"data": {"title": "Updated Site Title", "author": {"name": "Admin", "email": "[email protected]"}}, "meta": {"overrides": ["title"], "fallback": {"title": "Grav"}}}
Response Codes
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
/config/{scope}/revert
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. |
{"keys": ["pages.theme", "debugger.enabled"]}
{"data": {"pages": {"theme": "quark"}, "debugger": {"enabled": false}}, "meta": {"overrides": ["pages.markdown.extra"], "fallback": {"pages.markdown.extra": false}, "reverted": true}}
Response Codes
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
/config/accounts
{"data": {"object": {"compat": {"events": true}}}}
Response Codes
This route takes precedence over GET /config/{scope}, so accounts is never read as a generic scope.
Update Accounts Config
/config/accounts
{"object": {"compat": {"events": false}}}
{"data": {"object": {"compat": {"events": false}}}}
Response Codes
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.