Callback handler

The document editing service informs the document storage service about the status of the document editing using the callbackUrl from JavaScript API. The document editing service use the POST request with the information in body.

actions

Defines the object received when the user takes an action with the document. The type field value can have the following values:

  • 0 - the user disconnects from the document co-editing;
  • 1 - the new user connects to the document co-editing;
  • 2 - the user clicks the forcesave button.

The userid field value is the user identifier.

Type: array of object

changeshistory

Defines the array of objects with the document changes history. The object is present when the status value is equal to 2 or 3 only. Must be sent as a property changes of the object sent as the argument to the refreshHistory method. Removed since version 4.2, please use history instead.

Type: array of object

changesurl

Defines the link to the file with the document editing data used to track and display the document changes history. The link is present when the status value is equal to 2, 3, 6, or 7. The file must be saved and its address must be sent as changesUrl parameter using the setHistoryData method to show the changes corresponding to the specific document version.

Type: string

filetype

Defines an extension of the document that is downloaded from the link specified with the url parameter. The file type is OOXML by default but if the assemblyFormatAsOrigin server setting is enabled, the file will be saved in its original format.

Type: string

forcesavetype

Defines the type of initiator when the force saving request is performed. Can have the following values:

  • 0 - the force saving request is performed to the command service;
  • 1 - the force saving request is performed each time the saving is done (e.g. the Save button is clicked), which is only available when the forcesave option is set to true;
  • 2 - the force saving request is performed by timer with the settings from the server config;
  • 3 - the force saving request is performed each time the form is submitted (e.g. the Complete & Submit button is clicked).

The type is present when the status value is equal to 6 or 7 only.

Type: integer

formsdataurl

Defines the URL to the JSON file with the submitted form data. The array structure with the form data is described here. This file contains the following parameters:

ParameterTypeExampleDescription
keystring"Text1"The form key. If the current form is a radio button, then this field contains the form group key.
tagstring""The form tag.
valuestring"inner text"The current form value.
typestring"text"The form type (text, checkBox, picture, comboBox, dropDownList, dateTime, radio).

The object is present when the status value is equal to 6 and the forcesavetype value is equal to 3.

Type: object

history

Defines the object with the document changes history. The object is present when the status value is equal to 2 or 3 only. It contains the object changes and serverVersion, which must be sent as properties changes and serverVersion of the object sent as the argument to the refreshHistory method.

Type: object

key*

Defines the edited document identifier.

Type: string

status*

Defines the status of the document. Can have the following values:

  • 1 - document is being edited;
  • 2 - document is ready for saving;
  • 3 - document saving error has occurred;
  • 4 - document is closed with no changes;
  • 6 - document is being edited, but the current document state is saved;
  • 7 - error has occurred while force saving the document.

Type: integer

url

Defines the link to the edited document to be saved with the document storage service. The link is present when the status value is equal to 2, 3, 6 or 7 only.

Type: string

userdata

Defines the custom information sent to the command service for the forcesave and info commands in case it was present in the request.

Type: string

users

Defines the list of the identifiers of the users who opened the document for editing; when the document has been changed the users will return the identifier of the user who was the last to edit the document (for status 2 and status 6 replies).

Type: array of string

* - required parameter

The server stores all callbackUrls and chooses which one to use depending on the user who performed the action.

Since version 5.5, callbackUrl is selected depending on the status of the request. Starting from version 4.4 to version 5.5, callbackUrl is used from the last user who joined the co-editing. Prior to version 4.4, when co-editing, callbackUrl is used from the user who first opened the file for editing.

Since version 7.0, callbackUrl is used from the last tab of the same user. Prior to version 7.0, callbackUrl from the first user tab was used.

Possible document statuses and their description

Status 1

It is received every user connection to or disconnection from document co-editing. Their callbackUrl is used.

Please note that the status 1 can be also received when the user is returned to the document with no changes after the Internet problems. This situation can be described as follows:

  • When the user opens a document, the status 1 is sent.
  • If the Internet connection is lost and the user has not made any changes to the document, the status 4 is sent. An error is displayed on the screen and the document is opened in the viewer.
  • Within 100 seconds, the Internet connection is restored, the user is reconnected to the document and the status 1 is sent again.
  • Now the user can continue to edit the document. The status 2 or 4 will be received depending on whether the user made any changes to the document or not.

Status 2 (3)

It is received 10 seconds after the document is closed for editing with the identifier of the user who was the last to send the changes to the document editing service. The callbackUrl from the user who made the last changes to the file is used.

Status 4

It is received after the document is closed for editing with no changes by the last user. Their callbackUrl is used.

Status 6 (7)

It is received when the force saving request is performed.The callbackUrl depends on forcesavetype parameter:

  • If forcesavetype parameter is set to 1, the callbackUrl from the user who clicked the Save button is used.
  • If forcesavetype parameter is set to 0 or 2, the callbackUrl from the user who made the last changes to the file is used.
  • If forcesavetype parameter is set to 3, the callbackUrl from the user who clicked the Submit button is used.Starting from version 5.5 to version 6.1, the callbackUrl from the user who made the last changes to the file is always used.

Examples of requests

Sample of JSON object sent to the "callbackUrl" address by document editing service when two users are co-editing the document

{
  "actions": [
    {"type": 1,
      "userid": "78e1e841"}
  ],
  "key": "Khirz6zTPdfd7",
  "status": 1,
  "users": ["6d5a81d0", "78e1e841"]
}

Sample of JSON object sent to the "callbackUrl" address by document editing service when the user changed the document and closed it for editing

{
  "actions": [
    {
      "type": 0,
      "userid": "78e1e841"
    }
  ],
  "changesurl": "https://documentserver/url-to-changes.zip",
  "history": {
    "changes": changes,
    "serverVersion": serverVersion
  },
  "filetype": "docx",
  "key": "Khirz6zTPdfd7",
  "status": 2,
  "url": "https://documentserver/url-to-edited-document.docx",
  "users": ["6d5a81d0"]
}

Sample of JSON object sent to the "callbackUrl" address by document editing service when the last user closed the document for editing without changes

{
  "key": "Khirz6zTPdfd7",
  "status": 4
}

Sample of JSON object sent to the "callbackUrl" address by document editing service after the forcesave command had been received

{
  "changesurl": "https://documentserver/url-to-changes.zip",
  "forcesavetype": 0,
  "history": {
    "changes": changes,
    "serverVersion": serverVersion
  },
  "filetype": "docx",
  "key": "Khirz6zTPdfd7",
  "status": 6,
  "url": "https://documentserver/url-to-edited-document.docx",
  "users": ["6d5a81d0"],
  "userdata": "sample userdata"
}

Response from the document storage service

The document storage service must return the following response, otherwise the document editor will display an error message:

{
  "error": 0
}

The document manager and document storage service are either included to ONLYOFFICE Workspace or must be implemented by the software integrators who use ONLYOFFICE Docs on their own server.

Document save examples

.Net (C#) document save example

public class WebEditor : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        string body;
        using (var reader = new StreamReader(context.Request.InputStream))
            body = reader.ReadToEnd();

        var fileData = new JavaScriptSerializer().Deserialize<Dictionary<string, object>>(body);
        if ((int) fileData["status"] == 2)
        {
            var req = WebRequest.Create((string) fileData["url"]);

            using (var stream = req.GetResponse().GetResponseStream())
            using (var fs = File.Open(PATH_FOR_SAVE, FileMode.Create))
            {
                var buffer = new byte[4096];
                int readed;
                while ((readed = stream.Read(buffer, 0, 4096)) != 0)
                    fs.Write(buffer, 0, readed);
            }
        }
        context.Response.Write("{\"error\":0}");
    }
}

PATH_FOR_SAVE is the absolute path to your computer folder where the file will be saved including the file name.

On the .Net example page, you will learn how to integrate ONLYOFFICE Docs into your web application written on .Net (C#) or .Net (C# MVC).

Java document save example

public class IndexServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter writer = response.getWriter();

        Scanner scanner = new Scanner(request.getInputStream()).useDelimiter("\\A");
        String body = scanner.hasNext() ? scanner.next() : "";

        JSONObject jsonObj = (JSONObject) new JSONParser().parse(body);

        if((long) jsonObj.get("status") == 2)
        {
            String downloadUri = (String) jsonObj.get("url");

            URL url = new URL(downloadUri);
            java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection();
            InputStream stream = connection.getInputStream();

            File savedFile = new File(pathForSave);
            try (FileOutputStream out = new FileOutputStream(savedFile)) {
                int read;
                final byte[] bytes = new byte[1024];
                while ((read = stream.read(bytes)) != -1) {
                    out.write(bytes, 0, read);
                }

                out.flush();
            }

            connection.disconnect();
        }
        writer.write("{\"error\":0}");
    }
}

pathForSave is the absolute path to your computer folder where the file will be saved including the file name.

On the Java example and Java integration SDK pages, you will learn how to integrate ONLYOFFICE Docs into your web application written on Java.

Node.js document save example

import {fs} from "node:fs"
import {syncRequest} from "sync-request"

app.post("/track", (req, res) => {
  function updateFile(response, body, path) {
    if (body.status === 2) {
      const file = syncRequest("GET", body.url)
      fs.writeFileSync(path, file.getBody())
    }

    response.write("{\"error\":0}")
    response.end()
  }

  function readbody(request, response, path) {
    let content = ""
    request.on("data", (data) => {
      content += data
    })
    request.on("end", () => {
      const body = JSON.parse(content)
      updateFile(response, body, path)
    })
  }

  if (req.body.hasOwn("status")) {
    updateFile(res, req.body, pathForSave)
  } else {
    readbody(req, res, pathForSave)
  }
})

pathForSave is the absolute path to your computer folder where the file will be saved including the file name.

On the NodeJS example page, you will learn how to integrate ONLYOFFICE Docs into your web application written on Node.js.

PHP document save example

<?php

if (($body_stream = file_get_contents("php://input"))===FALSE){
    echo "Bad Request";
}

$data = json_decode($body_stream, TRUE);

if ($data["status"] == 2){
    $downloadUri = $data["url"];
        
    if (($new_data = file_get_contents($downloadUri))===FALSE){
        echo "Bad Response";
    } else {
        file_put_contents($path_for_save, $new_data, LOCK_EX);
    }
}
echo "{\"error\":0}";

?>

$path_for_save is the absolute path to your computer folder where the file will be saved including the file name.

On the PHP example page, you will learn how to integrate ONLYOFFICE Docs into your web application written on PHP.

Ruby document save example

class ApplicationController < ActionController::Base
    def index
        body = request.body.read

        file_data = JSON.parse(body)
        status = file_data["status"].to_i

        if status == 2
            download_uri = file_data["url"]
            uri = URI.parse(download_uri)
            http = Net::HTTP.new(uri.host, uri.port)

            if download_uri.start_with?("https")
                http.use_ssl = true
                http.verify_mode = OpenSSL::SSL::VERIFY_NONE
            end

            req = Net::HTTP::Get.new(uri.request_uri)
            res = http.request(req)
            data = res.body

            File.open(path_for_save, "wb") do |file|
                file.write(data)
            end
        end
        render :text => "{\"error\":0}"
    end
end

path_for_save is the absolute path to your computer folder where the file will be saved including the file name.

On the Ruby example page, you will learn how to integrate ONLYOFFICE Docs into your web application written on Ruby.

Get Help

  • If you have any questions about ONLYOFFICE Docs, try the FAQ section first.
  • You can request a feature or report a bug by posting an issue on GitHub.
  • You can also ask our developers on ONLYOFFICE forum (registration required).