License

Configure Exchange export authorization, query remaining quota, and handle license errors.

Exchange reads the License in the server process running @univerjs-pro/exchange-node. See Office file import and export for conversion.

Configure authorization

Provide the License through the UNIVER_LICENSE and UNIVER_LICENSE_KEY environment variables. Calling configureExchange is optional: the SDK reads the environment once on the first export or quota query and reuses that configuration. Without environment credentials, Free applies. Supplied but invalid credentials return an error and cannot be used for export.

For explicit configuration, configureExchange({ license, licenseKey }) returns Promise<void> and completely ignores the environment. Await it before starting exports that should use the new credentials.

TypeScript
import { configureExchange, getExportQuota } from '@univerjs-pro/exchange-node'await configureExchange({  license: '<license content>',  licenseKey: '<licenseKey content>',})const quota = await getExportQuota()

Use the complete license and licenseKey contents supplied by your license provider, not file paths. Configure both together through your application's secret management system.

InputBehavior
Do not call configureExchangeRead both environment variables on first use; use Free when neither is set.
configureExchange({ license, licenseKey })Use only the explicit credentials; ignore the environment.
configureExchange({})Explicitly select Free; ignore the environment.
Only one credential is supplied in the selected sourceReturn INVALID_ARGUMENT; never fill the other field from a different source.

Once a complete environment configuration is read, it remains fixed even if a later operation fails. To replace the default credentials at runtime, explicitly call and await configureExchange. Failed configuration leaves the previous configuration in effect; handle the error before starting new exports.

ESM and CommonJS share configuration within the same JavaScript context. Each worker_threads Worker must configure itself or initialize from its environment. Exports use the configuration captured when the public export method is called; later credential changes do not affect exports already started.

Provide authorization for one operation

Pass a complete license and licenseKey pair in the options for an export API or getExportQuota to authorize only that operation without changing the default configuration. For example, query quota and export with the same credentials:

TypeScript
import { UniverInstanceType } from '@univerjs/core'import { ExchangeFormat, exportToBuffer, getExportQuota } from '@univerjs-pro/exchange-node'const credentials = { license: '<license content>', licenseKey: '<licenseKey content>' }const quota = await getExportQuota(credentials)const output = await exportToBuffer(workbook, {  type: UniverInstanceType.UNIVER_SHEET,  format: ExchangeFormat.XLSX,  ...credentials,})

This also applies to file exports, Snapshot exports, and optional PDF exports. Omitting both fields uses the default configuration; supplying only one returns INVALID_ARGUMENT. An explicit pair is never completed from the default configuration or environment, and empty strings are not treated as omitted. Invalid credentials return LICENSE_INVALID without falling back to the default commercial license.

Optional PDF support

Install the PDF extension package and import its entry before configuring authorization:

Shell
pnpm add @univerjs-pro/exchange-node @univerjs-pro/exchange-pdf-node-binding
TypeScript
import '@univerjs-pro/exchange-node/pdf'import { configureExchange, getExportQuota } from '@univerjs-pro/exchange-node'await configureExchange({  license: '<license content>',  licenseKey: '<licenseKey content>',})const quota = await getExportQuota()

This entry registers PDF support; native components load when used. PDF uses the same importBuffer, importFile, exportToBuffer, exportToFile, and corresponding Snapshot APIs with UniverInstanceType.UNIVER_PDF and ExchangeFormat.PDF. A PDF-only application does not need to load the Office native component. Environment-based configuration also applies to PDF.

Query remaining quota

getExportQuota({ license, licenseKey }) returns Promise<ExportQuota> for the authorization's shared Office and PDF quota. Omitting credentials queries the default configuration. It accepts no Unit type and does not check permission to export a particular type; that check occurs during export.

Queries neither consume nor reserve quota, and do not check the SDK version, activation time, or export type entitlement. A zero balance still returns a successful snapshot. Other requests may consume quota afterward, so handle actual export errors as well.

Before authorization starts, a limited-quota query returns the first authorization month with a future periodStart. A successful query or a valid status does not grant permission to export. Version, activation, type entitlement, available quota, and concurrency checks occur during export.

FieldTypeMeaning
licenseStatus'not_configured' | 'expired' | 'valid'Export subscription is unconfigured, expired, or not expired. valid does not mean export admission checks have passed. Invalid credentials return an error.
expiresAtstring | nullExport subscription expiry as a UTC ISO timestamp; null when unconfigured or no expiry applies.
observedAtstringUTC ISO timestamp of this snapshot.
limitnumber | nullCurrent monthly export limit; null when unlimited.
usednumber | nullSuccessful exports in the current month; null when unlimited.
reservednumber | nullIn-flight exports occupying the current month's quota; null when unlimited.
remainingnumber | nullAvailable exports: max(0, limit - used - reserved); null when unlimited.
periodStartstring | nullInclusive UTC ISO start of the queried monthly quota window; the first period starts in the future before activation. null when unlimited.
periodEndstring | nullExclusive UTC ISO end of the queried monthly quota window; null when unlimited.

periodEnd marks the start of the next monthly quota window; expiresAt marks the end of the export subscription. A valid subscription always uses commercial quota. Exhaustion never selects Free, and a new commercial quota window begins the following month. Only subscription expiry selects the existing remaining Free quota, without resetting or granting it again.

Example of a limited-quota snapshot:

JSON
{  "licenseStatus": "valid",  "expiresAt": "2027-10-19T23:59:59Z",  "observedAt": "2026-10-21T09:00:00Z",  "limit": 500,  "used": 20,  "reserved": 1,  "remaining": 479,  "periodStart": "2026-10-19T00:00:00Z",  "periodEnd": "2026-11-19T00:00:00Z"}

Use export quota

Free allows 10 successful exports per authorization month. Commercial export quota, concurrency, and version entitlements depend on the purchased license. Neither Free nor commercial licenses impose file-size or cell-count limits. Use the query response for the current period and remaining quota. Unused monthly quota does not roll over.

Imports do not require export authorization and do not consume export quota. Office and PDF exports using the same commercial license within a deployment share quota. See Office file import and export for Exchange conversion formats.

Each successful conversion consumes one export. Returning a Buffer counts as success. A later file-write, upload, or download failure does not refund that export; another successful conversion consumes another export. When the current period has no remaining quota, new exports are rejected. Wait for the next authorization period or provide a valid license with a higher quota; an exhausted valid commercial license does not use Free quota.

Handle errors

Use the structured code to identify errors instead of parsing message text. Your UI can map error codes to localized messages. Retain diagnostic information for technical support.

TypeScript
import { UniverInstanceType } from '@univerjs/core'import { ExchangeError, ExchangeFormat, exportToBuffer } from '@univerjs-pro/exchange-node'try {  const output = await exportToBuffer(workbook, {    type: UniverInstanceType.UNIVER_SHEET,    format: ExchangeFormat.XLSX,  })} catch (error) {  if (error instanceof ExchangeError) {    // Display the message for error.code, e.g. LICENSE_EXPORT_QUOTA_EXCEEDED when the quota runs out    console.error(error.code)  } else {    throw error  }}

The table distinguishes quota queries (getExportQuota) from actual exports. Both APIs return Promises; handle failures with await and try/catch.

CodeOperationMeaning and response
LICENSE_EXPORT_QUOTA_EXCEEDEDExport onlyInsufficient export quota for the current period. Query quota or contact sales to adjust the license.
LICENSE_CONCURRENCY_TIMEOUTExport onlyWaiting for available export concurrency timed out. Reduce concurrent exports before submitting again.
LICENSE_UNIT_TYPE_REJECTEDExport onlyThis export type is not licensed or its type entitlement has expired. Provide a valid license covering the type.
LICENSE_INVALIDQuery, exportThe license is invalid. Check the complete credentials or contact the license provider for an update.
LICENSE_POLICY_INVALIDQuery, exportThe authorization configuration does not meet SDK requirements. Contact the license provider for an update.
LICENSE_NOT_YET_EFFECTIVEExport onlyAuthorization has not started yet. Use it after its effective date.
LICENSE_VERSION_NOT_ALLOWEDExport onlyThe current SDK version is outside the licensed range. Use a matching version or update the license.
UNSUPPORTED_FORMATExport onlyThe format is unsupported or incompatible with the Unit type. Check export options.
INVALID_FILEExport onlyThe conversion input is invalid. Check its contents.
INCOMPLETE_SNAPSHOTExport onlyExport data is incomplete. Provide complete data or a complete Snapshot.
CONVERSION_FAILEDExport onlyConversion failed. Retain the error and check the input contents.
IO_ERRORExport onlyFile input/output failed. An output-write failure after successful conversion has already consumed an export.
INVALID_ARGUMENTQuery, exportIncomplete arguments or credentials. Check the configuration.
NATIVE_LOAD_FAILEDQuery, exportA native SDK component could not load. Check package and runtime compatibility.
LICENSE_USAGE_STATE_INVALIDQuery, exportLicense usage status cannot be verified. Preserve the error and contact technical support.
LICENSE_USAGE_STORAGE_ERRORQuery, exportLicense usage processing failed. Preserve the error, contact technical support, and avoid automatic resubmission.

Applications can derive expiry reminders from licenseStatus and expiresAt; the SDK does not return a separate notice list.

After a license usage processing error, do not infer accounting solely from the error. Preserve the complete error and contact technical support.

How is this guide?

© 2026 DreamNum Co., Ltd.