Use the Files API to query media, upload binaries, register remote media, edit metadata, move managed files between public and private storage, and publish file versions. File IDs are UUIDs.
GraphQL Files
Start with PagibleAI GraphQL API for authentication, CSRF and JSON scalar handling. See Frontend Access Control before exposing private media to visitors.
File fields
File
Query one file
query FileDetail($id: ID!) {
file(id: $id) {
id
disk
mime
lang
name
path
previews
description
transcription
byversions_count
changed
latest { id published publish_at }
}
}
Query a file list
query Images($first: Int!, $page: Int!) {
files(
filter: {mime: ["image/jpeg", "image/png", "image/webp"], lang: "en"}
publish: DRAFT
trashed: WITHOUT
sort: [{column: NAME, order: ASC}]
first: $first
page: $page
) {
data {
id
disk
mime
name
path
previews
latest { id published }
}
paginatorInfo {
currentPage
lastPage
total
}
}
}
Filter and sort files
Effective FileFilter fields
The current resolver applies the fields listed above. MIME values are exact, so list each accepted type; use any to search file names, descriptions and transcriptions. publish and trashed are arguments of the files query, not fields inside FileFilter. Supported sort columns are ID, NAME, MIME, LANG, EDITOR and BYVERSIONS_COUNT.
FileInput fields
FileInput
Publication state is stored on versions, not in FileInput. The previews, description and transcription JSON scalars accept and return JSON-encoded strings. Use pubFile to publish or schedule the latest file version.
Upload a file
Uploads follow the GraphQL multipart request specification. Send null for each upload variable in the operations JSON, map multipart file fields to those variables, and include the binary parts.
mutation UploadFile(
$file: Upload!
$preview: Upload
$input: FileInput
$disk: FileDisk!
) {
addFile(
file: $file
preview: $preview
input: $input
disk: $disk
) {
id
disk
mime
name
path
previews
latest { id published }
}
}
{
"file": null,
"preview": null,
"disk": "private",
"input": {
"name": "Product manual",
"lang": "en",
"description": "{\"en\":\"Installation and maintenance instructions\"}"
}
}
Upload with curl
After completing the login workflow from the overview, reuse its cms.cookies file and CSRF token. Do not set Content-Type yourself; curl adds the multipart boundary.
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 UploadFile($file: Upload!, $preview: Upload, $input: FileInput, $disk: FileDisk!) { addFile(file: $file, preview: $preview, input: $input, disk: $disk) { id disk mime name path previews latest { id published } } }","variables":{"file":null,"preview":null,"disk":"private","input":{"name":"Product manual","lang":"en","description":"{\"en\":\"Installation and maintenance instructions\"}"}}}' \
--form 'map={"0":["variables.file"],"1":["variables.preview"]}' \
--form '0=@./manual.pdf;type=application/pdf' \
--form '1=@./manual-preview.jpg;type=image/jpeg' \
"$BASE/graphql"
{
"data": {
"addFile": {
"id": "018f2567-8508-7a62-9309-41708fbfe5fa",
"disk": "private",
"mime": "application/pdf",
"name": "Product manual",
"path": "018f2567-8508-7a62-9309-41708fbfe5fa/manual.pdf",
"previews": "{\"1024\":\"018f2567-8508-7a62-9309-41708fbfe5fa/preview.webp\"}",
"latest": {
"id": "0198d332-19f6-7616-b3a0-a570d62e1b89",
"published": false
}
}
}
}
The configured upload size and MIME allowlist are enforced for the main file and preview. disk defaults to public; choose private when access-controlled delivery is required.
Register a remote file
For a remote URL, omit the upload and put the URL in input.path. PagibleAI validates the URL and MIME type and may generate local previews.
mutation AddRemoteFile {
addFile(input: {
name: "Company logo"
lang: "en"
path: "https://assets.example.com/logo.svg"
description: "{\"en\": \"Company logo\"}"
}) {
id
mime
path
previews
latest { id published }
}
}
Save metadata or replace media
saveFile accepts partial metadata plus optional replacement file and preview uploads. Pass the version ID you originally read as latestId for conflict detection.
mutation SaveFile($id: ID!, $latestId: ID!, $input: FileInput!) {
saveFile(id: $id, latestId: $latestId, input: $input) {
id
name
description
transcription
changed
latest { id published }
}
}
{
"id": "018f2567-8508-7a62-9309-41708fbfe5fa",
"latestId": "0198d332-19f6-7616-b3a0-a570d62e1b89",
"input": {
"name": "Product manual, second edition",
"description": "{\"en\":\"Updated installation and maintenance instructions\"}"
}
}
{
"data": {
"saveFile": {
"id": "018f2567-8508-7a62-9309-41708fbfe5fa",
"name": "Product manual, second edition",
"description": "{\"en\":\"Updated installation and maintenance instructions\"}",
"transcription": "{}",
"changed": null,
"latest": {
"id": "0198d40a-c567-7d9f-b04f-abd353f71982",
"published": false
}
}
}
}
Update several files
bulkFile applies one partial FileInput to up to 1,000 files and creates a draft version for every successful item.
mutation SetFileLanguage($ids: [ID!]!) {
bulkFile(id: $ids, input: {lang: "en"}) {
ids
latest
data
failed
}
}
Move between public and private storage
relocateFile moves managed binaries, previews and stored versions to another logical disk. You can relocate up to 100 files at once. Remote hot-linked files cannot be relocated.
mutation ProtectFiles($ids: [ID!]!) {
relocateFile(id: $ids, disk: private) {
id
disk
path
}
}
Moving to private requires file view and save permission; moving to public requires file view and publish permission.
Deliver private files
A private file’s raw path is not a public URL. PagibleAI’s frontend creates a page-aware asset URL, checks the visitor’s access to the referencing page and returns a private, no-store response. Remote disks use temporary URLs whose expiry is capped by the page-access token. A custom headless frontend must preserve that authorization step; never expose the storage path directly.
Publish files
mutation PublishFiles($ids: [ID!]!, $at: DateTime) {
pubFile(id: $ids, at: $at) {
id
name
latest { id published publish_at }
}
}
Omit at to publish now or provide a DateTime to schedule the latest versions.
Trash, restore and purge
mutation TrashFiles($ids: [ID!]!) {
dropFile(id: $ids) { id name deleted_at }
}
mutation RestoreFiles($ids: [ID!]!) {
keepFile(id: $ids) { id name deleted_at }
}
mutation PurgeFiles($ids: [ID!]!) {
purgeFile(id: $ids) { id }
}
Trash is reversible. Purge permanently removes database records and managed storage paths, so inspect bypages, byelements, byversions or byversions_count before purging.