Skip to main content

Overview

The callback action receives POST requests from the OnlyOffice Document Server when document editing events occur. This is primarily used to save document changes back to the server storage when users finish editing.

Endpoint

POST OnlyOfficeHandler.ashx?action=callback&fileId={fileId}

Query Parameters

action
string
required
Must be set to callback to invoke this action
fileId
string
required
The unique identifier of the file being edited. Used to locate and update the stored file.

Request Body

The request body must be a JSON object with the following structure:
status
integer
required
The document status code from OnlyOffice Document Server:
  • 2 - Document is ready for saving (user clicked save)
  • 6 - Document is being edited, force save requested
  • Other status codes are ignored by this handler
url
string
required
The URL where the updated document can be downloaded from OnlyOffice Document Server. The handler will fetch the document from this URL and save it to storage.

Request Example

POST /OnlyOfficeHandler.ashx?action=callback&fileId=doc123 HTTP/1.1
Host: your-app.com
Content-Type: application/json

{
  "status": 2,
  "url": "https://documentserver.com/cache/files/doc123/output.docx"
}

Payload Class Structure

private class OnlyOfficeCallbackPayload
{
    public int status { get; set; }
    public string url { get; set; }
}

Response

The callback action always returns a JSON response indicating success or failure.

Success Response

statusCode
number
default:"200"
HTTP status code indicating success
Content-Type
string
default:"application/json"
Response content type
error
integer
default:"0"
Error code where 0 indicates success

Example Success Response

HTTP/1.1 200 OK
Content-Type: application/json

{"error":0}

Error Response

statusCode
number
default:"200"
HTTP status code (note: still returns 200 even on error)
Content-Type
string
default:"application/json"
Response content type
error
integer
default:"1"
Error code where 1 indicates failure

Example Error Response

HTTP/1.1 200 OK
Content-Type: application/json

{"error":1}
The handler returns HTTP 200 status code even when an error occurs. Check the error field in the JSON response to determine success or failure.

Status Codes

The handler only processes callbacks with specific status codes:

Status Code 2: Document Ready for Saving

Indicates that the document is ready to be saved. This typically occurs when:
  • A user clicks the save button
  • A user closes the document
  • Co-editing session ends

Status Code 6: Force Save

Indicates a force save event. This typically occurs when:
  • The application explicitly requests a document save
  • Periodic auto-save is triggered
  • Co-editing session requires synchronization

Ignored Status Codes

Other status codes (0, 1, 3, 4, 7) are ignored by this handler and will return success without performing any file operations:
  • 0 - Document not found
  • 1 - Document is being edited
  • 3 - Document saving error
  • 4 - Document closed with no changes
  • 7 - Error during force save

File Update Process

When a valid callback is received (status 2 or 6), the handler performs the following steps:

Step 1: Parse Request Body

Read and deserialize the JSON payload from the request body:
string body;
using (var reader = new StreamReader(context.Request.InputStream, Encoding.UTF8))
{
    body = reader.ReadToEnd();
}
var payload = serializer.Deserialize<OnlyOfficeCallbackPayload>(body);

Step 2: Validate Payload

Check that the payload contains valid data:
  • Status is 2 or 6
  • URL is not null or whitespace
  • File exists in storage
if (payload != null && 
    (payload.status == 2 || payload.status == 6) && 
    !string.IsNullOrWhiteSpace(payload.url) && 
    !string.IsNullOrWhiteSpace(currentPath))

Step 3: Download Updated Document

Fetch the updated document from the OnlyOffice Document Server:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | 
                                       SecurityProtocolType.Tls11 | 
                                       SecurityProtocolType.Tls;
var req = (HttpWebRequest)WebRequest.Create(payload.url);
req.Method = "GET";

Step 4: Save to Storage

Overwrite the existing file with the updated content:
using (var resp = (HttpWebResponse)req.GetResponse())
using (var stream = resp.GetResponseStream())
using (var fs = File.Create(currentPath))
{
    stream.CopyTo(fs);
}

Error Handling

The callback action wraps all processing in a try-catch block:
try
{
    // Process callback and update file
    responseObj = new { error = 0 };
}
catch
{
    responseObj = new { error = 1 };
}
Errors can occur due to:
  • Invalid JSON payload
  • Network errors when downloading from OnlyOffice server
  • File system errors when writing to storage
  • Missing or invalid fileId parameter

Implementation Details

Source Code Reference

The callback action is implemented in:
Controls/OnlyOfficeEditor/OnlyOfficeHandler.ashx.cs:71-109

Code Example

private static void Callback(HttpContext context)
{
    string body;
    using (var reader = new StreamReader(context.Request.InputStream, Encoding.UTF8))
    {
        body = reader.ReadToEnd();
    }

    var serializer = new JavaScriptSerializer();
    var responseObj = new { error = 0 };

    try
    {
        var payload = serializer.Deserialize<OnlyOfficeCallbackPayload>(body);
        var fileId = context.Request["fileId"];
        var uploads = UploadsPath(context);
        var currentPath = ResolveStoredFile(uploads, fileId);

        if (payload != null && 
            (payload.status == 2 || payload.status == 6) && 
            !string.IsNullOrWhiteSpace(payload.url) && 
            !string.IsNullOrWhiteSpace(currentPath))
        {
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | 
                                                   SecurityProtocolType.Tls11 | 
                                                   SecurityProtocolType.Tls;
            var req = (HttpWebRequest)WebRequest.Create(payload.url);
            req.Method = "GET";
            
            using (var resp = (HttpWebResponse)req.GetResponse())
            using (var stream = resp.GetResponseStream())
            using (var fs = File.Create(currentPath))
            {
                stream.CopyTo(fs);
            }
        }
    }
    catch
    {
        responseObj = new { error = 1 };
    }

    context.Response.ContentType = "application/json";
    context.Response.Write(serializer.Serialize(responseObj));
}

Usage in OnlyOffice Document Server

The callback action is configured in the OnlyOffice Document Server editor configuration:
var docEditor = new DocsAPI.DocEditor("placeholder", {
    document: {
        url: "https://your-app.com/OnlyOfficeHandler.ashx?action=download&fileId=doc123",
        fileType: "docx",
        key: "doc123",
        title: "Document.docx"
    },
    editorConfig: {
        callbackUrl: "https://your-app.com/OnlyOfficeHandler.ashx?action=callback&fileId=doc123"
    },
    // ... other config
});

Security Considerations

The callback action does not implement authentication or authorization. You should implement security measures to ensure only legitimate requests from your OnlyOffice Document Server are processed.

Security Risks

  1. Unauthenticated Requests: Any client can send callback requests
  2. File Overwriting: Malicious requests could overwrite files
  3. URL Injection: Arbitrary URLs could be provided in the payload

1. JWT Token Validation

OnlyOffice Document Server supports JWT tokens for secure callbacks:
private static void Callback(HttpContext context)
{
    // Validate JWT token from Authorization header
    if (!ValidateJwtToken(context.Request.Headers["Authorization"]))
    {
        context.Response.StatusCode = 401;
        return;
    }
    
    // Continue with callback processing...
}

2. IP Whitelist

Restrict callbacks to your OnlyOffice Document Server IP:
private static void Callback(HttpContext context)
{
    var allowedIps = new[] { "192.168.1.100", "10.0.0.5" };
    var clientIp = context.Request.UserHostAddress;
    
    if (!allowedIps.Contains(clientIp))
    {
        context.Response.StatusCode = 403;
        return;
    }
    
    // Continue with callback processing...
}

3. URL Validation

Ensure the callback URL originates from your OnlyOffice server:
if (payload != null && 
    (payload.status == 2 || payload.status == 6) && 
    !string.IsNullOrWhiteSpace(payload.url))
{
    var uri = new Uri(payload.url);
    if (uri.Host != "your-documentserver.com")
    {
        responseObj = new { error = 1 };
        return;
    }
    
    // Continue with download...
}

4. File Access Control

Verify user permissions before updating files:
var fileId = context.Request["fileId"];
if (!UserCanModifyFile(context.User, fileId))
{
    responseObj = new { error = 1 };
    return;
}

TLS Configuration

The handler configures secure protocols before making external requests:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | 
                                       SecurityProtocolType.Tls11 | 
                                       SecurityProtocolType.Tls;
This ensures communication with the OnlyOffice Document Server uses secure HTTPS connections.

Download Action

Download documents from server storage

Proxy Action

Proxy external document requests

Build docs developers (and LLMs) love