CloudPDF
DocsPricing
Start building

Opening documents

engine.open() gives you a handle to one document. Everything you do with the document starts from that handle.

const doc = await engine.open({ kind: 'token', token: () => fetchDocumentToken('contract') });

Open a document#

The document is already on your server, so you open it by reference. There are three ways, depending on where the credential comes from:

InputWhen to use it
{ kind: 'token', token }Your backend created a token for this user and this document.
{ kind: 'id', id }Your app has a token for your whole account (admin tools, jobs).
{ kind: 'share', shareToken }A public share link from the CloudPDF dashboard.

Authentication shows how to create tokens and when to use each.

open() fetches the document’s details from the server, never the file itself. Pages, text and images arrive as you ask for them.

Password-protected files#

A PDF can have its own password. When you know it, pass it when you open:

const doc = await engine.open(input, { password: 'secret' });

When you don’t, open without one and ask the user only if the file needs it. doc.security.passwordPrompt tells you:

const doc = await engine.open(input);
 
if (doc.security.passwordPrompt.state === 'required') {
  const password = await askUserForPassword();
  await doc.security.unlock({ password });
}
passwordPrompt.stateWhat it means
'none'Nothing to do: the file has no password, or it’s already fully unlocked.
'required'The file can’t be read without its password. Ask before you do anything else.
'optional'The file is open, but its owner password would give more rights. You may offer it.

passwordPrompt.hint says which password to ask for ('user' or 'owner'), when the engine knows. When the state is 'required', passwordPrompt.incorrect is true if the last password you tried was wrong.

A locked document still opens: without a password, open() succeeds, and every call that reads the file fails with DocPasswordRequired until you unlock it. A wrong password doesn’t fail open() either: the document opens locked, and passwordPrompt.incorrect is true, so you can say “that password is wrong” and ask again.

unlock() fails with DocPasswordIncorrect when the password is wrong, so you can ask again:

import { EngineError, EngineErrorCode } from '@cloudpdf/engine';
 
while (doc.security.passwordPrompt.state === 'required') {
  try {
    await doc.security.unlock({ password: await askUserForPassword() });
  } catch (error) {
    if (!EngineError.is(error, EngineErrorCode.DocPasswordIncorrect)) throw error;
    showMessage('That password is wrong. Try again.');
  }
}

Owner password#

A PDF can have two passwords. The user password opens it; the owner password also lifts the file’s own restrictions, such as “no printing” or “no copying”. When a file is open but not with its owner password, passwordPrompt is 'optional'.

To accept only the owner password, pass mode: 'owner'. The user password then fails with DocPasswordIncorrect:

await doc.security.unlock({ password, mode: 'owner' });

The file’s own restrictions only count when the user’s permissions include pdf.permissions; see Permissions.

On the cloud, who the user is and what they may do come from their token, so open() has no options for them. See What a token carries.

Close a document#

Close a document when you’re done with it:

await doc.close();

Closing stops the live updates for this document and forgets what the engine cached. The document itself stays on the server. After it, calls on doc fail with DocNotOpen. Closing twice is fine.

One engine, many documents#

Create one engine for your app and open every document on it:

const [contract, invoice] = await Promise.all([
  engine.open(contractInput),
  engine.open(invoiceInput),
]);

Keep the engine for as long as your app runs. When you do want to shut it down, at the end of a script for example, destroy it; that also closes every document still open on it:

await engine.destroy();

Each document keeps the token it was opened with, so one engine can hold documents opened for different users or with different permissions.

Good to know#

Cancelling an open#

open() returns a promise you can cancel, like every call:

const opening = engine.open(input);
cancelButton.onclick = () => opening.abort();

See Errors & cancelling.