Collaboration

Follow Collaboration integration to run the official example, connect your application, and verify persistence and authorization. Implementation details and runnable Web/Server examples are maintained at Collaboration Quick Start.

Create the Unit through an authenticated business API calling Collaboration Service, then load the returned identifier in the browser. Configure HTTP, Session Ticket, and WebSocket entry points together using Quick Start. Persist data with a Database Adapter and enforce read, JOIN, and edit policies through server middleware.

Before using these APIs, verify that your target backend supports PDF Units. A working Sheets collaboration example does not establish PDF support.

Load a collaborative PDF

After creating a PDF unit through the server API or importPdfToUnitIdAsync, load it with the collaboration Facade:

Set the current user before loading the document. See Collaboration integration.

TypeScript
import { UserManagerService } from '@univerjs/core'import '@univerjs-pro/collaboration-client/facade'univer.__getInjector().get(UserManagerService).setCurrentUser({ userID, name, avatar })const pdf = await univerAPI.getCollaboration().loadPdfAsync(unitId)if (!pdf) {  throw new Error(`PDF unit not found: ${unitId}`)}console.log(pdf.getId(), pdf.getName())

loadPdfAsync loads the server snapshot, prepares the collaboration session, and returns an FPdf. It returns null when the unit cannot be associated with a PDF.

Use synchronization status, retries, and conflict recovery to build saving indicators and protect unacknowledged edits before reloading.

Removal of built-in URL loading for collaborative documents

Note

Starting with version 1.2.0, Univer has removed built-in URL loading for collaborative documents. It no longer automatically reads the unit and type URL parameters to load a collaborative document.

If your application relies on this behavior, you can restore it with a custom plugin.

Integrate the custom plugin

Copy the four files below into your project using this directory structure:

text
custom-url-load/├── plugin.ts├── controllers/│   └── data-loader.controller.ts└── services/    ├── url.service.ts    └── web-url.service.ts

After initializing the editor and collaboration plugins, set the current user before registering CustomUrlLoadPlugin.

TypeScript
import { UserManagerService } from '@univerjs/core'import { CustomUrlLoadPlugin } from './custom-url-load/plugin'univer.__getInjector().get(UserManagerService).setCurrentUser({ userID, name, avatar })univer.registerPlugin(CustomUrlLoadPlugin)

Once registered, the plugin loads the document, so you do not need to call loadPdfAsync() for the same document. If your application already loads documents through the Facade, you can keep the approach in the previous section and handle URLs according to your application’s needs.

Complete plugin code

TypeScript
import { UniverCollaborationClientPlugin } from '@univerjs-pro/collaboration-client'import { DependentOn, Inject, Injector, Plugin } from '@univerjs/core'import { CollaborationDataLoaderController } from './controllers/data-loader.controller'import { IURLService } from './services/url.service'import { WebURLService } from './services/web-url.service'@DependentOn(UniverCollaborationClientPlugin)export class CustomUrlLoadPlugin extends Plugin {  static override pluginName = 'CUSTOM_URL_LOAD_PLUGIN'  constructor(    _config: undefined,    @Inject(Injector) protected override readonly _injector: Injector  ) {    super()  }  override onStarting(): void {    this._injector.add([IURLService, { useClass: WebURLService }])    this._injector.add([CollaborationDataLoaderController])    this.disposeWithMe(this._injector.get(IURLService))    this.disposeWithMe(this._injector.get(CollaborationDataLoaderController))  }}

How is this guide?

© 2026 DreamNum Co., Ltd.