Comprehensive Guide for Developers: UI & SDK Integration, Configuration, and API Reference
Essential configuration options for initializing the PDF Web SDK.
Your license key string.
const editor = await PdfEditor({
license: 'YOUR_LICENSE_KEY',
});
URL prefix under which the pwv-* static asset folders (worker, fonts, i18n, cursors, stamps) are served, e.g. '/custom-path' when hosting at example.com/custom-path/pwv-workers, example.com/custom-path/pwv-fonts, etc. Defaults to the domain root ('') — copy the package's public/pwv-* folders there, or set this to match wherever you host them.
const editor = await PdfEditor({
license: 'YOUR_LICENSE_KEY',
basePath: '/custom-path',
});
DOM element where the viewer UI will be rendered. Required for full UI mode.
Give the container an explicit height. For a viewer that fills the page, use
height: 100dvh so its bottom controls stay above the mobile browser's address and
navigation bars. When the page also has a header, size the page to 100dvh and let
the viewer container fill the remaining space with flex: 1; min-height: 0.
Embedded viewers can keep the height assigned by their host layout.
const editor = await PdfEditor({
license: 'YOUR_LICENSE_KEY',
container: document.getElementById('pdf-container'),
});
Hide toolbar and sidebar for minimal UI mode.
// Full UI mode (default)
const editor = await PdfEditor({
license: 'YOUR_LICENSE_KEY',
container: document.getElementById('pdf-container'),
hideToolsPanel: false,
});
// Minimal UI mode
const editor = await PdfEditor({
license: 'YOUR_LICENSE_KEY',
container: document.getElementById('pdf-container'),
hideToolsPanel: true,
});
Initial zoom/fit mode applied to every document on open — including documents
opened through built-in flows (home screen, Recents, cloud drives, drag &
drop). A pageView passed to an individual open call still takes precedence.
When omitted, the default is responsive: fit-width on viewports narrower
than 1024px, fit-page otherwise.
import { PdfEditor, PdfPageView } from '@avanquest/pdf-web-viewer';
const editor = await PdfEditor({
license: 'YOUR_LICENSE_KEY',
container: document.getElementById('pdf-container'),
// Every document opens fitted to the page width.
defaultPageView: PdfPageView.fitWidth,
});
Available values: PdfPageView.fitWidth, PdfPageView.fitPage,
PdfPageView.actualSize.
Control whether opening a new document creates a new tab or replaces the current view.
// New tab per document (default)
const editor = await PdfEditor({
license: 'YOUR_LICENSE_KEY',
container: document.getElementById('pdf-container'),
openDocumentsInNewTab: true,
});
// Replace current view (single-document mode)
const editor = await PdfEditor({
license: 'YOUR_LICENSE_KEY',
container: document.getElementById('pdf-container'),
openDocumentsInNewTab: false,
});
To read or change this setting after initialization, use editor.ui.pdfWebElement.getOpenDocumentsInNewTab() /
setOpenDocumentsInNewTab() — see Document Viewer Wrapper Element.
Reopening a document returns it to the page, zoom and layout it was last closed at. On by
default; set false to have every document open at the top.
const editor = await PdfEditor({
license: 'YOUR_LICENSE_KEY',
container: document.getElementById('pdf-container'),
restoreLastViewSettings: false,
});
The position is stored on the document's entry in the recent-files history, so it needs
recentsConfig to survive a restart — without it, resuming works for as long as the page is
open and starts over afterwards. A file the history cannot record (nothing could reopen it) is
not resumed either.
The reader can change this in Settings ▸ General. To follow that choice, persist
restoreLastViewSettings from onConfigChange and pass
it back here next time. To read or change it at runtime, use
editor.ui.pdfWebElement.getRestoreLastViewSettings() / setRestoreLastViewSettings().
Starts the navigationSidebar layout's left rail collapsed to icons. Off by default; ignored by
layouts that render no rail.
const editor = await PdfEditor({
license: 'YOUR_LICENSE_KEY',
container: document.getElementById('pdf-container'),
layoutConfig: { variant: LayoutVariant.NAVIGATION_SIDEBAR },
sidebarCollapsed: true,
});
The reader can change this from the rail's collapse button or in Settings ▸ Appearance. To follow
that choice, persist sidebarCollapsed from onConfigChange
and pass it back here next time. To read or change it at runtime, use
editor.ui.pdfWebElement.getSidebarCollapsed() / setSidebarCollapsed().
Lets a collapsed rail peek open while the pointer is over it, drawn over the document rather than pushing it. Off by default — a collapsed rail stays collapsed until the reader expands it.
const editor = await PdfEditor({
license: 'YOUR_LICENSE_KEY',
container: document.getElementById('pdf-container'),
layoutConfig: { variant: LayoutVariant.NAVIGATION_SIDEBAR },
sidebarCollapsed: true,
sidebarExpandOnHover: true,
});
The reader can change this in Settings ▸ Appearance, where the row is only enabled while the rail
is collapsed. Persist sidebarExpandOnHover from
onConfigChange and pass it back to restore it; at runtime
use editor.ui.pdfWebElement.getSidebarExpandOnHover() / setSidebarExpandOnHover().
Saving, Save as and Download — what they do, when the target picker appears and which option decides it — are covered in Saving & Downloading.
A document's initial path comes from the open call (initialDocument: { file, path } or
pdfWebService.openDocument(file, { path })); that is the file Save writes back to.
Translate, OCR, Convert (to Word, Excel, PowerPoint and PDF/A), HTML to PDF, eSign and opening Office documents (converted to PDF first) are server-side operations: the viewer uploads the document to an HTTP API, polls the operation and downloads the result. Two options control where those calls go and how they are authorized. Convert to text, images, JSON and Markdown runs locally and makes no API call.
Base URL of the online tools API. Defaults to
https://api-developers.avanquest.com. Point it at your own host to route the
calls through a proxy of yours.
const editor = await PdfEditor({
license: 'YOUR_LICENSE_KEY',
container: document.getElementById('pdf-container'),
apiToolsUrl: 'https://pdf-api.example.com',
});
Which credentials the viewer sends with each call to apiToolsUrl:
apiKey (default): X-API-KEY: <your license key> — the standard setup, no
extra configuration needed.umToken: Authorization: Bearer <access token> taken from the signed-in
user-management session, so the API bills and authorizes the user rather
than the integration. Requires userManagementConfig;
the token is renewed first when it has expired, and while nobody is signed in
the request goes out with no auth header at all.none: no auth header. For a proxy that holds the credentials itself and adds
them server-side — the browser then never sees them.// Calls are authorized as the signed-in user
const editor = await PdfEditor({
license: 'YOUR_LICENSE_KEY',
container: document.getElementById('pdf-container'),
apiAuthMode: 'umToken',
userManagementConfig: {
loginUrl: 'https://your-idp.example.com',
clientId: 'your-oidc-client',
},
});
// Your proxy attaches the real credentials; nothing secret reaches the browser
const editor = await PdfEditor({
license: 'YOUR_LICENSE_KEY',
container: document.getElementById('pdf-container'),
apiToolsUrl: 'https://pdf-api.example.com',
apiAuthMode: 'none',
});
Extra HTTP headers merged into every call to apiToolsUrl, applied after the
apiAuthMode auth header so these can override it. Only needed if you route
those calls through your own infrastructure and it expects extra headers —
e.g. a gateway token or a tenant identifier.
Pass a plain object for static headers, or a function for values that can go
stale (it is called fresh before every request, and may return a Promise).
// Static header
const editor = await PdfEditor({
license: 'YOUR_LICENSE_KEY',
container: document.getElementById('pdf-container'),
apiToolsUrl: 'https://pdf-api.example.com',
apiToolsHeaders: { 'X-Tenant-Id': 'acme-corp' },
});
// Resolved fresh before each request
const editor = await PdfEditor({
license: 'YOUR_LICENSE_KEY',
container: document.getElementById('pdf-container'),
apiToolsUrl: 'https://pdf-api.example.com',
apiToolsHeaders: async () => ({ 'X-Gateway-Token': await getGatewayToken() }),
});
Webhooks the API calls when it finishes a job in the background, sent as the
X-Callback-Url header.
The API cancels an online-tool job that exceeds its time limit. Without this option that is simply an error. With it, the viewer re-submits the run with the header, tells the user the work continues in the background, and the API reports the finished (or failed) document to your endpoint — which is where you mail it out to the user.
Give each tool its own URL. The callback body is the same payload
GET /operation/v1/{operationId}/status returns, and nothing in it names the tool
that produced it, so the URL you receive on is the only thing separating an OCR
result from a Translate one. A tool left unset keeps the old behavior.
const editor = await PdfEditor({
license: 'YOUR_LICENSE_KEY',
container: document.getElementById('pdf-container'),
apiCallbackUrls: {
ocr: 'https://api.example.com/pdf-tools/callback/ocr',
translate: 'https://api.example.com/pdf-tools/callback/translate',
},
});
Control how the Translate workflow handles scanned PDFs or embedded images when OCR is recommended.
ask (default): show the OCR prompt when needed.activate-ocr: enable OCR automatically and continue translation.proceed-without-ocr: continue translation without enabling OCR.const editor = await PdfEditor({
license: 'YOUR_LICENSE_KEY',
container: document.getElementById('pdf-container'),
translateConfig: {
ocrScanPreference: 'ask',
},
});
Specify a document to be opened automatically as soon as the viewer is initialized. This accepts an object containing a File instance.
// First, obtain a File object (e.g., from a file input or by fetching)
const response = await fetch('path/to/document.pdf');
const blob = await response.blob();
const initialFile = new File([blob], 'document.pdf', { type: 'application/pdf' });
const editor = await PdfEditor({
license: 'YOUR_LICENSE_KEY',
container: document.getElementById('pdf-container'),
initialDocument: {
file: initialFile,
},
});
const response = await fetch('document.pdf');
const blob = await response.blob();
const initialFile = new File([blob], 'document.pdf', { type: 'application/pdf' });
const editor = await PdfEditor({
// Required
license: 'YOUR_LICENSE_KEY',
// Container for full UI
container: document.getElementById('pdf-container'),
// Initial Document to open on load
initialDocument: {
file: initialFile,
},
// Asset path prefix (optional - defaults to the domain root)
basePath: '',
// UI mode
hideToolsPanel: false, // Full UI with toolbar and sidebar
// Document behavior
openDocumentsInNewTab: true, // Each document opens in its own tab
// Translate behavior
translateConfig: {
ocrScanPreference: 'ask',
},
});