Pages
Endpoints for managing Grav pages including listing, creating, updating, deleting, moving, and reordering.
Endpoints for managing Grav pages including listing, creating, updating, deleting, moving, and reordering.
List Pages
/pages
Parameters
| Name | Type | Description |
|---|---|---|
| page optional | integer | Page number for pagination (default 1). |
| per_page optional | integer | Number of results per page (default 20, max 100). |
| sort optional | string | Sort field: `date`, `title`, `slug`, `modified`, `order`, or `default`. `default` with `children_of` uses native page ordering. |
| order optional | string | Sort direction: `asc` or `desc`. |
| search optional | string | Full-text search across indexed page fields (Flex backend only). |
| published optional | boolean | Filter by published state. |
| visible optional | boolean | Filter by visible state. |
| routable optional | boolean | Filter by routable state. |
| template optional | string | Filter by page template name. |
| parent optional | string | Filter to descendants whose route starts with this parent path (e.g. `/blog` returns `/blog/post-1`, `/blog/sub/post-2`). |
| children_of optional | string | Filter to direct children of a given route. |
| root optional | string | Restrict the listing to a subtree root. |
| translations optional | boolean | Include translation metadata on each item: `translated_languages`, `untranslated_languages`, `has_default_file`, `explicit_language_files`. |
{"data": [{"route": "/blog", "slug": "blog", "title": "Blog", "template": "blog", "published": true}], "meta": {"total": 42, "page": 1, "per_page": 20}}
Response Codes
Get Page
/pages/{route}
Parameters
| Name | Type | Description |
|---|---|---|
| route required | string | The page route (e.g. `/blog/my-post`). |
| summary optional | boolean | Include page summary in the response. |
| render optional | boolean | Return rendered HTML content instead of raw markdown. |
| children optional | boolean | Include child pages in the response. |
| translations optional | boolean | Include translation metadata: `translated_languages`, `untranslated_languages`, `has_default_file` (whether an untyped `{template}.md` exists), `explicit_language_files` (the subset of languages backed by a real `{template}.{lang}.md` on disk). |
| lang optional | string | Return the page in a specific language (overrides the request's active language). |
{"data": {"route": "/blog/my-post", "slug": "my-post", "title": "My Post", "template": "post", "content": "# Hello World", "header": {"published": true}, "media": [], "has_default_file": true, "explicit_language_files": ["fr"]}}
Response Codes
Create Page
/pages
Parameters
| Name | Type | Description |
|---|---|---|
| route required | string | The route where the page will be created |
| title required | string | The page title |
| template optional | string |
Page template to use
Default:
default |
| content optional | string | Markdown content for the page body |
| header optional | object | Page header/frontmatter values |
| order optional | integer | Numeric ordering prefix for the page |
| lang optional | string | Language code for multi-language sites |
{"route": "/blog/new-post", "title": "New Post", "template": "post", "content": "# New Post\nContent here"}
{"data": {"route": "/blog/new-post", "title": "New Post"}}
Response Codes
Update Page
/pages/{route}
Parameters
| Name | Type | Description |
|---|---|---|
| route required | string | The page route (path parameter) |
| title optional | string | Updated page title |
| content optional | string | Updated markdown content |
| header optional | object | Header values to merge into existing frontmatter |
| template optional | string | Change the page template |
| published optional | boolean | Set the published state |
| visible optional | boolean | Set the visible state |
{"title": "Updated Title", "header": {"subtitle": "New subtitle"}}
Response Codes
Supports optimistic concurrency control via the If-Match header. Include the ETag from your last GET request to prevent overwriting concurrent changes.
Delete Page
/pages/{route}
Parameters
| Name | Type | Description |
|---|---|---|
| route required | string | The page route to delete |
| children optional | boolean |
Also delete child pages
Default:
true |
| lang optional | string | Delete only a specific language version |
Response Codes
Move Page
/pages/{route}/move
Parameters
| Name | Type | Description |
|---|---|---|
| route required | string | The current page route (path parameter) |
| parent required | string | The target parent route |
| slug optional | string | Optionally rename the slug during the move |
| order optional | integer | Numeric ordering prefix at the new location |
{"parent": "/blog", "slug": "moved-post"}
Response Codes
Reorder Pages
/pages/{route}/reorder
Parameters
| Name | Type | Description |
|---|---|---|
| route required | string | The parent page route (path parameter) |
| order required | array | Array of child slugs in the desired order |
{"order": ["first-post", "second-post", "third-post"]}
Response Codes
Copy Page
/pages/{route}/copy
Parameters
| Name | Type | Description |
|---|---|---|
| route required | string | Source page route (path param). |
| route required | string | Destination route for the copy (body field). |
{"route": "/blog/my-post-copy"}
{"data": {"route": "/blog/my-post-copy", "slug": "my-post-copy", "title": "My Post", "template": "post"}}
Response Codes
List Page Languages
/pages/{route}/languages
Parameters
| Name | Type | Description |
|---|---|---|
| route required | string | The page route (path param). |
{"data": {"route": "/blog/my-post", "default_language": "en", "translated": {"en": "default.en.md", "fr": "default.fr.md"}, "untranslated": ["de", "es"]}}
Response Codes
Note
When the site has only a bare default.md (no language suffix) and multilang is enabled, Grav will report the default language in translated as a fallback. Use GET /pages/{route}?translations=true to get the has_default_file / explicit_language_files fields that disambiguate which languages are backed by a real on-disk file.
Create Translation
/pages/{route}/translate
Parameters
| Name | Type | Description |
|---|---|---|
| route required | string | The page route (path param). |
| lang required | string | Target language code (must match a configured site language). |
| title optional | string | Title for the translation (defaults to the source page title). |
| content optional | string | Raw markdown content (defaults to the source page content). |
| header optional | object | Frontmatter object (defaults to a copy of the source page header, with `title` merged in). |
{"lang": "fr", "title": "Mon article", "content": "# Bonjour"}
{"data": {"route": "/blog/my-post", "lang": "fr", "title": "Mon article", "content": "# Bonjour"}}
Response Codes
Adopt Language
/pages/{route}/adopt-language
Parameters
| Name | Type | Description |
|---|---|---|
| route required | string | The page route (path param). |
| lang required | string | Language code to adopt the base file as. |
{"lang": "en"}
{"data": {"route": "/blog/my-post", "lang": "en"}}
Response Codes
Sync Translation
/pages/{route}/sync
Parameters
| Name | Type | Description |
|---|---|---|
| route required | string | The page route (path param). |
| source_lang required | string | Language code to copy content from. |
| target_lang required | string | Language code to overwrite. |
{"source_lang": "en", "target_lang": "fr"}
{"data": {"route": "/blog/my-post", "lang": "fr", "title": "My Post", "content": "# Hello"}}
Response Codes
Compare Translations
/pages/{route}/compare
Parameters
| Name | Type | Description |
|---|---|---|
| route required | string | The page route (path param). |
| source required | string | Source language code (query param). |
| target required | string | Target language code (query param). |
{"data": {"route": "/blog/my-post", "source": {"lang": "en", "exists": true, "title": "My Post", "content": "# Hello", "header": {"title": "My Post"}, "modified": "2026-04-17T10:00:00+00:00"}, "target": {"lang": "fr", "exists": false, "title": "My Post", "content": "# Hello", "header": {"title": "My Post"}, "modified": null}}}
Response Codes
Batch Page Operations
/pages/batch
Parameters
| Name | Type | Description |
|---|---|---|
| operation required | string | One of: `publish`, `unpublish`, `delete`, `copy`. |
| routes required | array | Non-empty array of page routes. |
| options optional | object | Operation-specific options (e.g., destination parent for `copy`). |
{"operation": "publish", "routes": ["/blog/post-1", "/blog/post-2"]}
{"data": {"operation": "publish", "results": [{"route": "/blog/post-1", "status": "success"}, {"route": "/blog/post-2", "status": "error", "message": "Page not found"}], "total": 2, "successful": 1, "failed": 1}}
Response Codes
Reorganize Pages
/pages/reorganize
Parameters
| Name | Type | Description |
|---|---|---|
| operations required | array | Non-empty array of operation objects. Each must have a `route`; optional fields are `parent` (new parent route) and `position` (integer, controls the numeric prefix on the folder). |
{"operations": [{"route": "/blog/post-1", "parent": "/archive", "position": 1}, {"route": "/blog/post-2", "position": 3}]}
{"data": [{"route": "/archive/post-1", "slug": "post-1", "title": "Post 1", "order": 1, "parent": "/archive"}, {"route": "/blog/post-2", "slug": "post-2", "title": "Post 2", "order": 3, "parent": "/blog"}]}
Response Codes
List Taxonomy
/taxonomy
{"data": {"category": ["blog", "docs"], "tag": ["php", "grav", "api"]}}
Response Codes
List Site Languages
/languages
{"data": {"enabled": true, "languages": [{"code": "en", "name": "English", "native_name": "English", "rtl": false, "is_default": true}, {"code": "fr", "name": "French", "native_name": "Français", "rtl": false, "is_default": false}], "default": "en", "active": "en"}}