Callback handler

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

Parameters and their description:

Parameter Description Type Presence
Defines the object received if the new user connected to the document co-editing or disconnected from it. In the first case the type field value is 1, in the other case - 0. The userid field value is the identifier of the user who connected to or disconnected from the document co-editing. array of object optional
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. Deprecated since version 4.2, please use history instead. array of object optional
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 or 3 only. 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. string optional
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.
The type is present when the status value is equal to 6 or 7 only.
integer optional
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 serverVersion and changes, which must be sent as properties serverVersion and changes of the object sent as the argument to the refreshHistory method. object optional
Defines the edited document identifier. string required
Defines the status of the document. Can have the following values:
  • 0 - no document with the key identifier could be found,
  • 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.
integer required
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 or 3 only. string optional
Defines the custom information sent to the command service in case it was present in the request. string optional
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). array of string optional

Status 1 is received every user connection to or disconnection from document co-editing.

Status 2 (3) 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.

Status 4 is received after the document is closed for editing with no changes by the last user.

Status 6 (7) is received when the force saving request is performed.

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

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 Community Server or must be implemented by the software integrators who use ONLYOFFICE Document Server on their own server.

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.
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.
Node.js document save example
var fs = require("fs");

app.post("/track", function (req, res) {

    var updateFile = function (response, body, path) {
        if (body.status == 2)
        {
            var file = syncRequest("GET", body.url);
            fs.writeFileSync(path, file.getBody());
        }

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

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

    if (req.body.hasOwnProperty("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.
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.
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.