Engine & handles
The engine exposes three layers of objects: the engine itself, a document handle for each open document, and a page handle for per-page work. Each layer narrows the scope of what you operate on.
The engine#
localEngine() returns an object implementing the Engine interface:
interface Engine {
open(input: OpenInput, options?: OpenOptions): AbortablePromise<DocumentHandle>;
destroy(): AbortablePromise<void>;
}open() is the only entry point.
The local engine accepts { kind: 'bytes' } (and { kind: 'layerBytes' }
for layer documents) — you hand it the PDF bytes and a stable id (see
Getting started).
Call destroy() when your app is shutting the engine down; existing handles
should be close()d first.
One engine can hold many open documents at once. When you open by token, each handle carries its own per-document bearer, so a single engine can serve several independently-authorized documents concurrently.
The document handle#
open() resolves to a DocumentHandle — your entry point to everything about
one open document:
interface DocumentHandle {
readonly id: string;
readonly capabilities: DocumentCapabilities;
readonly security: DocumentSecurityService;
readonly metadata: MetadataService;
readonly annotations: DocumentAnnotationsService;
readonly pages: DocumentPagesService;
readonly render: DocumentRenderService;
page(pageObjectNumber: PageObjectNumber): PageHandle;
download(opts?: { mode?: PdfSaveMode }): AbortablePromise<Uint8Array>;
close(): AbortablePromise<void>;
}metadata,annotations,pages, andsecurityare document-scoped services (covered in their own pages).rendercarries the document’s render policy — not pixels; per-page rendering stays onpage(pon).render. See Render policy.page(pon)returns a page handle (below).download()returns the full PDF bytes — see Downloading.close()releases the handle. It’s idempotent and safe to call more than once.
Capabilities#
capabilities advertises engine-specific behavior so portable code can adapt:
interface DocumentCapabilities {
readonly weakAnnotationEditSessions: 'not-needed' | 'required';
readonly pageEditSessions: 'unsupported' | 'supported';
}On the cloud engine, weakAnnotationEditSessions is 'required' (index-based
annotation edits need an active edit session) and pageEditSessions is
'unsupported'.
The page handle#
doc.page(pon) returns a PageHandle keyed on the page’s indirect object
number, never its display index — so the handle stays valid across page
reorders.
interface PageHandle {
readonly pageObjectNumber: PageObjectNumber;
readonly pageIndex: number; // advisory display index at mint time
readonly annotations: PageAnnotationsService;
readonly text: PageTextService;
readonly geometry: PageGeometryService;
readonly render: PageRenderService;
}page() is synchronous — page records are already known to the handle. To
discover page object numbers, call doc.pages.list():
const { pageCount, pages } = await doc.pages.list();
const firstPon = pages[0].pageObjectNumber;
const page = doc.page(firstPon);Treat pageIndex as advisory metadata. It reflects display order
at the time the handle was minted; the durable key is always
pageObjectNumber.
Lifecycle at a glance#
const engine = localEngine();
const doc = await engine.open({ kind: 'bytes', id: 'doc_123', bytes }); // open
const page = doc.page((await doc.pages.list()).pages[0].pageObjectNumber); // work
await page.render.image();
await doc.close(); // release the document
await engine.destroy(); // tear down the engineYour feedback goes directly to the documentation team.