Blueprints
Endpoints for retrieving blueprint schemas used for page templates, user accounts, groups, plugins, themes, configuration and permission definitions, plus GET /blueprint-files, which lists files for blueprint folder picker fields. Uploading and deleting files for blueprint file fields is covered...
Endpoints for retrieving blueprint schemas used for page templates, user accounts, groups, plugins, themes, configuration and permission definitions, plus GET /blueprint-files, which lists files for blueprint folder picker fields. Uploading and deleting files for blueprint file fields is covered under Media: POST /blueprint-upload and DELETE /blueprint-upload.
List Page Types
/blueprints/pages
Parameters
| Name | Type | Description |
|---|---|---|
| modular optional | boolean | Query parameter: `true` (or `1` / `yes`) lists modular templates instead of regular page templates |
{"data": [{"type": "default", "label": "Default"}, {"type": "blog", "label": "Blog"}, {"type": "post", "label": "Post"}]}
Response Codes
Get Page Blueprint
/blueprints/pages/{template}
Parameters
| Name | Type | Description |
|---|---|---|
| template required | string | The page template name (e.g. default, blog, post, or modular/hero for a modular template) |
{"data": {"name": "default", "title": "Default", "type": null, "child_type": null, "validation": "loose", "fields": [{"name": "header.title", "type": "text", "label": "Title"}]}}
Response Codes
Get User Blueprint
/blueprints/users
{"data": {"name": "account", "title": "Account", "type": null, "child_type": null, "validation": "loose", "fields": [{"name": "username", "type": "text", "label": "Username"}]}}
Response Codes
Get Permissions
/blueprints/users/permissions
{"data": [{"name": "admin", "label": "Admin", "children": [{"name": "admin.login", "label": "Login"}]}]}
Response Codes
Get Plugin Page Blueprint
/blueprints/plugins/{plugin}/pages/{pageId}
Parameters
| Name | Type | Description |
|---|---|---|
| plugin required | string | The plugin slug |
| pageId required | string | The page blueprint identifier (matches the filename without extension) |
{"data": {"name": "licenses", "title": "Licenses", "type": null, "child_type": null, "validation": "loose", "fields": [{"name": "licenses", "type": "array", "label": "Licenses"}]}}
Response Codes
Get Plugin Blueprint
/blueprints/plugins/{plugin}
Parameters
| Name | Type | Description |
|---|---|---|
| plugin required | string | Plugin slug. |
{"data": {"name": "simplesearch", "title": "SimpleSearch", "type": null, "child_type": null, "validation": "loose", "fields": [{"name": "enabled", "type": "toggle", "label": "Plugin status"}]}}
Response Codes
Get Theme Blueprint
/blueprints/themes/{theme}
Parameters
| Name | Type | Description |
|---|---|---|
| theme required | string | Theme slug. |
{"data": {"name": "quark", "title": "Quark", "type": null, "child_type": null, "validation": "loose", "fields": [{"name": "dropdown.enabled", "type": "toggle", "label": "Dropdown in navbar"}]}}
Response Codes
Get Config Blueprint
/blueprints/config/{scope}
Parameters
| Name | Type | Description |
|---|---|---|
| scope required | string | One of the core scopes `system`, `site`, `media`, `security`, `scheduler`, `backups`, or a custom top-level config scope the site defines (for example `user/blueprints/config/<scope>.yaml`). Other system blueprints such as `streams` are refused. |
{"data": {"name": "system", "title": "System Configuration", "type": null, "child_type": null, "validation": "loose", "fields": [{"name": "cache.enabled", "type": "toggle", "label": "Caching"}]}}
Response Codes
Resolve Data Options
/data/resolve
Parameters
| Name | Type | Description |
|---|---|---|
| callable required | string | Fully-qualified `\Class\Name::method` to invoke. Must be an approved data provider (on the core allowlist, or registered via `Blueprint::addAllowedDynamicCallable()`). |
| type optional | string | Extra arg passed when `callable` is `Grav\Common\Page\Pages::pageTypes` (`standard` / `modular`). Defaults to `standard`. |
{"data": [{"value": "default", "label": "Default"}, {"value": "blog", "label": "Blog"}]}
Response Codes
Get Group Blueprint
/blueprints/groups
{"data": {"name": "group", "title": "Group", "type": null, "child_type": null, "validation": "loose", "fields": [{"name": "readableName", "type": "text", "label": "Display Name"}]}}
Response Codes
Get New Group Blueprint
/blueprints/groups/new
{"data": {"name": "group_new", "title": "Add Group", "type": null, "child_type": null, "validation": "loose", "fields": [{"name": "groupname", "type": "text", "label": "Group Name"}]}}
Response Codes
Get Accounts Config Blueprint
/blueprints/config/accounts
{"data": {"name": "accounts", "title": "Accounts Configuration", "type": null, "child_type": null, "validation": "loose", "fields": [{"name": "object.cache.index.enabled", "type": "toggle", "label": "Enable Index Caching"}]}}
Response Codes
List Blueprint Folder Files
/blueprint-files
Parameters
| Name | Type | Description |
|---|---|---|
| folder required | string | Query parameter: folder to list. A Grav stream (`user://media`, `theme://images`, `account://`), a `self@:subpath` token resolved against `scope`, or a path relative to `user/` |
| scope optional | string | Query parameter: blueprint owner used to resolve `self@:`. One of `plugins/<slug>`, `themes/<slug>`, `pages/<route>`, `users/<username>` |
| accept optional | string | Query parameter: comma-separated filter of extensions (`.pdf`, `*.jpg`) or MIME patterns (`image/*`). `*` matches everything |
{"data": [{"filename": "logo.png", "url": "/user/themes/quark/images/logo.png", "type": "image/png", "size": 18432, "dimensions": {"width": 400, "height": 120}, "thumbnail_url": "/api/v1/thumbnails/3f2a9c1e4b5d6a7f8e9d0c1b2a394857.png", "modified": "2026-09-01T10:15:00+00:00"}], "meta": {"pagination": {"page": 1, "per_page": 1, "total": 1, "total_pages": 1}, "folder": "themes/quark/images", "scope": null, "exists": true}, "links": {"self": "/api/v1/blueprint-files?page=1&per_page=1"}}
Response Codes
The result uses the paginated envelope but is never actually paginated: every matching file comes back on page 1.
The page-media literals @self and self@ (with no subpath) are not handled here, since the client already has a page's media from GET /pages/{route}/media. They return a standard 422 validation error whose errors entry for folder carries the message PAGE_MEDIA_ONLY:
{"status": 422, "title": "Unprocessable Entity", "detail": "Use /pages/{route}/media for @self / self@ folders.", "errors": [{"field": "folder", "message": "PAGE_MEDIA_ONLY"}]}