PagibleAI JSON REST API

The PagibleAI CMS JSON frontend API adheres to the JSON:API standard, as documented at jsonapi.org. It is accessible at the following URL (remember to replace pagible.com with your own domain):

https://pagible.com/cms/pages

JSON:API response

The JSON response returned by the JSON API is structured like this:

{
  "meta": {
    "baseurl": "https://pagible.com/storage/",
    "page": {
      "currentPage": 1,
      "from": 1,
      "lastPage": 1,
      "perPage": 15,
      "to": 1,
      "total": 1
    }
  },
  "jsonapi": {
    "version": "1.0"
  },
  "links": {
    "first": "https://pagible.com/cms/pages?include=subtree&page%5Bnumber%5D=1&page%5Bsize%5D=15",
    "last": "https://pagible.com/cms/pages?include=subtree&page%5Bnumber%5D=1&page%5Bsize%5D=15"
  },
  "data": [
    {
      "type": "pages",
      "id": "1",
      "attributes": {
       "parent_id": null,
        "lang": "en",
        "path": "",
        "name": "Home",
        "title": "Pagible AI CMS - Next level content management!",
        "theme": "",
        "type": "",
        "to": "",
        "domain": "",
        "has": true,
        "cache": 5,
        "createdAt": "2025-07-29T09:00:58.000000Z",
        "updatedAt": "2025-08-20T22:46:15.000000Z",
        "meta": {
          "meta-tags": {
            "type": "meta-tags",
            "data": {
              "description": "Experience the future of content management with PagibleAI, the AI-powered CMS that combines WordPress's ease of use with Contentful's power"
            },
            "files": []
          }
        },
        "config": null,
        "content": {
          "main": [
            {
              "id": "Ah3jsZ",
              "group": "main",
              "type": "hero",
              "data": {
                "title": "PagibleAI: The future of CMS",
                "text": "The first CMS build on AI with the ease of Wordpress and the power of Contentful!",
                "button": "",
                "url": null
              }
            }
          ]
        }
      },
      "relationships": {
        "subtree": {
          "data": [
            {
              "type": "navs",
              "id": "9"
            },
            {
              "type": "navs",
              "id": "11"
            }
          ]
        }
      },
      "links": {
        "self": "https://pagible.com/cms/pages/1"
      }
    }
  ],
  "included": [
    {
      "type": "navs",
      "id": "9",
      "attributes": {
        "parent_id": 1,
        "lang": "en",
        "path": "demo",
        "name": "Demo",
        "title": "Demo",
        "to": "https://pagible.demo.aimeos.org/cmsadmin",
        "domain": "",
        "has": false,
        "createdAt": "2025-08-06T14:27:08.000000Z",
        "updatedAt": "2025-08-06T14:28:32.000000Z"
      },
      "links": {
        "self": "https://pagible.com/cms/pages/9"
      }
    },
    {
      "type": "navs",
      "id": "11",
      "attributes": {
        "parent_id": 1,
        "lang": "en",
        "path": "documentation",
        "name": "Docs",
        "title": "Documentation",
        "to": "",
        "domain": "",
        "has": true,
        "createdAt": "2025-08-16T20:46:38.000000Z",
        "updatedAt": "2025-08-20T08:43:58.000000Z"
      },
      "links": {
        "self": "https://pagible.com/cms/pages/11"
      }
   }
  ]
}

Working with JSON:API efficiently

If you are working in a Javascript environment (e.g. in a single page application or a NodeJS server), the json-api-models npm package makes it much easier to access data from a JSON:API response.

First, install the json-api-models package using npm:

npm install json-api-models

Then, create a model and apply the JSON response to the model:

import { Store } from 'json-api-models';

const models = new Store();
models.sync({
  "meta": {/* ... */},
  "jsonapi": {/* ... */},
  "links": {/* ... */},
  "data": [
    {
      "type": "pages",
      "id": "1",
      "attributes": {
        "parent_id": null,
        "lang": "en",
        "path": "",
        "name": "Home",
        "title": "Pagible AI CMS - Next level content management!"
        /* ... */
      },
      "relationships": {
        "subtree": {
          "data": [
            {"type": "navs", "id": "9"},
            {"type": "navs", "id": "11"}
          ]
        }
      },
      "links": {/* ... */}
    }
  ],
  "included": [
    {
      "type": "navs",
      "id": "9",
      "attributes": {
        "parent_id": 1,
        "lang": "en",
        "path": "demo",
        "title": "Demo",
        /* ... */
      },
    }
  ]
});

Afterwards, you can retrieve the items and their nested data easily.

const pages = models.findAll('pages');
const page = models.find('pages', '1');

const children = page.subtree.findAll('navs');
children.forEach(item => console.log(item.title));

Error Handling

The JSON:API standard, like other REST protocols, uses HTTP status codes to signal error conditions and the following HTTP status codes are used:

  • 2xx : Successful operation
    • 200 : Operation was performed successfully
    • 201 : Resource has been created
  • 4xx : Bad request
    • 401 : Authentication required
    • 403 : Operation is forbidden/unsupported
    • 404 : The resource wasn't found
  • 5xx : Internal server error
    • 500 : A non-recoverable error occurred
    • 501 : Operation not implemented

The JSON API standard also defines an errors section in the JSON response, providing error hints for one or more operations:

{
  "errors": [
    {
      "title": "No page with ID 1 available",
      "detail": "<stack trace where the error occured>"
    },
    // ...
  ]
}

Each error item includes a title attribute containing the user-friendly error message and a detail attribute with the stack trace, intended for developers (only if APP_DEBUG=1 in your .env file). Displaying error details can be helpful for debugging:

const promise = fetch('/cms/pages?...', {
  method: 'GET',
  credentials: 'same-origin',
}).then(response => {
  if(!response.ok) {
    throw new Error(response.statusText)
  }
  return response.json();
}).then(result => {
  if(result.errors) {
    throw result.errors
  }
  return result
}).catch(err => {
  console.error(err)
})