PagibleAI’s image mutations generate and transform images through authenticated GraphQL requests. They return base64-encoded image data; they do not create or publish a CMS File automatically.
GraphQL AI Image Mutations
Use PagibleAI GraphQL API for session and CSRF setup. Use GraphQL Files when you want to store, protect and publish a generated result.
Generate an image
imagine creates an image from a text prompt and can use up to ten stored file UUIDs as visual references.
mutation Imagine(
$prompt: String!
$context: String
$files: [String!]
) {
imagine(prompt: $prompt, context: $context, files: $files)
}
{
"prompt": "A compact electric bicycle parked beside a city café",
"context": "Editorial product image, soft morning light",
"files": ["018f2567-8508-7a62-9309-41708fbfe5fa"]
}
imagine arguments
The result is String containing base64 image data. Required capability: image:imagine. Referenced files also require file:view permission; only image files are used. Reference files stored as remote URLs are fetched by the server, and URLs resolving to private or reserved IP addresses are rejected unless CMS_ALLOW_INTERNAL=true is set. If context is set, it is appended to the prompt, separated by a blank line, before the request is sent to the image provider. Use it for style, mood or brand guidelines that apply in addition to the prompt.
Upload images for editing
Editing mutations accept Upload! values through the GraphQL multipart request specification. Send null in the operations JSON for each upload variable and map each multipart binary field to its variable path.
Edit an image with curl
After logging in with the overview workflow, reuse the authenticated cookie jar. This request removes an image background with isolate:
BASE='https://your-domain.example'
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 "X-XSRF-TOKEN: $TOKEN" \
--form 'operations={"query":"mutation Isolate($file: Upload!) { isolate(file: $file) }","variables":{"file":null}}' \
--form 'map={"0":["variables.file"]}' \
--form '0=@./product.jpg;type=image/jpeg' \
"$BASE/graphql"
{
"data": {
"isolate": "iVBORw0KGgoAAAANSUhEUgAA..."
}
}
Repaint a whole image
mutation Repaint($file: Upload!, $prompt: String!) {
repaint(file: $file, prompt: $prompt)
}
Use repaint for changes that may affect the whole uploaded image. prompt is limited to 2,000 characters. Required capability: image:repaint.
Replace a masked area
mutation Inpaint($file: Upload!, $mask: Upload!, $prompt: String!) {
inpaint(file: $file, mask: $mask, prompt: $prompt)
}
inpaint edits the area selected by the mask according to the prompt. The prompt is limited to 2,000 characters. Required capability: image:inpaint.
Erase a masked area
mutation Erase($file: Upload!, $mask: Upload!) {
erase(file: $file, mask: $mask)
}
For erase, black mask pixels are kept and white pixels mark the area to remove. The provider fills the removed area from its surroundings. Required capability: image:erase.
Remove the background
mutation Isolate($file: Upload!) {
isolate(file: $file)
}
isolate removes the background and returns base64 image data with transparency when the output format supports it. Required capability: image:isolate.
Extend an image
mutation Uncrop(
$file: Upload!
$top: Int!
$right: Int
$bottom: Int
$left: Int
) {
uncrop(
file: $file
top: $top
right: $right
bottom: $bottom
left: $left
)
}
uncrop outpaints beyond the existing boundaries. top is required; each side accepts 0 to 4,096 pixels. Required capability: image:uncrop.
Upscale an image
mutation Upscale($file: Upload!, $factor: Int!) {
upscale(file: $file, factor: $factor)
}
factor must be an integer from 2 through 4. Required capability: image:upscale.
Handle the returned image
function detectImageMime(base64) {
const bytes = Uint8Array.from(
atob(base64.slice(0, 24)),
character => character.charCodeAt(0),
);
if (bytes[0] === 0x89 && bytes[1] === 0x50) return 'image/png';
if (bytes[0] === 0xff && bytes[1] === 0xd8) return 'image/jpeg';
if (bytes[0] === 0x47 && bytes[1] === 0x49) return 'image/gif';
if (String.fromCharCode(...bytes.slice(0, 4)) === 'RIFF' &&
String.fromCharCode(...bytes.slice(8, 12)) === 'WEBP') return 'image/webp';
return 'application/octet-stream';
}
const base64 = result.data.isolate;
const bytes = Uint8Array.from(
atob(base64),
character => character.charCodeAt(0),
);
const blob = new Blob([bytes], {type: detectImageMime(base64)});
const previewUrl = URL.createObjectURL(blob);
The GraphQL response does not include a MIME field. Detect the common image signatures as shown above or use the output format guaranteed by your configured provider. Reject application/octet-stream instead of presenting unknown binary data. To keep the result in the CMS, upload the Blob with addFile, review its detected MIME type and publish it separately.
Validation and errors
Uploaded images and masks are checked against the configured size and MIME policies. Provider failures, invalid arguments and missing capabilities appear in the GraphQL errors array. When the AI provider rejects a request, errors[].message contains the provider's own error message, for example an invalid API key, an exhausted quota or a content policy rejection; the full error is also written to the Laravel log. Image operations can take longer than normal content queries, so use a client timeout appropriate for your configured AI timeout.
All AI mutations share the cms-ai rate limiter, which allows 10 requests per minute per user (or per IP address for guests). Further requests are rejected until the window resets.
{
"errors": [
{
"message": "Image type \"application/pdf\" is not allowed",
"path": ["isolate"]
}
],
"data": {
"isolate": null
}
}