Files
intotheeast-com-content/plugins/api/grav-api.postman_collection.json
T

5992 lines
190 KiB
JSON

{
"info": {
"_postman_id": "grav-api-collection-v1",
"name": "Grav CMS API",
"description": "Complete API collection for the Grav CMS RESTful API plugin.\n\n## Setup\n\n1. Set the `base_url` variable to your Grav site URL (e.g., `https://localhost/grav-api`)\n2. Set the `api_key` variable to a valid API key (generate via `bin/plugin api keys:generate`)\n3. Set `grav_environment` to your Grav environment (default: `localhost`)\n4. All requests include `X-API-Key` and `X-Grav-Environment` headers automatically\n\n## Authentication\n\nAll requests (except `/auth/*` endpoints) require the `X-API-Key` header.\nThe `X-Grav-Environment` header is included on all requests to ensure correct environment context.",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"variable": [
{
"key": "base_url",
"value": "http://localhost",
"type": "string"
},
{
"key": "api_key",
"value": "grav_your_api_key_here",
"type": "string"
},
{
"key": "access_token",
"value": "",
"type": "string"
},
{
"key": "refresh_token",
"value": "",
"type": "string"
},
{
"key": "api_prefix",
"value": "/api/v1",
"type": "string"
},
{
"key": "test_username",
"value": "testuser",
"type": "string"
},
{
"key": "test_api_key_id",
"value": "",
"type": "string"
},
{
"key": "grav_environment",
"value": "localhost",
"type": "string"
},
{
"key": "page_route",
"value": "blog",
"type": "string"
},
{
"key": "lang",
"value": "en",
"type": "string"
},
{
"key": "package_slug",
"value": "",
"type": "string"
},
{
"key": "webhook_id",
"value": "",
"type": "string"
},
{
"key": "notification_id",
"value": "",
"type": "string"
},
{
"key": "username",
"value": "admin",
"type": "string"
},
{
"key": "password",
"value": "",
"type": "string"
},
{
"key": "test_page_route",
"value": "",
"type": "string"
}
],
"item": [
{
"name": "Setup",
"description": "Setup requests that run before all other tests. Creates test data and authenticates.",
"item": [
{
"name": "Setup: Login",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test(\"Status is 200\", () => pm.response.to.have.status(200));",
"pm.test(\"Has access_token\", () => pm.expect(res.data).to.have.property(\"access_token\"));",
"",
"if (res.data && res.data.access_token) {",
" pm.collectionVariables.set(\"access_token\", res.data.access_token);",
" pm.collectionVariables.set(\"refresh_token\", res.data.refresh_token);",
"}"
]
}
}
],
"request": {
"auth": {
"type": "noauth"
},
"method": "POST",
"header": [
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"username\": \"{{username}}\",\n \"password\": \"{{password}}\"\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/auth/token",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"auth",
"token"
]
},
"description": "Authenticate and save access_token and refresh_token to collection variables."
}
},
{
"name": "Setup: Create Test Page",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"if (res.data && res.data.route) {",
" pm.collectionVariables.set('test_page_route', res.data.route);",
"}",
"",
"pm.test('Status is 201', () => pm.response.to.have.status(201));",
"pm.test('Has route', () => pm.expect(res.data).to.have.property('route'));"
]
}
}
],
"request": {
"method": "POST",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"route\": \"/newman-test-page\",\n \"title\": \"Newman Test Page\",\n \"template\": \"default\",\n \"content\": \"# Test Page\\nCreated by Newman test runner.\"\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/pages",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"pages"
]
},
"description": "Create a test page used by subsequent tests. Saves the route to test_page_route."
}
},
{
"name": "Setup: Create Test Webhook",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test(\"Status is 201\", () => pm.response.to.have.status(201));",
"",
"if (res.data && res.data.id) {",
" pm.collectionVariables.set(\"webhook_id\", res.data.id);",
"}"
]
}
}
],
"request": {
"method": "POST",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"url\": \"https://httpbin.org/post\",\n \"events\": [\n \"page.created\"\n ],\n \"secret\": \"newman-test-secret\"\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/webhooks",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"webhooks"
]
},
"description": "Create a test webhook. Saves the webhook_id to collection variables."
}
}
]
},
{
"name": "Auth",
"description": "Authentication endpoints. These do not require prior authentication.",
"item": [
{
"name": "Login (Get JWT Tokens)",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"if (res.data && res.data.access_token) {",
" pm.collectionVariables.set('access_token', res.data.access_token);",
" pm.collectionVariables.set('refresh_token', res.data.refresh_token);",
"}",
"",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has access_token', () => pm.expect(res.data).to.have.property('access_token'));",
"pm.test('Has refresh_token', () => pm.expect(res.data).to.have.property('refresh_token'));",
"pm.test('Token type is Bearer', () => pm.expect(res.data.token_type).to.equal('Bearer'));",
"pm.test('Has expires_in', () => pm.expect(res.data.expires_in).to.be.a('number'));"
]
}
}
],
"request": {
"auth": {
"type": "noauth"
},
"method": "POST",
"header": [
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"username\": \"{{username}}\",\n \"password\": \"{{password}}\"\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/auth/token",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"auth",
"token"
]
},
"description": "Exchange username/password for JWT access and refresh tokens. The access token is automatically saved for use by other requests."
}
},
{
"name": "Refresh Token",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"if (res.data && res.data.access_token) {",
" pm.collectionVariables.set('access_token', res.data.access_token);",
" pm.collectionVariables.set('refresh_token', res.data.refresh_token);",
"}",
"",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('New tokens issued', () => pm.expect(res.data).to.have.property('access_token'));"
]
}
}
],
"request": {
"auth": {
"type": "noauth"
},
"method": "POST",
"header": [
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"refresh_token\": \"{{refresh_token}}\"\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/auth/refresh",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"auth",
"refresh"
]
},
"description": "Exchange a refresh token for a new access/refresh token pair. The old refresh token is revoked (token rotation)."
}
},
{
"name": "Revoke Token",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 204', () => pm.response.to.have.status(204));"
]
}
}
],
"request": {
"auth": {
"type": "noauth"
},
"method": "POST",
"header": [
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"refresh_token\": \"{{refresh_token}}\"\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/auth/revoke",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"auth",
"revoke"
]
},
"description": "Revoke a refresh token, preventing it from being used to generate new access tokens."
}
}
]
},
{
"name": "Pages",
"description": "Content management \u2014 create, read, update, delete, move, and copy pages.",
"item": [
{
"name": "List Pages",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has data array', () => pm.expect(res.data).to.be.an('array'));",
"pm.test('Has pagination meta', () => pm.expect(res.meta.pagination).to.have.property('total'));",
"pm.test('Has links', () => pm.expect(res.links).to.have.property('self'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/pages?page=1&per_page=20",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"pages"
],
"query": [
{
"key": "page",
"value": "1"
},
{
"key": "per_page",
"value": "20"
},
{
"key": "sort",
"value": "date",
"disabled": true
},
{
"key": "order",
"value": "desc",
"disabled": true
},
{
"key": "published",
"value": "true",
"disabled": true
},
{
"key": "template",
"value": "post",
"disabled": true
},
{
"key": "routable",
"value": "true",
"disabled": true
},
{
"key": "visible",
"value": "true",
"disabled": true
},
{
"key": "parent",
"value": "blog",
"disabled": true
}
]
},
"description": "List all pages with filtering, sorting, and pagination.\n\n**Filters** (enable as needed):\n- `published` - true/false\n- `template` - page template name\n- `routable` - true/false\n- `visible` - true/false\n- `parent` - parent route prefix\n\n**Sorting**: `sort` (date, title, slug, modified, order) + `order` (asc, desc)",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "List Pages (Filtered: Blog Posts)",
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/pages?published=true&template=post&parent=blog&sort=date&order=desc",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"pages"
],
"query": [
{
"key": "published",
"value": "true"
},
{
"key": "template",
"value": "post"
},
{
"key": "parent",
"value": "blog"
},
{
"key": "sort",
"value": "date"
},
{
"key": "order",
"value": "desc"
}
]
},
"description": "Example: List published blog posts, newest first.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Get Page",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has route', () => pm.expect(res.data).to.have.property('route'));",
"pm.test('Has title', () => pm.expect(res.data).to.have.property('title'));",
"pm.test('Has content', () => pm.expect(res.data).to.have.property('content'));",
"pm.test('Has ETag header', () => pm.response.to.have.header('ETag'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/pages/blog",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"pages",
"blog"
]
},
"description": "Get a single page by route. Returns full content, frontmatter, taxonomy, and media list.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Get Page (Rendered HTML + Children)",
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/pages/blog?render=true&children=true&children_depth=2",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"pages",
"blog"
],
"query": [
{
"key": "render",
"value": "true"
},
{
"key": "children",
"value": "true"
},
{
"key": "children_depth",
"value": "2"
}
]
},
"description": "Get a page with rendered HTML content and child pages up to 2 levels deep.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Create Page",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 201', () => pm.response.to.have.status(201));",
"pm.test('Has Location header', () => pm.response.to.have.header('Location'));",
"pm.test('Has route', () => pm.expect(res.data).to.have.property('route'));"
]
}
}
],
"request": {
"method": "POST",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"route\": \"/newman-test-create-{{$timestamp}}\",\n \"title\": \"Newman Created Page\",\n \"template\": \"default\",\n \"content\": \"# Test Page\\n\\nCreated by Newman with timestamp.\",\n \"header\": {\n \"taxonomy\": {\n \"category\": [\"test\"],\n \"tag\": [\"api\", \"newman\"]\n },\n \"published\": true\n }\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/pages",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"pages"
]
},
"description": "Create a new page. Requires `route` and `title`. Optional: `template`, `content`, `header` (frontmatter), `order`."
}
},
{
"name": "Update Page",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has updated content', () => pm.expect(res.data).to.have.property('content'));"
]
}
}
],
"request": {
"method": "PATCH",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
},
{
"key": "Content-Type",
"value": "application/json"
},
{
"key": "If-Match",
"value": "\"etag-from-get-request\"",
"description": "Optional: ETag from a previous GET for conflict detection",
"disabled": true
}
],
"body": {
"mode": "raw",
"raw": "{\n \"title\": \"Updated Blog Post Title\",\n \"content\": \"# Updated Content\\n\\nThis content was updated via the API.\",\n \"header\": {\n \"taxonomy\": {\n \"tag\": [\"api\", \"grav\", \"updated\"]\n }\n }\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/pages/newman-test-page",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"pages",
"test",
"newman-page"
]
},
"description": "Partial update \u2014 only send the fields you want to change. Supports `content`, `title`, `header`, `template`, `published`, `visible`.\n\nEnable the `If-Match` header for optimistic concurrency control."
}
},
{
"name": "Move Page",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 200', () => pm.response.to.have.status(200));"
]
}
}
],
"request": {
"method": "POST",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"parent\": \"/\",\n \"slug\": \"newman-moved-page\"\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/pages/newman-test-page/move",
"host": [
"{{base_url}}{{api_prefix}}/pages/newman-test-page/move"
],
"path": [
"pages",
"test",
"newman-page",
"move"
]
},
"description": "Move a page to a new parent and/or rename its slug. Requires `parent`. Optional: `slug`, `order`."
}
},
{
"name": "Copy Page",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 201', () => pm.response.to.have.status(201));",
"pm.test('Has Location header', () => pm.response.to.have.header('Location'));"
]
}
}
],
"request": {
"method": "POST",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"route\": \"/newman-test-copy\"\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/pages/newman-test-page/copy",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"pages",
"test",
"newman-page",
"copy"
]
},
"description": "Copy a page (and its media) to a new route."
}
},
{
"name": "Delete Page",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 204', () => pm.response.to.have.status(204));"
]
}
}
],
"request": {
"method": "DELETE",
"url": {
"raw": "{{base_url}}{{api_prefix}}/pages/newman-test-copy?children=true",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"pages",
"test",
"newman-copy"
],
"query": [
{
"key": "children",
"value": "true",
"description": "Set to true to also delete child pages"
}
]
},
"description": "Delete a page. If the page has children and `children=true` is not set, returns a 422 error requiring confirmation.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "List Taxonomy",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has data', () => pm.expect(res.data).to.be.an('object'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/taxonomy",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"taxonomy"
]
},
"description": "List all taxonomy types (categories, tags, etc.) and their values across all pages.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "List Root Children (Lazy Load)",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Returns array', () => pm.expect(pm.response.json().data).to.be.an('array'));",
"pm.test('Pages have has_children field', () => {",
" const pages = pm.response.json().data;",
" if (pages.length > 0) {",
" pm.expect(pages[0]).to.have.property('has_children');",
" }",
"});"
]
}
}
],
"request": {
"method": "GET",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"url": {
"raw": "{{base_url}}{{api_prefix}}/pages?children_of=/&sort=order",
"host": [
"{{base_url}}{{api_prefix}}/pages?children_of=/&sort=order"
]
},
"description": "Get only root-level pages (direct children of /). Returns has_children boolean for each page. Ideal for lazy-loading tree views and miller columns."
},
"response": []
},
{
"name": "List Children of /blog",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('All pages are direct children of /blog', () => {",
" const pages = pm.response.json().data;",
" pages.forEach(p => {",
" pm.expect(p.route).to.match(/^\\/blog\\/[^\\/]+$/);",
" });",
"});"
]
}
}
],
"request": {
"method": "GET",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"url": {
"raw": "{{base_url}}{{api_prefix}}/pages?children_of=/blog&sort=order",
"host": [
"{{base_url}}{{api_prefix}}/pages?children_of=/blog&sort=order"
]
},
"description": "Get direct children of /blog only (one level deep). Unlike parent filter, children_of does not return deeper descendants."
},
"response": []
}
]
},
{
"name": "Media",
"description": "Media management \u2014 upload, list, and delete media files for pages and the site.",
"item": [
{
"name": "List Page Media",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has data array', () => pm.expect(res.data).to.be.an('array'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/pages/blog/media",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"pages",
"blog",
"media"
]
},
"description": "List all media files attached to a specific page.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Upload Page Media",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 201', () => pm.response.to.have.status(201));"
]
}
}
],
"request": {
"method": "POST",
"body": {
"mode": "formdata",
"formdata": [
{
"key": "file",
"type": "file",
"src": "",
"description": "Select a file to upload"
}
]
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/pages/blog/media",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"pages",
"blog",
"media"
]
},
"description": "Upload one or more media files to a page. Use multipart/form-data. Files are validated against Grav's security config for dangerous extensions.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Delete Page Media",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 204', () => pm.response.to.have.status(204));"
]
}
}
],
"request": {
"method": "DELETE",
"url": {
"raw": "{{base_url}}{{api_prefix}}/pages/blog/media/photo.jpg",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"pages",
"blog",
"media",
"photo.jpg"
]
},
"description": "Delete a specific media file from a page.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "List Site Media",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has data array', () => pm.expect(res.data).to.be.an('array'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/media?page=1&per_page=20",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"media"
],
"query": [
{
"key": "page",
"value": "1"
},
{
"key": "per_page",
"value": "20"
},
{
"key": "path",
"value": "",
"description": "Subfolder path relative to user/media",
"disabled": true
},
{
"key": "search",
"value": "",
"description": "Recursive filename search across all subfolders",
"disabled": true
},
{
"key": "type",
"value": "image",
"description": "Filter by type: image, video, audio, document",
"disabled": true
}
]
},
"description": "List site-level media files and folders from user/media. Supports subfolder browsing via path, recursive search, and type filtering. Response includes folders array in meta.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Upload Site Media",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 201', () => pm.response.to.have.status(201));"
]
}
}
],
"request": {
"method": "POST",
"body": {
"mode": "formdata",
"formdata": [
{
"key": "file",
"type": "file",
"src": "",
"description": "Select a file to upload"
}
]
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/media",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"media"
],
"query": [
{
"key": "path",
"value": "",
"description": "Subfolder path to upload into (created automatically)",
"disabled": true
}
]
},
"description": "Upload media files to the site-level media folder (user/media). Optionally specify a subfolder path.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Delete Site Media",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 204', () => pm.response.to.have.status(204));"
]
}
}
],
"request": {
"method": "DELETE",
"url": {
"raw": "{{base_url}}{{api_prefix}}/media/logo.png",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"media",
"logo.png"
]
},
"description": "Delete a site-level media file. Filename may include a subfolder path (e.g. blog/hero.jpg).",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Create Media Folder",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 201', () => pm.response.to.have.status(201));"
]
}
}
],
"request": {
"method": "POST",
"body": {
"mode": "raw",
"raw": "{\n \"path\": \"blog/2026\"\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/media/folders",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"media",
"folders"
]
},
"description": "Create a new folder in the site-level media directory.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Delete Media Folder",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 204', () => pm.response.to.have.status(204));"
]
}
}
],
"request": {
"method": "DELETE",
"url": {
"raw": "{{base_url}}{{api_prefix}}/media/folders/blog/2026",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"media",
"folders",
"blog",
"2026"
]
},
"description": "Delete an empty folder from the site-level media directory.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Rename Site Media",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 200', () => pm.response.to.have.status(200));"
]
}
}
],
"request": {
"method": "POST",
"body": {
"mode": "raw",
"raw": "{\n \"from\": \"blog/hero.jpg\",\n \"to\": \"blog/banner.jpg\"\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/media/rename",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"media",
"rename"
]
},
"description": "Rename or move a media file within the site-level media directory.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Rename Media Folder",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 200', () => pm.response.to.have.status(200));"
]
}
}
],
"request": {
"method": "POST",
"body": {
"mode": "raw",
"raw": "{\n \"from\": \"blog/old-name\",\n \"to\": \"blog/new-name\"\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/media/folders/rename",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"media",
"folders",
"rename"
]
},
"description": "Rename a folder within the site-level media directory.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
}
]
},
{
"name": "Config",
"description": "Configuration management \u2014 read and update system, site, plugin, and theme configs.",
"item": [
{
"name": "Get System Config",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has data', () => pm.expect(res.data).to.be.an('object'));",
"pm.test('Has ETag', () => pm.response.to.have.header('ETag'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/config/system",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"config",
"system"
]
},
"description": "Read the system configuration.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Get Site Config",
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/config/site",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"config",
"site"
]
},
"description": "Read the site configuration (site.yaml).",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Get Plugin Config",
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/config/plugins/markdown",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"config",
"plugins",
"markdown"
]
},
"description": "Read configuration for a specific plugin. Change `markdown` to any plugin name.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Get Theme Config",
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/config/themes/quark",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"config",
"themes",
"quark"
]
},
"description": "Read configuration for a specific theme.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Update Site Config",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has updated data', () => pm.expect(res.data).to.be.an('object'));"
]
}
}
],
"request": {
"method": "PATCH",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
},
{
"key": "Content-Type",
"value": "application/json"
},
{
"key": "If-Match",
"value": "\"etag-from-get\"",
"disabled": true
}
],
"body": {
"mode": "raw",
"raw": "{\n \"title\": \"My Updated Site Title\",\n \"metadata\": {\n \"description\": \"Updated via the Grav API\"\n }\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/config/site",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"config",
"site"
]
},
"description": "Update site configuration. Values are deep-merged with existing config. Only send the fields you want to change."
}
},
{
"name": "Update Plugin Config",
"request": {
"method": "PATCH",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"extra\": true,\n \"auto_line_breaks\": false\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/config/plugins/markdown",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"config",
"plugins",
"markdown"
]
},
"description": "Update a plugin's configuration."
}
}
]
},
{
"name": "Users",
"description": "User account management and API key administration.",
"item": [
{
"name": "List Users",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has data array', () => pm.expect(res.data).to.be.an('array'));",
"pm.test('Has pagination', () => pm.expect(res.meta.pagination).to.have.property('total'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/users?page=1&per_page=20",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"users"
],
"query": [
{
"key": "page",
"value": "1"
},
{
"key": "per_page",
"value": "20"
}
]
},
"description": "List all user accounts (paginated). Sensitive fields (password, API key hashes) are excluded.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Get User",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has username', () => pm.expect(res.data).to.have.property('username'));",
"pm.test('No password field', () => pm.expect(res.data).to.not.have.property('hashed_password'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/users/admin",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"users",
"admin"
]
},
"description": "Get details for a specific user.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Create User",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 201', () => pm.response.to.have.status(201));"
]
}
}
],
"request": {
"method": "POST",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"username\": \"{{test_username}}\",\n \"password\": \"SecureP@ssw0rd!\",\n \"email\": \"testuser@example.com\",\n \"fullname\": \"Test User\",\n \"title\": \"Editor\",\n \"access\": {\n \"api\": {\n \"access\": true,\n \"pages\": {\n \"read\": true,\n \"write\": true\n }\n }\n }\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/users",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"users"
]
},
"description": "Create a new user account. Required: `username`, `password`, `email`."
}
},
{
"name": "Update User",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 200', () => pm.response.to.have.status(200));"
]
}
}
],
"request": {
"method": "PATCH",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"fullname\": \"Updated Test User\",\n \"title\": \"Senior Editor\"\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/users/{{test_username}}",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"users",
"{{test_username}}"
]
},
"description": "Partial update a user. Only send the fields you want to change."
}
},
{
"name": "List API Keys",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has data array', () => pm.expect(res.data).to.be.an('array'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/users/{{test_username}}/api-keys",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"users",
"{{test_username}}",
"api-keys"
]
},
"description": "List all API keys for a user. Returns metadata only (no hashes).",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Create API Key",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 201', () => pm.response.to.have.status(201));",
"pm.test('Has raw key', () => pm.expect(res.data).to.have.property('key'));",
"pm.test('Key starts with grav_', () => pm.expect(res.data.key).to.match(/^grav_/));",
"",
"if (res.data && res.data.id) {",
" pm.collectionVariables.set('test_api_key_id', res.data.id);",
"}"
]
}
}
],
"request": {
"method": "POST",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"name\": \"Test CLI Key\",\n \"scopes\": [\"api.pages.read\", \"api.pages.write\"],\n \"expiry_days\": 90\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/users/{{test_username}}/api-keys",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"users",
"{{test_username}}",
"api-keys"
]
},
"description": "Generate a new API key. The raw key is returned ONCE \u2014 save it immediately. The key ID is saved to the `test_api_key_id` variable for the revoke request."
}
},
{
"name": "Revoke API Key",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 204', () => pm.response.to.have.status(204));"
]
}
}
],
"request": {
"method": "DELETE",
"url": {
"raw": "{{base_url}}{{api_prefix}}/users/{{test_username}}/api-keys/{{test_api_key_id}}",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"users",
"{{test_username}}",
"api-keys",
"{{test_api_key_id}}"
]
},
"description": "Revoke (delete) a specific API key.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Upload Avatar",
"request": {
"method": "POST",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}"
}
],
"url": {
"raw": "{{base_url}}{{api_prefix}}/users/{{test_username}}/avatar",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"users",
"{{test_username}}",
"avatar"
]
},
"description": "Upload a custom avatar image for a user.",
"body": {
"mode": "formdata",
"formdata": [
{
"key": "avatar",
"type": "file",
"src": ""
}
]
}
}
},
{
"name": "Delete Avatar",
"request": {
"method": "DELETE",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}"
},
{
"key": "Accept",
"value": "application/json"
}
],
"url": {
"raw": "{{base_url}}{{api_prefix}}/users/{{test_username}}/avatar",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"users",
"{{test_username}}",
"avatar"
]
},
"description": "Remove the user's custom avatar."
}
},
{
"name": "Generate 2FA Secret",
"request": {
"method": "POST",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}"
},
{
"key": "Accept",
"value": "application/json"
}
],
"url": {
"raw": "{{base_url}}{{api_prefix}}/users/{{test_username}}/2fa",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"users",
"{{test_username}}",
"2fa"
]
},
"description": "Generate a new TOTP 2FA secret and return the QR code as a data URI."
}
},
{
"name": "Delete User",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 204', () => pm.response.to.have.status(204));"
]
}
}
],
"request": {
"method": "DELETE",
"url": {
"raw": "{{base_url}}{{api_prefix}}/users/{{test_username}}",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"users",
"{{test_username}}"
]
},
"description": "Delete a user account. You cannot delete yourself.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
}
]
},
{
"name": "System",
"description": "System administration \u2014 info, cache, logs, and backups.",
"item": [
{
"name": "Ping / Keep-Alive",
"request": {
"method": "GET",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}"
},
{
"key": "Accept",
"value": "application/json"
}
],
"url": {
"raw": "{{base_url}}{{api_prefix}}/ping",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"ping"
]
},
"description": "Lightweight health check endpoint. Returns {pong: true}. Useful for session keep-alive."
}
},
{
"name": "System Info",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has grav_version', () => pm.expect(res.data).to.have.property('grav_version'));",
"pm.test('Has php_version', () => pm.expect(res.data).to.have.property('php_version'));",
"pm.test('Has plugins', () => pm.expect(res.data).to.have.property('plugins'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/system/info",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"system",
"info"
]
},
"description": "Get system information: Grav version, PHP version, extensions, plugins, themes, and environment.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Clear Cache (Standard)",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 200', () => pm.response.to.have.status(200));"
]
}
}
],
"request": {
"method": "DELETE",
"url": {
"raw": "{{base_url}}{{api_prefix}}/cache?scope=standard",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"cache"
],
"query": [
{
"key": "scope",
"value": "standard",
"description": "Options: all, standard, images, assets, tmp"
}
]
},
"description": "Clear the Grav cache. Scopes: `all`, `standard`, `images`, `assets`, `tmp`.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Clear Cache (All)",
"request": {
"method": "DELETE",
"url": {
"raw": "{{base_url}}{{api_prefix}}/cache?scope=all",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"cache"
],
"query": [
{
"key": "scope",
"value": "all"
}
]
},
"description": "Clear ALL caches including images and assets.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "View Logs",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has data array', () => pm.expect(res.data).to.be.an('array'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/system/logs?page=1&per_page=50",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"system",
"logs"
],
"query": [
{
"key": "page",
"value": "1"
},
{
"key": "per_page",
"value": "50"
},
{
"key": "level",
"value": "error",
"disabled": true,
"description": "Filter: error, warning, info, debug"
}
]
},
"description": "Read Grav log entries. Optional `level` filter for error/warning/info/debug.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Create Backup",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 200', () => pm.response.to.have.status(200));"
]
}
}
],
"request": {
"method": "POST",
"url": {
"raw": "{{base_url}}{{api_prefix}}/system/backup",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"system",
"backup"
]
},
"description": "Create a new site backup.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "List Backups",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has data array', () => pm.expect(res.data).to.be.an('array'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/system/backups",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"system",
"backups"
]
},
"description": "List all available backups.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
}
]
},
{
"name": "Languages",
"description": "Site language configuration and multi-language support.",
"item": [
{
"name": "List Site Languages",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has data', () => pm.expect(res).to.have.property('data'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/languages",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"languages"
]
},
"description": "List all configured site languages and their status.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
}
]
},
{
"name": "Pages / Multi-Language",
"description": "Multi-language page operations \u2014 translations, language-specific content.",
"item": [
{
"name": "Get Page in Language",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has data', () => pm.expect(res).to.have.property('data'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/pages/{{page_route}}?lang={{lang}}",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"pages",
"{{page_route}}"
],
"query": [
{
"key": "lang",
"value": "{{lang}}"
}
]
},
"description": "Get a page in a specific language.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Get Page Translations",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has data', () => pm.expect(res).to.have.property('data'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/pages/{{page_route}}/languages",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"pages",
"{{page_route}}",
"languages"
]
},
"description": "List all available translations for a page.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Create Translation",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 201', () => pm.response.to.have.status(201));"
]
}
}
],
"request": {
"method": "POST",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"lang\": \"fr\",\n \"title\": \"Mon titre\",\n \"content\": \"# Contenu\"\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/pages/{{page_route}}/translate",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"pages",
"{{page_route}}",
"translate"
]
},
"description": "Create a new translation for a page in a specific language."
}
},
{
"name": "Update Page in Language",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 200', () => pm.response.to.have.status(200));"
]
}
}
],
"request": {
"method": "PATCH",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"title\": \"Updated\"\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/pages/{{page_route}}?lang={{lang}}",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"pages",
"{{page_route}}"
],
"query": [
{
"key": "lang",
"value": "{{lang}}"
}
]
},
"description": "Update a page in a specific language."
}
},
{
"name": "Delete Language File",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 204', () => pm.response.to.have.status(204));"
]
}
}
],
"request": {
"method": "DELETE",
"url": {
"raw": "{{base_url}}{{api_prefix}}/pages/{{page_route}}?lang=fr",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"pages",
"{{page_route}}"
],
"query": [
{
"key": "lang",
"value": "fr"
}
]
},
"description": "Delete a specific language file for a page.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
}
]
},
{
"name": "Pages / Batch Operations",
"description": "Batch page operations \u2014 reorder children, bulk publish, bulk delete.",
"item": [
{
"name": "Reorder Children",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 200', () => pm.response.to.have.status(200));"
]
}
}
],
"request": {
"method": "POST",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"order\": [\"sunshine-in-the-hills\", \"london-at-night\", \"forest-in-the-fog\"]\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/pages/blog/reorder",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"pages",
"blog",
"reorder"
]
},
"description": "Reorder child pages under a parent page."
}
},
{
"name": "Batch Publish",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 200', () => pm.response.to.have.status(200));"
]
}
}
],
"request": {
"method": "POST",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"operation\": \"publish\",\n \"routes\": [\"/newman-test-page\"]\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/pages/batch",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"pages",
"batch"
]
},
"description": "Batch publish multiple pages at once."
}
},
{
"name": "Batch Delete",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 200', () => pm.response.to.have.status(200));"
]
}
}
],
"request": {
"method": "POST",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"operation\": \"delete\",\n \"routes\": [\n \"/newman-test-copy\"\n ]\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/pages/batch",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"pages",
"batch"
]
},
"description": "Batch delete multiple pages at once."
}
},
{
"name": "Reorganize Pages",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has data array', () => pm.expect(res.data).to.be.an('array'));",
"pm.test('Each result has route and slug', () => {",
" res.data.forEach(item => {",
" pm.expect(item).to.have.property('route');",
" pm.expect(item).to.have.property('slug');",
" pm.expect(item).to.have.property('parent');",
" });",
"});"
]
}
}
],
"request": {
"method": "POST",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"operations\": [\n { \"route\": \"/blog/sunshine-in-the-hills\", \"position\": 2 },\n { \"route\": \"/blog/london-at-night\", \"position\": 1 }\n ]\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/pages/reorganize",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"pages",
"reorganize"
]
},
"description": "Reorganize multiple pages atomically \u2014 move across parents and/or reorder within the same request. Each operation specifies a page route and optionally a new parent and/or position. All operations are validated before any changes are applied."
}
}
]
},
{
"name": "GPM",
"description": "Grav Package Manager \u2014 manage plugins, themes, updates, and the repository.",
"item": [
{
"name": "GPM / Installed",
"description": "List and inspect installed plugins and themes.",
"item": [
{
"name": "List Installed Plugins",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has data', () => pm.expect(res).to.have.property('data'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/gpm/plugins",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"gpm",
"plugins"
]
},
"description": "List all installed plugins with their versions and status.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Plugin Details",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has data', () => pm.expect(res).to.have.property('data'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/gpm/plugins/{{package_slug}}",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"gpm",
"plugins",
"{{package_slug}}"
]
},
"description": "Get details for a specific installed plugin.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "List Installed Themes",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has data', () => pm.expect(res).to.have.property('data'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/gpm/themes",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"gpm",
"themes"
]
},
"description": "List all installed themes with their versions and status.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Theme Details",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has data', () => pm.expect(res).to.have.property('data'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/gpm/themes/{{package_slug}}",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"gpm",
"themes",
"{{package_slug}}"
]
},
"description": "Get details for a specific installed theme.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Plugin README",
"request": {
"method": "GET",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}"
},
{
"key": "Accept",
"value": "application/json"
}
],
"url": {
"raw": "{{base_url}}{{api_prefix}}/gpm/plugins/{{package_slug}}/readme",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"gpm",
"plugins",
"{{package_slug}}",
"readme"
]
},
"description": "Get the README.md content for an installed plugin."
}
},
{
"name": "Plugin Changelog",
"request": {
"method": "GET",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}"
},
{
"key": "Accept",
"value": "application/json"
}
],
"url": {
"raw": "{{base_url}}{{api_prefix}}/gpm/plugins/{{package_slug}}/changelog",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"gpm",
"plugins",
"{{package_slug}}",
"changelog"
]
},
"description": "Get the CHANGELOG.md content for an installed plugin."
}
},
{
"name": "Theme README",
"request": {
"method": "GET",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}"
},
{
"key": "Accept",
"value": "application/json"
}
],
"url": {
"raw": "{{base_url}}{{api_prefix}}/gpm/themes/{{package_slug}}/readme",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"gpm",
"themes",
"{{package_slug}}",
"readme"
]
},
"description": "Get the README.md content for an installed theme."
}
},
{
"name": "Theme Changelog",
"request": {
"method": "GET",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}"
},
{
"key": "Accept",
"value": "application/json"
}
],
"url": {
"raw": "{{base_url}}{{api_prefix}}/gpm/themes/{{package_slug}}/changelog",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"gpm",
"themes",
"{{package_slug}}",
"changelog"
]
},
"description": "Get the CHANGELOG.md content for an installed theme."
}
}
]
},
{
"name": "GPM / Updates",
"description": "Check for available updates.",
"item": [
{
"name": "Check Updates",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has data', () => pm.expect(res).to.have.property('data'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/gpm/updates",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"gpm",
"updates"
]
},
"description": "Check for available updates to plugins, themes, and Grav core.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Check Updates (flush cache)",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has data', () => pm.expect(res).to.have.property('data'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/gpm/updates?flush=true",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"gpm",
"updates"
],
"query": [
{
"key": "flush",
"value": "true"
}
]
},
"description": "Check for updates with cache flushed to get the latest information.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
}
]
},
{
"name": "GPM / Install & Remove",
"description": "Install and remove packages.",
"item": [
{
"name": "Install Plugin",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 200', () => pm.response.to.have.status(200));"
]
}
}
],
"request": {
"method": "POST",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"package\": \"admin\",\n \"type\": \"plugin\"\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/gpm/install",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"gpm",
"install"
]
},
"description": "Install a plugin from the GPM repository. For premium packages, add a `license` field: `\"license\": \"XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXXX\"`."
}
},
{
"name": "Install Theme",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 200', () => pm.response.to.have.status(200));"
]
}
}
],
"request": {
"method": "POST",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"package\": \"quark\",\n \"type\": \"theme\"\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/gpm/install",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"gpm",
"install"
]
},
"description": "Install a theme from the GPM repository. For premium themes, add a `license` field: `\"license\": \"XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXXX\"`."
}
},
{
"name": "Remove Package",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 200', () => pm.response.to.have.status(200));"
]
}
}
],
"request": {
"method": "POST",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"package\": \"some-plugin\"\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/gpm/remove",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"gpm",
"remove"
]
},
"description": "Remove an installed plugin or theme."
}
},
{
"name": "Direct Install from URL",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 200', () => pm.response.to.have.status(200));"
]
}
}
],
"request": {
"method": "POST",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"url\": \"https://example.com/package.zip\"\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/gpm/direct-install",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"gpm",
"direct-install"
]
},
"description": "Install a package directly from a URL (zip file)."
}
}
]
},
{
"name": "GPM / Update",
"description": "Update packages and Grav core.",
"item": [
{
"name": "Update Package",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 200', () => pm.response.to.have.status(200));"
]
}
}
],
"request": {
"method": "POST",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"package\": \"admin\"\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/gpm/update",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"gpm",
"update"
]
},
"description": "Update a specific package to the latest version."
}
},
{
"name": "Update All",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 200', () => pm.response.to.have.status(200));"
]
}
}
],
"request": {
"method": "POST",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
],
"url": {
"raw": "{{base_url}}{{api_prefix}}/gpm/update-all",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"gpm",
"update-all"
]
},
"description": "Update all installed packages to their latest versions."
}
},
{
"name": "Upgrade Grav",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 200', () => pm.response.to.have.status(200));"
]
}
}
],
"request": {
"method": "POST",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
],
"url": {
"raw": "{{base_url}}{{api_prefix}}/gpm/upgrade",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"gpm",
"upgrade"
]
},
"description": "Upgrade Grav core to the latest version."
}
}
]
},
{
"name": "GPM / Repository",
"description": "Browse and search the GPM repository for available packages.",
"item": [
{
"name": "Search Packages",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has data', () => pm.expect(res).to.have.property('data'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/gpm/search?q=email",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"gpm",
"search"
],
"query": [
{
"key": "q",
"value": "email",
"description": "Search query (matches slug, name, description, author, keywords)"
}
]
},
"description": "Search across all plugins and themes in the GPM repository by keyword.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Browse Repository Plugins",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has data', () => pm.expect(res).to.have.property('data'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/gpm/repository/plugins",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"gpm",
"repository",
"plugins"
],
"query": [
{
"key": "q",
"value": "",
"description": "Optional keyword filter (matches slug, name, description, author, keywords)",
"disabled": true
}
]
},
"description": "Browse available plugins in the GPM repository. Use ?q=keyword to filter.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Browse Repository Themes",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has data', () => pm.expect(res).to.have.property('data'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/gpm/repository/themes",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"gpm",
"repository",
"themes"
],
"query": [
{
"key": "q",
"value": "",
"description": "Optional keyword filter (matches slug, name, description, author, keywords)",
"disabled": true
}
]
},
"description": "Browse available themes in the GPM repository. Use ?q=keyword to filter.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Repository Package Details",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has data', () => pm.expect(res).to.have.property('data'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/gpm/repository/{{package_slug}}",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"gpm",
"repository",
"{{package_slug}}"
]
},
"description": "Get details for a specific package in the GPM repository.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
}
]
},
{
"name": "GPM / Plugin Pages",
"description": "Plugin admin page definitions and custom web component scripts.",
"item": [
{
"name": "Plugin Page Definition",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has data', () => pm.expect(res).to.have.property('data'));",
"pm.test('Has required fields', () => {",
" const d = res.data;",
" pm.expect(d).to.have.property('id');",
" pm.expect(d).to.have.property('plugin');",
" pm.expect(d).to.have.property('title');",
" pm.expect(d).to.have.property('page_type');",
" pm.expect(d).to.have.property('has_custom_component');",
"});"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/gpm/plugins/{{package_slug}}/page",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"gpm",
"plugins",
"{{package_slug}}",
"page"
]
},
"description": "Get the admin page definition for a plugin. Returns page metadata, blueprint reference, data/save endpoints, and available actions.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Plugin Page Script",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Content-Type is JavaScript', () => {",
" pm.expect(pm.response.headers.get('Content-Type')).to.include('application/javascript');",
"});"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/gpm/plugins/{{package_slug}}/page-script",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"gpm",
"plugins",
"{{package_slug}}",
"page-script"
]
},
"description": "Get the JavaScript web component script for a plugin's custom admin page. Returns application/javascript content.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Plugin Report Script",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Content-Type is JavaScript', () => {",
" pm.expect(pm.response.headers.get('Content-Type')).to.include('application/javascript');",
"});"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/gpm/plugins/{{package_slug}}/report-script/{{report_id}}",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"gpm",
"plugins",
"{{package_slug}}",
"report-script",
"{{report_id}}"
]
},
"description": "Get the JavaScript web component script for a plugin's report. Returns application/javascript content. The reportId matches the component field from the /reports endpoint response.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
}
]
}
]
},
{
"name": "Scheduler",
"description": "Scheduler management \u2014 list jobs, view status, check history, and run the scheduler.",
"item": [
{
"name": "List Jobs",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has data', () => pm.expect(res).to.have.property('data'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/scheduler/jobs",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"scheduler",
"jobs"
]
},
"description": "List all configured scheduler jobs.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Scheduler Status",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has data', () => pm.expect(res).to.have.property('data'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/scheduler/status",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"scheduler",
"status"
]
},
"description": "Get the current scheduler status and cron configuration.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Job History",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has data', () => pm.expect(res).to.have.property('data'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/scheduler/history",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"scheduler",
"history"
]
},
"description": "View the history of scheduler job executions.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Run Scheduler",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 200', () => pm.response.to.have.status(200));"
]
}
}
],
"request": {
"method": "POST",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"force\": false\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/scheduler/run",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"scheduler",
"run"
]
},
"description": "Trigger the scheduler to run. Set force to true to run regardless of schedule."
}
}
]
},
{
"name": "System Info",
"description": "System info and diagnostics overview.",
"item": [
{
"name": "System Info",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has data', () => pm.expect(res).to.have.property('data'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/systeminfo",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"systeminfo"
]
},
"description": "Get system info overview including environment checks and diagnostics.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
}
]
},
{
"name": "Reports",
"description": "Plugin-extensible diagnostic reports.",
"item": [
{
"name": "Get Reports",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has data array', () => pm.expect(res.data).to.be.an('array'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/reports",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"reports"
]
},
"description": "Get plugin-extensible diagnostic reports including security check, YAML linting, and plugin-provided reports.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
}
]
},
{
"name": "Sidebar",
"description": "Admin sidebar navigation items contributed by plugins.",
"item": [
{
"name": "Get Sidebar Items",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has data array', () => pm.expect(res.data).to.be.an('array'));",
"pm.test('Items have required fields', () => {",
" if (res.data.length > 0) {",
" const item = res.data[0];",
" pm.expect(item).to.have.property('id');",
" pm.expect(item).to.have.property('plugin');",
" pm.expect(item).to.have.property('label');",
" pm.expect(item).to.have.property('icon');",
" pm.expect(item).to.have.property('route');",
" pm.expect(item).to.have.property('priority');",
" }",
"});"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/sidebar/items",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"sidebar",
"items"
]
},
"description": "Get all admin sidebar navigation items contributed by installed plugins.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
}
]
},
{
"name": "Dashboard",
"description": "Dashboard data \u2014 notifications, news feed, and statistics.",
"item": [
{
"name": "Get Notifications",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has data', () => pm.expect(res).to.have.property('data'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/dashboard/notifications",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"dashboard",
"notifications"
]
},
"description": "Get all dashboard notifications.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Hide Notification",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 200', () => pm.response.to.have.status(200));"
]
}
}
],
"request": {
"method": "POST",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
],
"url": {
"raw": "{{base_url}}{{api_prefix}}/dashboard/notifications/{{notification_id}}/hide",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"dashboard",
"notifications",
"{{notification_id}}",
"hide"
]
},
"description": "Hide a specific notification by ID."
}
},
{
"name": "News Feed",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has data', () => pm.expect(res).to.have.property('data'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/dashboard/feed",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"dashboard",
"feed"
]
},
"description": "Get the dashboard news feed.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Dashboard Stats",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has data', () => pm.expect(res).to.have.property('data'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/dashboard/stats",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"dashboard",
"stats"
]
},
"description": "Get dashboard statistics (page counts, user counts, etc.).",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Dashboard Popularity",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has summary', () => pm.expect(res.data).to.have.property('summary'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/dashboard/popularity",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"dashboard",
"popularity"
]
},
"description": "Get page view statistics including daily chart data (last 14 days), summary counters, and top pages by views.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
}
]
},
{
"name": "Webhooks",
"description": "Webhook management \u2014 create, update, delete, and test webhooks.",
"item": [
{
"name": "List Webhooks",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has data', () => pm.expect(res).to.have.property('data'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/webhooks",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"webhooks"
]
},
"description": "List all configured webhooks.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Create Webhook",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 201', () => pm.response.to.have.status(201));",
"",
"if (res.data && res.data.id) {",
" pm.collectionVariables.set('webhook_id', res.data.id);",
"}"
]
}
}
],
"request": {
"method": "POST",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"url\": \"https://example.com/webhook\",\n \"events\": [\"page.created\", \"page.updated\"],\n \"enabled\": true\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/webhooks",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"webhooks"
]
},
"description": "Create a new webhook. The webhook ID is automatically saved to the `webhook_id` variable."
}
},
{
"name": "Get Webhook",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has data', () => pm.expect(res).to.have.property('data'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/webhooks/{{webhook_id}}",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"webhooks",
"{{webhook_id}}"
]
},
"description": "Get details for a specific webhook.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Update Webhook",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 200', () => pm.response.to.have.status(200));"
]
}
}
],
"request": {
"method": "PATCH",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"events\": [\"page.created\", \"page.updated\", \"page.deleted\"]\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/webhooks/{{webhook_id}}",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"webhooks",
"{{webhook_id}}"
]
},
"description": "Update an existing webhook configuration."
}
},
{
"name": "Delete Webhook",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 204', () => pm.response.to.have.status(204));"
]
}
}
],
"request": {
"method": "DELETE",
"url": {
"raw": "{{base_url}}{{api_prefix}}/webhooks/{{webhook_id}}",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"webhooks",
"{{webhook_id}}"
]
},
"description": "Delete a webhook.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Webhook Deliveries",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has data', () => pm.expect(res).to.have.property('data'));"
]
}
}
],
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/webhooks/{{webhook_id}}/deliveries",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"webhooks",
"{{webhook_id}}",
"deliveries"
]
},
"description": "View delivery history for a specific webhook.",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "Test Webhook",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 200', () => pm.response.to.have.status(200));"
]
}
}
],
"request": {
"method": "POST",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
],
"url": {
"raw": "{{base_url}}{{api_prefix}}/webhooks/{{webhook_id}}/test",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"webhooks",
"{{webhook_id}}",
"test"
]
},
"description": "Send a test payload to a webhook endpoint."
}
}
]
},
{
"name": "Workflows",
"description": "Multi-step workflow examples that chain API calls together.",
"item": [
{
"name": "01. Create Blog Post with Media",
"item": [
{
"name": "1. Create the page",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 201', () => pm.response.to.have.status(201));"
]
}
}
],
"request": {
"method": "POST",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"route\": \"/blog/api-workflow-test\",\n \"title\": \"API Workflow Test Post\",\n \"template\": \"post\",\n \"content\": \"# Workflow Test\\n\\nThis post was created as part of an API workflow test.\\n\\n![Hero Image](hero.jpg)\",\n \"header\": {\n \"taxonomy\": {\n \"category\": [\"blog\"],\n \"tag\": [\"api\", \"test\"]\n },\n \"published\": true\n }\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/pages",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"pages"
]
}
}
},
{
"name": "2. Upload hero image",
"request": {
"method": "POST",
"body": {
"mode": "formdata",
"formdata": [
{
"key": "file",
"type": "file",
"src": "",
"description": "Select hero.jpg"
}
]
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/pages/blog/api-workflow-test/media",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"pages",
"blog",
"api-workflow-test",
"media"
]
},
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "3. Verify the page",
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/pages/blog/api-workflow-test?render=true",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"pages",
"blog",
"api-workflow-test"
],
"query": [
{
"key": "render",
"value": "true"
}
]
},
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "4. Cleanup - delete the page",
"request": {
"method": "DELETE",
"url": {
"raw": "{{base_url}}{{api_prefix}}/pages/blog/api-workflow-test?children=true",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"pages",
"blog",
"api-workflow-test"
],
"query": [
{
"key": "children",
"value": "true"
}
]
},
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
}
]
},
{
"name": "02. Full User Lifecycle",
"item": [
{
"name": "1. Create user",
"request": {
"method": "POST",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"username\": \"workflow-user\",\n \"password\": \"T3stP@ss!\",\n \"email\": \"workflow@example.com\",\n \"fullname\": \"Workflow User\",\n \"access\": {\n \"api\": { \"access\": true, \"pages\": { \"read\": true } }\n }\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/users",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"users"
]
}
}
},
{
"name": "2. Generate API key for user",
"request": {
"method": "POST",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"name\": \"Workflow Test Key\",\n \"scopes\": [\"api.pages.read\"]\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/users/workflow-user/api-keys",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"users",
"workflow-user",
"api-keys"
]
}
}
},
{
"name": "3. Login as user (get JWT)",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const res = pm.response.json();",
"if (res.data) {",
" pm.collectionVariables.set('access_token', res.data.access_token);",
" pm.collectionVariables.set('refresh_token', res.data.refresh_token);",
"}"
]
}
}
],
"request": {
"auth": {
"type": "noauth"
},
"method": "POST",
"header": [
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"username\": \"workflow-user\",\n \"password\": \"T3stP@ss!\"\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/auth/token",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"auth",
"token"
]
}
}
},
{
"name": "4. List API keys",
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}{{api_prefix}}/users/workflow-user/api-keys",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"users",
"workflow-user",
"api-keys"
]
},
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
},
{
"name": "5. Cleanup - delete user",
"request": {
"method": "DELETE",
"url": {
"raw": "{{base_url}}{{api_prefix}}/users/workflow-user",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"users",
"workflow-user"
]
},
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
]
}
}
]
}
]
},
{
"name": "Blueprints",
"item": [
{
"name": "List Page Types",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Returns array', () => pm.expect(pm.response.json().data).to.be.an('array'));",
"pm.test('Items have type and label', () => {",
" const items = pm.response.json().data;",
" if (items.length > 0) {",
" pm.expect(items[0]).to.have.property('type');",
" pm.expect(items[0]).to.have.property('label');",
" }",
"});"
]
}
}
],
"request": {
"method": "GET",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"url": {
"raw": "{{base_url}}{{api_prefix}}/blueprints/pages",
"host": [
"{{base_url}}{{api_prefix}}/blueprints/pages"
]
},
"description": "List all available page template types in the active theme."
},
"response": []
},
{
"name": "Get Page Blueprint (default)",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has name', () => pm.expect(pm.response.json().data.name).to.equal('default'));",
"pm.test('Has fields', () => pm.expect(pm.response.json().data.fields).to.be.an('array'));",
"pm.test('Has validation', () => pm.expect(pm.response.json().data).to.have.property('validation'));"
]
}
}
],
"request": {
"method": "GET",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"url": {
"raw": "{{base_url}}{{api_prefix}}/blueprints/pages/default",
"host": [
"{{base_url}}{{api_prefix}}/blueprints/pages/default"
]
},
"description": "Get the resolved blueprint for the default page template. Includes all inherited fields from extends@ and import@ directives."
},
"response": []
},
{
"name": "Get Page Blueprint (blog)",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has blog-specific fields', () => {",
" const data = pm.response.json().data;",
" pm.expect(data.fields).to.be.an('array');",
"});"
]
}
}
],
"request": {
"method": "GET",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"url": {
"raw": "{{base_url}}{{api_prefix}}/blueprints/pages/blog",
"host": [
"{{base_url}}{{api_prefix}}/blueprints/pages/blog"
]
},
"description": "Get the resolved blueprint for the blog page template."
},
"response": []
},
{
"name": "Get Plugin Blueprint",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has fields', () => pm.expect(pm.response.json().data.fields).to.be.an('array'));",
"pm.test('Has name', () => pm.expect(pm.response.json().data.name).to.equal('email'));"
]
}
}
],
"request": {
"method": "GET",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"url": {
"raw": "{{base_url}}{{api_prefix}}/blueprints/plugins/email",
"host": [
"{{base_url}}{{api_prefix}}/blueprints/plugins/email"
]
},
"description": "Get the configuration blueprint for the email plugin."
},
"response": []
},
{
"name": "Get Theme Blueprint",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has fields', () => pm.expect(pm.response.json().data.fields).to.be.an('array'));"
]
}
}
],
"request": {
"method": "GET",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"url": {
"raw": "{{base_url}}{{api_prefix}}/blueprints/themes/quark",
"host": [
"{{base_url}}{{api_prefix}}/blueprints/themes/quark"
]
},
"description": "Get the configuration blueprint for the quark theme."
},
"response": []
},
{
"name": "Get Config Blueprint (system)",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has fields', () => pm.expect(pm.response.json().data.fields).to.be.an('array'));",
"pm.test('Has name', () => pm.expect(pm.response.json().data.name).to.equal('system'));"
]
}
}
],
"request": {
"method": "GET",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"url": {
"raw": "{{base_url}}{{api_prefix}}/blueprints/config/system",
"host": [
"{{base_url}}{{api_prefix}}/blueprints/config/system"
]
},
"description": "Get the blueprint for system configuration."
},
"response": []
},
{
"name": "Get User Blueprint",
"request": {
"method": "GET",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}"
},
{
"key": "Accept",
"value": "application/json"
}
],
"url": {
"raw": "{{base_url}}{{api_prefix}}/blueprints/users",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"blueprints",
"users"
]
},
"description": "Get the user account form blueprint."
}
},
{
"name": "Get Permissions Tree",
"request": {
"method": "GET",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}"
},
{
"key": "Accept",
"value": "application/json"
}
],
"url": {
"raw": "{{base_url}}{{api_prefix}}/blueprints/users/permissions",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"blueprints",
"users",
"permissions"
]
},
"description": "Get all registered permission actions as a nested tree."
}
},
{
"name": "Get Plugin Page Blueprint",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has fields', () => pm.expect(pm.response.json().data.fields).to.be.an('array'));",
"pm.test('Has name', () => pm.expect(pm.response.json().data).to.have.property('name'));"
]
}
}
],
"request": {
"method": "GET",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"url": {
"raw": "{{base_url}}{{api_prefix}}/blueprints/plugins/api/pages/settings",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"blueprints",
"plugins",
"api",
"pages",
"settings"
]
},
"description": "Get the resolved blueprint for a plugin's custom admin page. Used to render blueprint-form type pages registered by plugins."
},
"response": []
},
{
"name": "Resolve Data Options",
"request": {
"method": "GET",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}"
},
{
"key": "Accept",
"value": "application/json"
}
],
"url": {
"raw": "{{base_url}}{{api_prefix}}/data/resolve",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"data",
"resolve"
]
},
"description": "Resolve a blueprint data-options@ directive. Pass ?callable=\\\\Grav\\\\Common\\\\Page\\\\Pages::pageTypes"
}
}
]
},
{
"name": "Translations",
"item": [
{
"name": "Get All Translations (English)",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('Has lang', () => pm.expect(pm.response.json().data.lang).to.equal('en'));",
"pm.test('Has strings object', () => pm.expect(pm.response.json().data.strings).to.be.an('object'));",
"pm.test('Has checksum', () => pm.expect(pm.response.json().data.checksum).to.be.a('string'));",
"pm.test('Count matches', () => {",
" const data = pm.response.json().data;",
" pm.expect(data.count).to.equal(Object.keys(data.strings).length);",
"});"
]
}
}
],
"request": {
"auth": {
"type": "noauth"
},
"method": "GET",
"header": [
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"url": {
"raw": "{{base_url}}{{api_prefix}}/translations/en",
"host": [
"{{base_url}}{{api_prefix}}/translations/en"
]
},
"description": "Get all translation strings for English. No authentication required."
},
"response": []
},
{
"name": "Get Translations with Prefix Filter",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status is 200', () => pm.response.to.have.status(200));",
"pm.test('All keys have prefix', () => {",
" const strings = pm.response.json().data.strings;",
" Object.keys(strings).forEach(key => {",
" pm.expect(key.toUpperCase()).to.match(/^PLUGIN_ADMIN\\./);",
" });",
"});"
]
}
}
],
"request": {
"auth": {
"type": "noauth"
},
"method": "GET",
"header": [
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"url": {
"raw": "{{base_url}}{{api_prefix}}/translations/en?prefix=PLUGIN_ADMIN",
"host": [
"{{base_url}}{{api_prefix}}/translations/en?prefix=PLUGIN_ADMIN"
]
},
"description": "Get translation strings filtered by PLUGIN_ADMIN prefix. Useful for partial/incremental loading."
},
"response": []
}
]
},
{
"name": "Teardown",
"description": "Teardown requests that run after all other tests. Cleans up test data.",
"item": [
{
"name": "Teardown: Delete Test Page",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test(\"Status is 204 or 404\", () => {",
" pm.expect(pm.response.code).to.be.oneOf([204, 404]);",
"});"
]
}
}
],
"request": {
"method": "DELETE",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
],
"url": {
"raw": "{{base_url}}{{api_prefix}}/pages/newman-test-page?children=true",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"pages",
"test",
"newman-page"
],
"query": [
{
"key": "children",
"value": "true"
}
]
},
"description": "Delete the test page created during setup."
}
},
{
"name": "Teardown: Delete Test Webhook",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test(\"Status is 204 or 404\", () => {",
" pm.expect(pm.response.code).to.be.oneOf([204, 404]);",
"});"
]
}
}
],
"request": {
"method": "DELETE",
"header": [
{
"key": "X-API-Key",
"value": "{{api_key}}",
"description": "API Key authentication"
},
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
}
],
"url": {
"raw": "{{base_url}}{{api_prefix}}/webhooks/{{webhook_id}}",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"webhooks",
"{{webhook_id}}"
]
},
"description": "Delete the test webhook created during setup."
}
},
{
"name": "Teardown: Revoke Token",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test(\"Status is 204 or 401\", () => {",
" pm.expect(pm.response.code).to.be.oneOf([204, 401]);",
"});"
]
}
}
],
"request": {
"auth": {
"type": "noauth"
},
"method": "POST",
"header": [
{
"key": "X-Grav-Environment",
"value": "{{grav_environment}}",
"description": "Grav environment"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"refresh_token\": \"{{refresh_token}}\"\n}"
},
"url": {
"raw": "{{base_url}}{{api_prefix}}/auth/revoke",
"host": [
"{{base_url}}{{api_prefix}}"
],
"path": [
"auth",
"revoke"
]
},
"description": "Revoke the refresh token obtained during setup."
}
}
]
}
]
}