Using the Guillotine API
Contents
Guillotine exposes content through a GraphQL schema generated from the content types and other schemas in your Enonic installation. Common fields such as displayName are available across content types; fields from your content model are exposed through generated types.
Use the Query Playground in Content Studio or a third-party GraphQL client to inspect the schema and try queries against a project and branch. The API reference describes the built-in fields and types.
Endpoint
For a deployment exposing XP’s shared API base URL, append /com.enonic.app.guillotine:graphql to that base to form the GraphQL endpoint.
With a local Enonic sandbox running on the default port 8080, the API base URL is http://localhost:8080/api. With Guillotine installed, its endpoint is:
http://localhost:8080/api/com.enonic.app.guillotine:graphql
Production URLs depend on your deployment. See Setup for shared API bases, custom routes and site mounting.
Project and branch
At the Web endpoint, specify project and branch on the guillotine field, as shown in the query below. Use master for published content or draft for work in progress. Content permissions apply to the caller; querying draft normally requires authentication.
When Guillotine is mounted on a site, the endpoint supplies the project and branch, and query arguments cannot override them. See Site context for selecting a site within a project.
Request format
Send an HTTP POST request with Content-Type: application/json and a JSON body containing:
| Property | Type | Description |
|---|---|---|
|
query |
String |
The GraphQL query to execute. |
|
variables |
Object |
Optional. Values for variables declared by the query. |
The examples below use this local sandbox API base and retrieve up to ten root content items. For other environments, set the API base URL to the one exposed by your deployment. If Guillotine has an individual custom route, use that full endpoint URL. The queries use only built-in fields, so no custom content type is needed. Replace myproject with your project name. The project must contain published content readable by the caller to return a non-empty list.
query RootItems($project: String!, $branch: String!) {
guillotine(project: $project, branch: $branch) {
getChildren(key: "/", first: 10) {
_id
displayName
type
}
}
}
Third-party GraphQL clients
You can connect Altair or another GraphQL client to Guillotine. Guillotine 9 serves the API without a query editor at its endpoint; the Query Playground is available in Content Studio.
To try the query above in Altair:
-
Enter the full GraphQL endpoint URL:
<apiBaseUrl>/com.enonic.app.guillotine:graphql. For a local sandbox running on port8080with Guillotine installed, usehttp://localhost:8080/api/com.enonic.app.guillotine:graphql. -
Use HTTP POST and
Content-Type: application/json. -
Paste the
RootItemsquery above into the query editor. -
Open the Variables section and enter the JSON below, replacing
myprojectwith your project name. -
Configure any authentication required by your deployment, then send the request.
{
"project": "myproject",
"branch": "master"
}
The client sends the query and variables together in the request format described above. Use draft to query work in progress; content permissions apply, and draft access normally requires authentication. At a site-mounted endpoint, the endpoint determines project and branch.
Use Altair’s authorization settings or request headers for the authentication mechanism supported by your deployment. A separate client needs its own authentication configuration to access protected content.
For a client running in a web page on another origin, configure CORS to allow that origin. If authentication uses cookies across origins, enable credentials in both the client and the CORS configuration.
cURL
Save the query and variables as request.json:
{
"query": "query RootItems($project: String!, $branch: String!) { guillotine(project: $project, branch: $branch) { getChildren(key: \"/\", first: 10) { _id displayName type } } }",
"variables": {
"project": "myproject",
"branch": "master"
}
}
Send the request:
API_BASE_URL='http://localhost:8080/api'
curl "${API_BASE_URL}/com.enonic.app.guillotine:graphql" \
-H 'Content-Type: application/json' \
--data-binary @request.json
JavaScript
The same request can be sent with fetch():
const apiBaseUrl = 'http://localhost:8080/api';
const query = `
query RootItems($project: String!, $branch: String!) {
guillotine(project: $project, branch: $branch) {
getChildren(key: "/", first: 10) {
_id
displayName
type
}
}
}
`;
async function getRootItems() {
const response = await fetch(
`${apiBaseUrl}/com.enonic.app.guillotine:graphql`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
query,
variables: { project: 'myproject', branch: 'master' }
})
}
);
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.guillotine.getChildren;
}
getRootItems().then(console.log).catch(console.error);
For browser requests from another origin, configure CORS to allow the frontend origin. If your deployment uses cookie authentication across origins, the request also needs credentials: 'include' and the corresponding CORS credentials configuration.
Response
Both requests return the same JSON structure. The items depend on your project’s content and permissions:
{
"data": {
"guillotine": {
"getChildren": [
{
"_id": "531e40c9-6e5b-4259-b9e0-0d3144b2382a",
"displayName": "My site",
"type": "portal:site"
}
]
}
}
}
GraphQL errors appear in an errors array and can accompany partial data, even when the HTTP status is successful. Check both the HTTP response and the GraphQL result. The JavaScript example treats any GraphQL error as a failed request; a client that supports partial results can handle the returned data separately.
Troubleshooting
Check both the HTTP status and the response body. A successful HTTP status can still contain GraphQL errors; those errors identify fields or arguments that need attention.
Empty results or missing content
Confirm that project names the intended project and that branch is master or draft. Content must be published to appear in master. Also check the content path, query filters and the caller’s read permissions. At a site-mounted endpoint, the request supplies project and branch even if the query specifies different values.
Query Playground uses your signed-in Content Studio user. A separate client may be anonymous or use another identity, so the same query can return different results. Compare requests using the same project, branch and caller.
Missing project or branch context
At the Web endpoint, explicitly pass both values, for example guillotine(project: "myproject", branch: "master"). An omitted value must come from the request context; when it is unavailable, context setup fails. See Project and branch.
siteKey selects a site inside that project and does not replace project or branch selection. Supply it when using getSite or the ${site} placeholder, and make sure the selected site exists in the requested branch.
Authentication or access failures
For 401 or 403 responses, confirm that the client sends the authentication expected by your deployment and that the caller can access the endpoint and content. Use the configured identity provider or gateway’s authentication mechanism; installing Guillotine does not create a separate API credential.
A Content Studio login does not automatically authenticate another client. Configure its session or authorization headers separately. For cross-origin cookie sessions, use credentials: 'include' in browser requests and enable credentials for the frontend origin in the CORS configuration. Browser cookie restrictions still apply.
Browser CORS errors
If a request works in cURL or a desktop client but the browser reports a CORS error, inspect the OPTIONS preflight and the POST response in the browser’s Network panel:
-
cors.originmust allow the frontend’s origin, including its scheme and port. -
The public route or proxy must pass
OPTIONSrequests through to Guillotine. -
Allowed methods must include
POST, and allowed headers must cover those the client sends. AddAuthorizationif your authentication uses that header. -
For cookie credentials, use an explicit allowed origin and
cors.credentials=true, together withcredentials: 'include'in the client.
See Configuration for a complete example. CORS settings do not grant access to protected content.
Query examples
-
Content queries — retrieve items by ID or path, search by type, and paginate results.
-
References and mixins — traverse related content and access fields contributed by other schemas.
-
Images and URLs — generate image, attachment and page URLs, or build URLs from their parts.
-
Rich text — work with processed HTML, links, images and macros.
-
Site context — select a site, use path placeholders and retrieve site-relative paths.