Editor scripts
The Server-side Editor API can be accessed through the POST /collaborations/{document_id}/evaluate-script endpoint from the REST API. This endpoint allows you to execute JavaScript code that uses the CKEditor–5 API directly on the Cloud Services server.
- An editor bundle needs to be uploaded.
- The source document needs to be created after uploading the editor bundle.
The request body should contain a script parameter with the JavaScript code to be executed:
{
"script": "// Your JavaScript code here that uses the CKEditor 5 API"
}
The script parameter should contain valid JavaScript code that can access the CKEditor–5 API. The script has access to:
- Editor instance: The CKEditor–5 editor instance is available in the script context
- Document model: Access to the document’s data model for content manipulation
- Editor plugins: All loaded plugins and their APIs
- Collaboration features: Access to comments, suggestions, and revision history
It should be a properly formatted string according to ECMA-404 (The JSON Data Interchange Standard). The only characters you must escape are \ and ". Control codes such as \n, \t, etc., can be removed or escaped as well.
You can also include a user object in the request body to control the user details, like name, during script execution.
By default, the system uses hardcoded user data with the ServerSideEditorAPI identifier for the script execution. You can implement special handling for this user in your application, for example, to process webhook events or track script execution activities.
The example below shows a basic script for getting editor data, along with user context configuration that allows you to execute scripts with specific user context and to control how the user appears in the collaboration session:
{
"script": "return editor.getData()",
"user": {
"id": "user-123",
"name": "John Doe",
}
}
You can specify a plugins_to_remove parameter in the request body to provide a list of plugin names for removal from the editor before executing the script. It is useful when you need to disable certain editor features or plugins that might interfere with your script execution. Note that, it is different from the removePlugins option that you may have specified in the editor bundle configuration during the bundle upload, as it permanently excludes those plugins from typical document conversions. The removePlugins option is often used to exclude plugins that communicate with the internet. However, in the case of the Server-side Editor API, such plugins can be included in your editor bundle and used in scripts if needed.
{
"script": "return editor.getData()",
"plugins_to_remove": ["DocumentOutline", "ExportInlineStyles"]
}
Scripts can be written in both async and non-async ways. You can use await for asynchronous operations:
// Non-async script
editor.getData();
// Async script
await Promise.resolve( editor.getData() );
You can return data from your script using the return statement. The returned value will be available as literal data or as a JSON (in case of an object) in the API response:
// Return processed data
const content = editor.getData();
return {
content: content,
wordCount: content.split(' ').length
};
The SSE API can return only serializable values (e.g., plain objects, arrays, strings, numbers, booleans, and null). Functions, classes, DOM elements, and other non-serializable objects, like Map or Set, cannot be returned. If your script returns a non-serializable value, the API will attempt to serialize it into a JSON object. However, it may omit some custom properties.
The CKEditor 5 editor instance is available globally as the editor object. You can access all editor methods and properties:
// Get editor content
const content = editor.getData();
// Set editor content
editor.setData('<p>New content</p>', { suppressErrorInCollaboration: true } );
// Access editor model
const model = editor.model;
// Use editor commands
editor.execute('bold');
Scripts have access to most browser and JavaScript APIs, with some restrictions for security reasons.
Refer to the security considerations guide for detailed implementation.
Regular HTTP calls using fetch() or HTTP requests through the editor’s data layer are permitted and can be used to communicate with third-party services.
All requests to the Server-side Editor API require proper authentication using:
X-CS-Timestampheader with the current timestampX-CS-Signatureheader with a valid request signature
Refer to the request signature guide for detailed implementation.
The API returns a 201 status code on successful execution. The response contains the data returned by your script under the data attribute:
{
"data": "<p>Editor content</p>"
}
For objects returned by your script, the response will be:
{
"data": {
"content": "<p>Editor content</p>",
"wordCount": 5
}
}
The script execution time is limited to 18s. For complex operations, consider breaking them into smaller, more focused scripts.
Make sure your script is well-tested before executing it on production documents, as it can permanently modify document content and structure.
When a script fails to execute, the API returns detailed error information. Example error response:
{
"message": "Editor script failed to evaluate",
"trace_id": "2daa364a-a658-4123-9630-50497447ed07",
"status_code": 400,
"data": {
"error": {
"name": "TypeError",
"message": "Cannot read properties of undefined (reading 'get')",
"details":[
"Cannot read properties of undefined (reading 'change')"
]
}
},
"level": "trace",
"explanation": "The provided script cannot be evaluated due to the attached error",
"action": "Please check the error and script syntax or contact support if the problem persists"
}
The data.error.details field contains an array of intercepted and parsed browser console errors, which can help you identify the root cause of script execution failures.
Serialization omits custom error attributes, as only serializable content can be returned. In this case, it only preserves the name and message properties in the response.
When developing and testing your editor scripts, you can enable the debug mode by setting the debug: true parameter in your API request. This will allow you to collect the console.debug logs from the script execution. It can be helpful for troubleshooting and understanding script behavior.
{
"script": "console.debug('Processing editor data', { wordCount: editor.getData().length }); return editor.getData();",
"debug": true
}
With debug mode enabled, any console.debug() calls in your script will be captured and included in the response. This provides additional insight into your script’s execution flow:
{
"data": "<p>Editor content</p>",
"metadata": {
"logs": [
{
"type": "debug",
"createdAt": "2025-08-08T12:00:00.000Z",
"data": [
"Processing editor data",
{ "wordCount": 245 }
]
}
]
}
}
In order to improve the debugging experience in case of an error tracking process, the evaluation error also includes the collected logs during the script evaluation. This means that if a script fails to execute when debug mode is enabled, you will receive both the error details and any debug logs that were captured before the failure occurred, providing valuable context for troubleshooting script issues.
{
"message": "Editor script failed to evaluate",
"trace_id": "2daa364a-a658-4123-9630-50497447ed07",
"status_code": 400,
"data": {
"error": {
"name": "TypeError",
"message": "Cannot read properties of undefined (reading 'get')",
},
"logs": [
{
"createdAt": "2025-08-08T12:00:00.000Z",
"type": "debug",
"data": [
"Processing editor data",
{ "wordCount": 245 }
]
}
]
},
"explanation": "The provided script cannot be evaluated due to the attached error",
"action": "Please check the error and script syntax or contact support if the problem persists"
}
Please remember, that only serializable objects can be outputted in debug logs. Custom error attributes and non-serializable content will be omitted from the response.
Debug mode is disabled by default. Only enable it during development and testing, as it may impact performance in production environments.