TMA CloudTMA Cloud
API Reference

OnlyOffice API

Endpoints for opening, serving and saving documents through OnlyOffice.

Endpoints for opening, serving and saving documents through OnlyOffice.

Editor Configuration

GET /api/onlyoffice/config/:id

Get OnlyOffice editor configuration for a file.

Permission: files.download. A sub-user without it receives 403. Without files.edit the editor opens in view-only mode.

Edit locks: a config in edit mode takes the file's edit lock for its document session. While anyone holds the lock (another browser session or a desktop app), the config comes back in view mode. Every open gets its own document key, so two browser sessions would otherwise save over each other instead of co-editing.

Rate limiting: General API limit (30,000 per 15 minutes per user).

Validation:

  • The file id from the URL is required.
  • The file's extension must be one supported by OnlyOffice.
  • The file's actual MIME type must match the expected type for its extension.
  • The server will return a 400 Bad Request if a MIME type mismatch is detected.

Response:

{
  "config": {
    "document": {
      "fileType": "docx",
      "key": "file_key",
      "title": "document.docx",
      "url": "https://example.com/api/onlyoffice/file/123"
    },
    "editorConfig": {
      "mode": "edit",
      "callbackUrl": "https://example.com/api/onlyoffice/callback"
    }
  },
  "token": "signed_jwt_token",
  "onlyofficeJsUrl": "https://onlyoffice.example.com/web-apps/apps/api/documents/api.js"
}

Viewer

GET /api/onlyoffice/viewer/:id

Get standalone viewer page for a file.

Permission: files.download, as for the config endpoint.

Rate limiting: General API limit (30,000 per 15 minutes per user).

Validation:

  • The file id from the URL is required.
  • The file's extension must be one supported by OnlyOffice.
  • The file's actual MIME type must match the expected type for its extension.
  • The server will return a 400 Bad Request (as JSON or HTML) if a MIME type mismatch is detected.

Response: HTML page with OnlyOffice viewer. Its inline script carries the request's CSP nonce, and the editor config embedded in it is escaped for use inside a <script> element. See Security Model.

Open in a Browser Tab

The desktop app opens documents in the user's browser, which has no session cookie for TMA Cloud. It asks for a one-minute link instead.

POST /api/onlyoffice/ticket/:id

Create a link that opens the document without signing in.

Permission: files.download. The link opens in edit mode only when the caller also has files.edit.

Query: theme (optional) - light or dark, passed on to the editor.

Response:

{
  "url": "https://example.com/api/onlyoffice/open/123?ticket=signed_token",
  "expiresIn": 60
}

Errors: 404 when the file is not in the account; 424 when OnlyOffice is not configured.

GET /api/onlyoffice/open/:id?ticket=...

Serve the same page as the viewer endpoint for the user named in the ticket. No session is needed. A ticket is signed with JWT_SECRET, names one file, and expires 60 seconds after it was made. An expired or altered ticket gets a "This link has expired" page with status 401.

These links are allowed in desktop-app-only mode, since the browser opening them sends no desktop header.

File Serving

GET /api/onlyoffice/file/:id

Serve file to OnlyOffice server (requires signed token).

Rate limiting: General API limit (10,000 per 15 minutes per IP).

Response: File content

Callback

POST /api/onlyoffice/callback

OnlyOffice callback endpoint. Called by the OnlyOffice Document Server when document state changes.

Request Body: OnlyOffice callback data including status, key, url, and forcesavetype.

Callback Statuses:

StatusMeaning
0Document is being edited
2Document is ready for saving (all users closed)
3Document saving error
4Document closed with no changes
6Document is being edited, current state saved (forcesave)

Forcesave Types (when status = 6):

TypeTrigger
0Command service request (auto-save service)
1Save button click (Ctrl+S)
2Timer-based (autoAssembly)
3Form submission

Response:

{
  "error": 0
}

Note: The callback returns error: 0 after it accepts or handles a save callback. A quota rejection returns error: 1; an invalid callback token returns 401.

Auto-Save

Documents are saved to storage periodically while being edited, not only when the editor closes.

How it works:

  1. When a document is opened through the viewer or config endpoint, the app creates one schedule for its document key in the job_schedules table.
  2. Every five minutes, the standalone worker sends a forcesave command to the OnlyOffice Document Server command service API (/command). The document key is also sent as the recommended shardkey query parameter. If /command returns 404, the worker uses the pre-8.2 path /coauthoring/CommandService.ashx instead.
  3. OnlyOffice responds by calling the callback endpoint with status 6 and forcesavetype: 0.
  4. The callback handler streams the current document through encryption to object storage, without loading the whole document into memory. After the database points at the new object, deletion of the old object is queued.
  5. When all users close the document (status 2 or 4), the app removes its schedule. A command response that says the document is no longer open also removes it.

The same events drive the session's edit lock. A browser session's lock lasts ten minutes; each force-save tick and each status 1 callback (a user joined or left) renews it. Status 2 or 4, or a tick that finds the document closed, releases it. A browser that disappears without OnlyOffice noticing frees the file within ten minutes.

The command service is an OnlyOffice-supported server API. A successful command returns error: 0; error: 4 means there are no changes to save, and error: 1 that the document is no longer open. Other command and network errors are retried by the queue.

The interval is fixed at five minutes. The background worker must be running for scheduled force-save commands.

Editor configuration:

The editor config includes customization.forcesave: true, which allows manual saves through Ctrl+S or the save button without closing the document. The worker's command-service request does not depend on that UI setting.

Command service request format:

{
  "c": "forcesave",
  "key": "userId-fileId-timestamp"
}

When JWT is enabled, the payload is signed and sent as { "token": "signed_jwt" }.

Last updated on

On this page