PagibleAI GraphQL API

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.

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

Symptom
Likely cause
What to check
HTTP 419
Missing or stale CSRF token
Refresh the session cookie and resend its decoded token header
Unauthenticated
Missing or expired session
Send cookies with the request and log in again
Insufficient permissions
The user lacks a CMS capability
Inspect me.permission and the operation’s required capability
Unknown argument or field
Documentation and installed schema differ
Inspect your application’s compiled GraphQL schema
Invalid JSON value
A native object was sent to the JSON scalar
Send one JSON-encoded string
Conflict details in changed
Another editor saved a newer version
Re-read the item, merge the fields and retry with its latest ID
Upload rejected
Size, MIME or image dimensions violate policy
Check CMS upload configuration and the detected MIME type

Filtering enums

Collection filters

Enum
Value
Meaning
Publish
DRAFT
Latest unpublished versions
Publish
PUBLISHED
Currently published versions
Publish
SCHEDULED
Versions scheduled for later publication
Trashed
WITHOUT
Exclude soft-deleted items
Trashed
WITH
Include active and soft-deleted items
Trashed
ONLY
Return only soft-deleted items

GraphQL reference guides