PagibleAI exposes its authenticated content-management API at https://your-domain.example/graphql. You can query pages, shared elements, files and editor data, then create drafts and publish them when they are ready. The API is powered by Lighthouse and follows the GraphQL request and response format.
PagibleAI GraphQL API
Documentation scope: reviewed against the current PagibleAI development schema on 2 August 2026. If your installed package differs, compare its published graphql/cms.graphql file before copying an operation.
JSON scalar values
PagibleAI uses MLL’s JSON scalar. Send JSON documents as encoded strings and parse JSON scalar responses before using them. With JavaScript, use JSON.stringify(value) once when building variables and JSON.parse(result.data.page.content) after reading a field. Native GraphQL object literals are not accepted for this scalar.
Before you start
You need a Laravel user with CMS permissions. Grant the editor role from your application directory:
php artisan cms:editor editor@example.com
The examples below use browser session authentication. Send JSON requests with Content-Type: application/json and keep credentials: "include" so the session cookie is sent with later requests. Use HTTPS outside local development.
Authenticate an editor
const response = await fetch('/graphql', {
method: 'POST',
credentials: 'include',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: `mutation Login($email: String!, $password: String!) {
cmsLogin(email: $email, password: $password) {
id
name
email
}
}`,
variables: {
email: 'editor@example.com',
password: 'secret',
},
}),
});
const result = await response.json();
{
"data": {
"cmsLogin": {
"id": "42",
"name": "CMS editor",
"email": "editor@example.com"
}
}
}
A successful response places the requested fields under data.cmsLogin. Authentication failures and validation errors appear in the top-level errors array. See GraphQL User & Authentication for login, editor permissions, preferences and logout.
Call GraphQL with curl
The installed GraphQL route uses Laravel sessions and CSRF validation. Start a session with a same-origin GET, retain its cookies, URL-decode the XSRF-TOKEN cookie and send it as X-XSRF-TOKEN:
BASE='https://your-domain.example'
curl --silent --show-error \
--cookie-jar cms.cookies \
"$BASE/cmsadmin" \
--output /dev/null
ENCODED=$(awk '$6 == "XSRF-TOKEN" {print $7}' cms.cookies | tail -1)
TOKEN=$(php -r 'echo urldecode($argv[1]);' "$ENCODED")
curl --silent --show-error \
--cookie cms.cookies \
--cookie-jar cms.cookies \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header "X-XSRF-TOKEN: $TOKEN" \
--data-binary @- \
"$BASE/graphql" <<'JSON'
{
"query": "mutation Login($email: String!, $password: String!) { cmsLogin(email: $email, password: $password) { id name email } }",
"variables": {
"email": "editor@example.com",
"password": "secret"
}
}
JSON
Keep cms.cookies outside source control and delete it after the session. If your application exposes the CMS under a different route, use any same-origin GET that starts the configured web session and issues the XSRF-TOKEN cookie.
Query paginated content
Collection queries are paginated. Select records through data and request paginatorInfo when you need page counts.
query PageList($first: Int!, $page: Int!) {
pages(
filter: { parent_id: null, lang: "" }
publish: DRAFT
trashed: WITHOUT
first: $first
page: $page
) {
data {
id
name
title
path
status
latest { id }
}
paginatorInfo {
currentPage
lastPage
total
}
}
}
{
"first": 25,
"page": 1
}
Use page(id: ID!), element(id: ID!) or file(id: ID!) when you already know an item’s UUID. You can request several root fields in one operation; GraphQL returns each result under its field name or alias.
Create a page draft
PagibleAI uses MLL’s JSON scalar. It expects a JSON-encoded string, not a native GraphQL object. When you use variables, stringify each meta, config and content document once; the surrounding PageInput remains a normal variable object. File and shared-element references inside the decoded documents are discovered automatically.
mutation AddPage($input: PageInput!, $parent: ID) {
addPage(input: $input, parent: $parent) {
id
title
latest { id }
}
}
{
"parent": "018f0f9d-83b3-7d69-a1b2-6f2db5e40c35",
"input": {
"lang": "en",
"path": "getting-started",
"name": "Getting started",
"title": "Getting started with PagibleAI",
"status": 1,
"cache": 5,
"meta": "{\"meta-tags\":{\"type\":\"meta-tags\",\"data\":{\"description\":\"Set up your first PagibleAI page.\"},\"files\":[]}}",
"config": "{}",
"content": "[{\"id\":\"intro\",\"type\":\"text\",\"group\":\"main\",\"data\":{\"text\":\"Welcome to your new page.\"}}]"
}
}
addPage creates an unpublished version. Keep the returned latest.id; pass it as latestId when saving later so concurrent edits can be detected.
Save and publish safely
mutation SavePage($id: ID!, $input: PageInput!, $latestId: ID!) {
savePage(id: $id, input: $input, latestId: $latestId) {
id
title
changed
latest { id }
}
}
mutation PublishPage($id: ID!) {
pubPage(id: [$id]) {
id
title
}
}
Saving creates another draft version; it does not update the public page. Publish only after reviewing the returned draft. Mutations in one GraphQL operation run serially, but separate publish operations are clearer when your workflow includes review or approval.
Handle GraphQL errors
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const result = await response.json();
if (result.errors?.length) {
throw new Error(result.errors.map(error => error.message).join('\n'));
}
return result.data;
Transport failures use HTTP status codes. GraphQL validation, authentication, permission and resolver failures normally use the errors array and may still arrive with an HTTP 200 response. Do not expose debug details from production responses.
Troubleshoot requests
Common GraphQL failures
me.permission and the operation’s required capabilityFiltering enums
Collection filters
GraphQL reference guides
Continue with the guide for the resource you want to manage: