> For the complete documentation index, see [llms.txt](https://docs.apryse.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.apryse.com/web/full-api/setup.md).

# Get started with Full API

Unlock PDF viewing, parsing, and editing with the Full API. Learn to set up a basic project to count pages in a PDF document. No document conversion needed. Get started now! The Apryse Web SDK streaml

The full API is a complete browser side PDF SDK, unlocking viewing, parsing and editing of PDF files. This guide will demonstrate how to set up a basic full API project that outputs the number of pages in a PDF document.

The full API does not require any conversion of documents but can only view PDF documents.

## Initial setup

This guide will require the following files:

1. The WebViewer folder.
2. An empty HTML document.
3. An empty JavaScript document.
4. A PDF document of your choice. For this guide we will be using the [newsletter](https://sdk.apryse.com/samples/web/samples/full-apis/TestFiles/newsletter.pdf) PDF document.
5. An image to add to the PDF document. For this guide we will be using an [image of a butterfly](https://sdk.apryse.com/samples/web/samples/full-apis/TestFiles/butterfly.png).

![](https://3532544125-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FX9YnTSKIHvV7m0A36LbO%2Fuploads%2Fgit-blob-cac6eb92f82e1f4886074fc0c7da499fe15ff710%2Fa8b9c0de4dd7a2ba9237bc37dcb8603808fa822d-141x87.png?alt=media)

## Setting up the HTML file

Open up index.html with a text editor and copy/paste the following code into the HTML document.

{% tabs %}
{% tab title="HTML" %}
{% code lineNumbers="true" %}

```html
<!DOCTYPE html>
<html style="height:100%;">
  <head>
    <meta http-equiv="Content-Type" content="text/html">
    <script src="WebViewer/lib/webviewer.min.js"></script>
  </head>
  <body style="width:100%; height:100%; margin:0px; padding:0px; overflow:hidden">
    <div id="viewer" style="height: 100%; overflow: hidden;"></div>
    <script src="index.js"></script>
  </body>
</html>
```

{% endcode %}
{% endtab %}
{% endtabs %}

Here we include the required WebViewer file and start out with a single "viewer" div that we will add content to using a script.

## Setting up your JavaScript document

In our custom script `index.js`, the `WebViewer` function is called to create a new WebViewer instance that will be added as a child to our "viewer" div.

<pre class="language-js" data-line-numbers><code class="lang-js">WebViewer({
  path: "WebViewer/lib",
  initialDoc: "WebViewer/samples/full-apis/TestFiles/newsletter.pdf",
  showLocalFilePicker: true,
  fullAPI: true,
  licenseKey: '<code class="expression">visitor.claims.wvKey || "YOUR_LICENSE_KEY"</code>',
}, document.getElementById('viewer'))
  .then(instance => {
    // WebViewer instance is ready
  });
</code></pre>

Overview of WebViewer initialization parameters:

* `path` - String representing the URL that points to the WebViewer libraries.
* `initialDoc` - String representing the URL of the document that will be loaded in WebViewer.
* `showLocalFilePicker` - Boolean that determines whether we can open local documents in the viewer.
* `fullAPI` - If true, allows the Full API to be used and `PDFNet` will be available on the instance.
* `licenseKey` - String containing the license key (you do not need to set this property if you are just trialing)

If you open index.html from a server, you should be able to see your document displayed in WebViewer.

![](https://3532544125-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FX9YnTSKIHvV7m0A36LbO%2Fuploads%2Fgit-blob-5522a5b37bb532fc89ddff3af5cc294d19702245%2F62a657fe0e471db19b8e4ec0cbb1cd6369a3601e-356x178.png?alt=media)

Now that we have our pdf displayed, let's use the full API to manipulate the document.

{% tabs %}
{% tab title="JavaScript (SDK v8.0+)" %}
{% code lineNumbers="true" %}

```js
WebViewer({
  // ...
}, document.getElementById('viewer'))
  .then(instance => {
    const { documentViewer, PDFNet } = instance.Core;

    documentViewer.addEventListener('documentLoaded', async () => {
      await PDFNet.initialize();
      const doc = documentViewer.getDocument();
      const pdfDoc = await doc.getPDFDoc();

      // Ensure that we have our first page.
      await pdfDoc.requirePage(1);

      // Run our main function using 'runWithCleanup'
      await PDFNet.runWithCleanup(async () => await main(pdfDoc));

      // Refresh the cache with the newly updated document
      documentViewer.refreshAll();
      // Update viewer with new document
      documentViewer.updateView();
    });

    async function main(pdfDoc) {
      alert("Hello WebViewer!");
    }
  });
```

{% endcode %}

[DocumentViewer.getDocument](https://sdk.apryse.com/api/web/Core.DocumentViewer.html#getDocument__anchor) [Document.getPDFDoc](https://sdk.apryse.com/api/web/Core.Document.html#getPDFDoc__anchor) [Document.refreshAll](https://sdk.apryse.com/api/web/Core.DocumentViewer.html#refreshAll__anchor) [Document.updateView](https://sdk.apryse.com/api/web/Core.DocumentViewer.html#updateView__anchor) [PDFDoc.requirePage](https://sdk.apryse.com/api/web/Core.PDFNet.PDFDoc.html#requirePage__anchor) [PDFNet.runWithCleanup](https://sdk.apryse.com/api/web/Core.PDFNet.html#.runWithCleanup__anchor)
{% endtab %}

{% tab title="JavaScript (SDK v6.0+)" %}
{% code lineNumbers="true" %}

```js
WebViewer({
  // ...
}, document.getElementById('viewer'))
  .then(instance => {
    const { docViewer, PDFNet } = instance;

    docViewer.on('documentLoaded', async () => {
      await PDFNet.initialize();
      const doc = docViewer.getDocument();
      const pdfDoc = await doc.getPDFDoc();

      // Ensure that we have our first page.
      await pdfDoc.requirePage(1);

      // Run our main function using 'runWithCleanup'
      await PDFNet.runWithCleanup(async () => await main(pdfDoc));

      // Refresh the cache with the newly updated document
      docViewer.refreshAll();
      // Update viewer with new document
      docViewer.updateView();
    });

    async function main(pdfDoc) {
      alert("Hello WebViewer!");
    }
  });
```

{% endcode %}

[DocumentViewer.getDocument](https://sdk.apryse.com/api/web/Core.DocumentViewer.html#getDocument__anchor) [Document.getPDFDoc](https://sdk.apryse.com/api/web/Core.Document.html#getPDFDoc__anchor) [Document.refreshAll](https://sdk.apryse.com/api/web/Core.DocumentViewer.html#refreshAll__anchor) [Document.updateView](https://sdk.apryse.com/api/web/Core.DocumentViewer.html#updateView__anchor) [PDFDoc.requirePage](https://sdk.apryse.com/api/web/Core.PDFNet.PDFDoc.html#requirePage__anchor) [PDFNet.runWithCleanup](https://sdk.apryse.com/api/web/Core.PDFNet.html#.runWithCleanup__anchor)
{% endtab %}
{% endtabs %}

{% hint style="info" %}
In order to run this on browsers without ES7 support, you can convert the file to ES5 using ES7-to-ES5 transformers such as [Babel](https://babeljs.io/).
{% endhint %}

If you run the project again in a server, you should be able to see "Hello WebViewer" pop up in an alert box once WebViewer has loaded. Before the custom code is run however, several checks and initializations need to be done first.

* `PDFNet.initialize()` - Initializes Full API backend. This should be called before any Full API functions are called.
* `doc.getPDFDoc()` - Extracts the PDFNet PDFDoc object from the WebViewer document.
* `pdfDoc.requirePage()` - Ensures that a particular page of the pdf document is finished downloading before we read or write from it.
  * If the page(s) to be edited cannot be known until the custom script runs, `requirePage()` can be called instead in the middle of the custom code, but only by unlocking and relocking all operations.
  * An example of this can be seen in the html file of the Viewer Edit test on the [samples page](/web/get-started/guides/samples/full-apis.md).

## Writing your custom code

Let us change our `main()` code to do something more interesting:

{% tabs %}
{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
async function main(pdfDoc) {
  pdfDoc.initSecurityHandler();
  pdfDoc.lock();
  const inputPath = "../../samples/full-apis/TestFiles/";
  const firstPage =  await pdfDoc.getPage(1);
  // create a new page builder that allows us to create new page elements
  const builder = await PDFNet.ElementBuilder.create();
  // create a new page writer that allows us to add/change page elements
  const writer = await PDFNet.ElementWriter.create();
  writer.beginOnPage(firstPage, PDFNet.ElementWriter.WriteMode.e_overlay);

  // Adding a JPEG image to output file
  const img = await PDFNet.Image.createFromURL(pdfDoc, inputPath + "butterfly.png");

  const imgWidth = await img.getImageWidth();
  const imgHeight = await img.getImageHeight();
  const element = await builder.createImageScaled(img, 100, 600, imgWidth, imgHeight);
  writer.writePlacedElement(element);
  writer.end();
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

[PDFDoc.initSecurityHandler](https://sdk.apryse.com/api/web/Core.PDFNet.PDFDoc.html#initSecurityHandler__anchor) [PDFDoc.lock](https://sdk.apryse.com/api/web/Core.PDFNet.PDFDoc.html#lock__anchor) [PDFDoc.getPage](https://sdk.apryse.com/api/web/Core.PDFNet.PDFDoc.html#getPage__anchor) [ElementBuilder.create](https://sdk.apryse.com/api/web/Core.PDFNet.ElementBuilder.html#.create__anchor) [ElementWriter.createImageScaled](https://sdk.apryse.com/api/web/Core.PDFNet.ElementBuilder.html#createImageScaled__anchor) [ElementWriter.beginOnPage](https://sdk.apryse.com/api/web/Core.PDFNet.ElementWriter.html#beginOnPage__anchor) [ElementWriter.writePlacedElement](https://sdk.apryse.com/api/web/Core.PDFNet.ElementWriter.html#writePlacedElement__anchor) [ElementWriter.end](https://sdk.apryse.com/api/web/Core.PDFNet.ElementWriter.html#end__anchor) [Image.createFromURL](https://sdk.apryse.com/api/web/Core.PDFNet.Image.html#.createFromURL__anchor) [Image.getImageWidth](https://sdk.apryse.com/api/web/Core.PDFNet.Image.html#getImageWidth__anchor) [Image.getImageHeight](https://sdk.apryse.com/api/web/Core.PDFNet.Image.html#getImageHeight__anchor)

This code sample adds the "butterfly.png" image to location (x:100, y:600) relative to the lower left corner of the document's first page.

Once our custom code has finished running, two final functions `docViewer.refreshAll()` and `docViewer.updateView()` are called to refresh and update the WebViewer display.

The resulting viewer should look like this:

![](https://3532544125-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FX9YnTSKIHvV7m0A36LbO%2Fuploads%2Fgit-blob-b909f48a346610cc2763eb6a85a68296a37ed392%2F9fd58abfe4899f8251b2b43cc6057fed80d11266-323x215.png?alt=media)

## Converting async/await code (important for IE usage)

This guide and all other Full API guides use ES7 async/await functions in JavaScript which are currently supported in Chrome, Firefox, Edge, Safari, and Opera but may be unsupported in other browsers. If you are working with a browser without async/await support, you will have to transpile the code from ES7 to ES5 using something like [Babel](https://babeljs.io/).

## Full API samples

The best way to get started with writing your own full API code is to run the full API samples. You can find working samples and their source code on the [Full API samples page](/web/get-started/guides/samples/full-apis.md).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.apryse.com/web/full-api/setup.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
