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>');
// 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-Timestamp
header with the current timestampX-CS-Signature
header 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.