USIP Integration

GitHubEdit on GitHub

Univer Pro does not include an account system by default. If you need identity verification, permission control, or system integration, use USIP (Univer Server Integration Protocol). USIP is an SPI: Univer defines the interfaces, and your system implements them.

Use Cases

  • Access requires login
  • Role-based editing permissions
  • Sync collaborator info, comments, and edit time

Integration Flow

  1. Implement the USIP APIs (see below)
  2. Enable USIP in deployment config
  3. Forward auth headers from the client (e.g., token)

USIP APIs

USIP currently covers three categories:

  • 👥 Account: identity verification, user info
  • 🔒 Permissions: role and collaborators
  • 📄 Document: last edit time

User Authentication

When It’s Called

Every request between client and server triggers authentication.

Flow

Flow

API Definition

GET
Headers
All request headers are forwarded to help you authenticate
No Parameters
Response
application/json
ParameterTypeExampleDescription
userObject-Returned on successful authentication
userIDstringace55655ceabd55User ID (recommend open_uid)
namestringaliceDisplay name for collaborators
avatarstringhttps://image.xx/acde55acb45bbead55Avatar URL for collaborators
{  "user": {    "userID": "ace55655ceabd55g",    "name": "alice",    "avatar": "https://image.xx/acde55acb45bbead55"  }}

Batch User Info

When It’s Called

For showing collaborator avatars/names and comment authors.

Flow

Flow

API Definition

POST
Headers
No custom headers; user headers are not forwarded
Body Parameters
ParameterTypeExampleDescription
userIDsarray[string]["user_id1", "user_id2"]User IDs to resolve
{  "userIDs": [    "user_id1",    "user_id2",    "user_id3"  ]}
Response
application/json
ParameterTypeExampleDescription
usersarray[Object]-User objects; same schema as authentication
{  "users": [    {      "userID": "user_id1",      "name": "name1",      "avatar": "https://xxxx"    },    {      "userID": "user_id2",      "name": "name2",      "avatar": "https://xxxx"    },    {      "userID": "user_id3",      "name": "name3",      "avatar": "https://xxxx"    }  ]}

User Role

When It’s Called

To determine permissions for reading/editing a document.

Flow

Flow

API Definition

GET
Headers
No custom headers; user headers are not forwarded
Query Parameters
ParameterTypeExampleDescription
userIDstringacd5455e44fc5bb55User ID
unitIDstringacff-adebc125e45bDocument ID
curl -X GET "http://sample.univer.ai/role?unitID=acff-adebc125e45b&userID=acd5455e44fc5bb55"
Response
application/json
ParameterTypeExampleDescription
userIDstringacd5455e44fc5bb55User ID in request
rolestringeditorRole: owner, editor, reader
{  "userID": "acd5455e44fc5bb55",  "role": "editor"}

Document Collaborators

When It’s Called

Required when selecting users for protected ranges or sheets.

Flow

Flow

API Definition

POST
Headers
No custom headers; user headers are not forwarded
Body Parameters
ParameterTypeExampleDescription
unitIDsarray[string]["unit_id1", "unit_id2"]Document IDs
{  "unitIDs": [    "unit_id1",    "unit_id2",    "unit_id3"  ]}
Response
application/json
ParameterTypeExampleDescription
collaboratorsarray[Object]-Collaborators grouped by document
unitIDstringunit_id1Document ID
subjectsarray[Object]-Collaborator list
rolestringeditorRole: owner, editor, reader
subjectObject-Collaborator info
typestringuserMust be "user"
idstringacdef12555b12User ID
namestringaliceUser name
avatarstringhttps://image.ai/36554Avatar URL
{  "collaborators": [    {      "unitID": "unit_id1",      "subjects": [        {          "subject": {            "id": "1",            "name": "alice",            "avatar": "https://image.ai/36554",            "type": "user"          },          "role": "owner"        },        {          "subject": {            "id": "2",            "name": "bob",            "avatar": "https://image.ai/36559",            "type": "user"          },          "role": "editor"        }      ]    }  ]}

Notify Last Edit Time

When It’s Called

For your system to display last edit time.

API Definition

POST
Headers
No custom headers; user headers are not forwarded
Body Parameters
ParameterTypeExampleDescription
unitIDstringacff-adebc125e45bDocument ID
editTimeUnixMsint1762591632345Unix timestamp in milliseconds
{  "unitID": "unit_id1",  "editTimeUnixMs": 1762591632345}
Response
application/json
ParameterTypeExampleDescription
{}

Configure USIP

.env.custom
USIP_ENABLED=true
USIP_URI_CREDENTIAL=https://your-domain/usip/credential
USIP_URI_USERINFO=https://your-domain/usip/userinfo
USIP_URI_ROLE=https://your-domain/usip/role
USIP_URI_COLLABORATORS=https://your-domain/usip/collaborators
USIP_URI_UNITEDITTIME=https://your-domain/usip/unit-edit-time

USIP_APIKEY=

AUTH_PERMISSION_ENABLE_OBJ_INHERIT=false
AUTH_PERMISSION_CUSTOMER_STRATEGIES=
values.yaml
universer:
  config:
    usip:
      enabled: true
      uri:
        userinfo: 'https://your-domain/usip/userinfo'
        collaborators: 'https://your-domain/usip/collaborators'
        role: 'https://your-domain/usip/role'
        credential: 'https://your-domain/usip/credential'
        unitEditTime: 'https://your-domain/usip/unit-edit-time'
      apikey: ''
    auth:
      permission:
        enableObjInherit: false
        customerStrategies: ''

Note: When USIP is enabled, all five endpoints must be configured and implemented.

If your USIP service is exposed on the public network, to ensure API request security, we can follow a mechanism similar to AI API requests. You can generate an API key and configure it in the Univer server. When calling the USIP APIs, the request will include the header x-api-key: API_KEY, which you can use to verify the legitimacy of the request.

Permission Model

Univer uses RBAC with fixed roles: owner, editor, reader. You can override minimum role requirements for permission points.

Default permission points:

PermissionEnumDescriptionMinimum RoleRole Enum
ManageCollaborator2Invite/delete collaboratorsowner2
Copy6Copy contentreader0
Print3Printeditor1
Duplicate4Duplicate documenteditor1
Share7Share documentreader0
Export8Exporteditor1
Comment5Commentreader0
View0Viewreader0
MoveSheet25Move worksheeteditor1
DeleteSheet26Delete worksheeteditor1
HideSheet27Hide worksheeteditor1
CopySheet28Copy worksheeteditor1
RenameSheet29Rename worksheeteditor1
CreateSheet30Create worksheeteditor1
SetCellStyle33Set cell styleeditor1
SetCellValue34Set cell valueeditor1
InsertHyperlink16Insert hyperlinkeditor1
Sort17Sorteditor1
Filter18Filtereditor1
PivotTable19Pivot tableeditor1
RecoverHistory43Recover historyeditor1
ViewHistory44View historyreader0
SelectProtectedCells31Select protected cellseditor1
SelectUnProtectedCells32Select unprotected cellseditor1
SetRowStyle35Set row styleeditor1
SetColumnStyle36Set column styleeditor1
InsertRow37Insert roweditor1
InsertColumn38Insert columneditor1
DeleteRow39Delete roweditor1
DeleteColumn40Delete columneditor1
Delete42Delete documentowner2
CreatePermissionObject45Create protected range/sheeteditor1

To restrict copy/print to owners:

.env.custom
AUTH_PERMISSION_CUSTOMER_STRATEGIES=[{"action": 3, "role": 2}, {"action": 6, "role": 2}]

K8s config:

values.yaml
universer:
  config:
    auth:
      permission:
        customerStrategies: '[ {"action": 3, "role": 2}, {"action": 6, "role": 2} ]'

Object Permission Inheritance

By default, document owners do not automatically own all protected ranges/sheets. To enable inheritance:

.env.custom
AUTH_PERMISSION_ENABLE_OBJ_INHERIT=true

K8s config:

values.yaml
universer:
  config:
    auth:
      permission:
        enableObjInherit: true

Example Implementation

See: https://github.com/dream-num/usip-example

Client Headers

If you need to add custom headers (e.g. Authorization token), use HTTPService interceptors:

import { HTTPService } from '@univerjs/preset-sheets-core'

const injector = univer.__getInjector()
const httpService = injector.get(HTTPService)
httpService.registerHTTPInterceptor({
  priority: 0,
  interceptor: (request, next) => {
    // request.headers.set('Authorization', 'Bearer your-token-here')
    return next(request)
  },
})
import { HTTPService } from '@univerjs/network'

const injector = univer.__getInjector()
const httpService = injector.get(HTTPService)
httpService.registerHTTPInterceptor({
  priority: 0,
  interceptor: (request, next) => {
    // request.headers.set('Authorization', 'Bearer your-token-here')
    return next(request)
  },
})

If you use Edit History, apply the same interceptor to HistoryUniver:

historyLoaderService.historyUniver$.subscribe((historyUniver) => {
  if (!historyUniver) return

  const injector = historyUniver.__getInjector()
  const httpService = injector.get(HTTPService)
  httpService.registerHTTPInterceptor({
    priority: 0,
    interceptor: (request, next) => {
      // request.headers.set('Authorization', 'Bearer your-token-here')
      return next(request)
    },
  })
})

For a full example, see the Univer Pro Sheet starter kit.

How is this guide?