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.
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.
| Input | Behavior |
|---|---|
Do not call configureExchange | Read 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 source | Return 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:
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:
pnpm add @univerjs-pro/exchange-node @univerjs-pro/exchange-pdf-node-bindingimport '@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.
| Field | Type | Meaning |
|---|---|---|
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. |
expiresAt | string | null | Export subscription expiry as a UTC ISO timestamp; null when unconfigured or no expiry applies. |
observedAt | string | UTC ISO timestamp of this snapshot. |
limit | number | null | Current monthly export limit; null when unlimited. |
used | number | null | Successful exports in the current month; null when unlimited. |
reserved | number | null | In-flight exports occupying the current month's quota; null when unlimited. |
remaining | number | null | Available exports: max(0, limit - used - reserved); null when unlimited. |
periodStart | string | null | Inclusive UTC ISO start of the queried monthly quota window; the first period starts in the future before activation. null when unlimited. |
periodEnd | string | null | Exclusive 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:
{ "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.
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.
| Code | Operation | Meaning and response |
|---|---|---|
LICENSE_EXPORT_QUOTA_EXCEEDED | Export only | Insufficient export quota for the current period. Query quota or contact sales to adjust the license. |
LICENSE_CONCURRENCY_TIMEOUT | Export only | Waiting for available export concurrency timed out. Reduce concurrent exports before submitting again. |
LICENSE_UNIT_TYPE_REJECTED | Export only | This export type is not licensed or its type entitlement has expired. Provide a valid license covering the type. |
LICENSE_INVALID | Query, export | The license is invalid. Check the complete credentials or contact the license provider for an update. |
LICENSE_POLICY_INVALID | Query, export | The authorization configuration does not meet SDK requirements. Contact the license provider for an update. |
LICENSE_NOT_YET_EFFECTIVE | Export only | Authorization has not started yet. Use it after its effective date. |
LICENSE_VERSION_NOT_ALLOWED | Export only | The current SDK version is outside the licensed range. Use a matching version or update the license. |
UNSUPPORTED_FORMAT | Export only | The format is unsupported or incompatible with the Unit type. Check export options. |
INVALID_FILE | Export only | The conversion input is invalid. Check its contents. |
INCOMPLETE_SNAPSHOT | Export only | Export data is incomplete. Provide complete data or a complete Snapshot. |
CONVERSION_FAILED | Export only | Conversion failed. Retain the error and check the input contents. |
IO_ERROR | Export only | File input/output failed. An output-write failure after successful conversion has already consumed an export. |
INVALID_ARGUMENT | Query, export | Incomplete arguments or credentials. Check the configuration. |
NATIVE_LOAD_FAILED | Query, export | A native SDK component could not load. Check package and runtime compatibility. |
LICENSE_USAGE_STATE_INVALID | Query, export | License usage status cannot be verified. Preserve the error and contact technical support. |
LICENSE_USAGE_STORAGE_ERROR | Query, export | License 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?