> ## Documentation Index
> Fetch the complete documentation index at: https://paperlinkai.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Install with a script tag

> Add the Paperlink AI widget to any page with one script tag.

The script tag is the only way to install the widget. You paste one line of HTML and the widget appears on your page, or you start the widget from your own code.

## Add the widget

**1. Get an API key**

Open the dashboard and select Settings. Find the API keys & embed card and select Create key. Copy the key when the dashboard shows it. The dashboard shows the full key only once.

**2. Paste the tag**

Paste the tag before the closing `</body>` tag of your page. You can also put it in `<head>` if you keep the `async` attribute. Replace `YOUR_API_KEY` with your key.

```html Paste before </body> theme={"dark"}
<script src="https://api.paperlinkai.com/widget.js" data-api-key="YOUR_API_KEY" async></script>
```

**3. Add your site to allowed origins**

In Settings, open the Widget card. Add your site to Allowed origins and select Save widget settings.

**4. Load your site**

Open your site in a browser. The widget launcher appears on the page.

> [!NOTE]
>
> Keys you create in the dashboard start with `pl_live_`. The key is meant to be public: it sits in your page's HTML. Allowed origins, Turnstile and rate limits are what protect it.

## Attributes

The tag reads these attributes from the script element.

| Attribute | Required | Description |
| - | - | - |
| `data-api-key` | For the standard install | Your API key. Without this attribute, the tag starts no widget. See [Start the widget from your code](#start-the-widget-from-your-code). |
| `data-api-base-url` | No | The API base URL. The default is the URL of the script without `/widget.js`. |
| `data-turnstile-site-key` | No | Overrides the Turnstile site key that the bot configuration provides. |
| `data-open` | No | Set to `"true"` to open the widget when the page loads. |

With the tag before `</body>`, the widget starts at once. If the tag is in `<head>`, the widget waits for `DOMContentLoaded` before it starts. If a page has a second tag, the second tag does nothing.

## Start the widget from your code

Start the widget from your code when you need options that the tag attributes do not have. Examples are inline mode, `onAnalyticsEvent` and `historyLimit`.

**1. Load the script without data-api-key**

Without `data-api-key`, the script starts no widget. It adds `window.PaperlinkAIChat` and `window.PaperlinkAIChatQueue` to the page.

```html theme={"dark"}
<script src="https://api.paperlinkai.com/widget.js" async></script>
```

**2. Call init when the script is ready**

Push a function onto `window.PaperlinkAIChatQueue`. The script calls the function with `PaperlinkAIChat` when it is ready. This example puts the widget inside a page element.

```html theme={"dark"}
<div id="support-chat" style="height: 560px"></div>

<script>
  window.PaperlinkAIChatQueue = window.PaperlinkAIChatQueue || [];
  window.PaperlinkAIChatQueue.push(function (PaperlinkAIChat) {
    PaperlinkAIChat.init({
      apiKey: 'YOUR_API_KEY',
      mode: 'inline',
      container: document.getElementById('support-chat'),
    });
  });
</script>
```

`init` uses the same default API base URL as the tag: `data-api-base-url`, or else the URL of the script without `/widget.js`. For all options, see [Attributes and init options](https://paperlinkai.com/docs/developers/configure/attributes-and-options.md).

## Run code when the script is ready

The script loads with `async`, so your code can run before `window.PaperlinkAIChat` exists. Use one of these two signals.

* **The queue.** Functions that you push onto `window.PaperlinkAIChatQueue` before the script loads run when it is ready. Functions that you push after that run at once. Use the queue in most cases, because it works in both orders.
* **The `paperlinkai:ready` event.** The script fires this event on `window` one time, when it is ready. `event.detail.PaperlinkAIChat` holds the API. Add your listener before the script loads, or the listener misses the event.

If one of your functions throws an error, the script logs the error to the browser console and runs the next function.

## What the tag exposes

The tag adds these properties to `window`.

* `window.PaperlinkAIChat` has the `init` method. See [JavaScript API](https://paperlinkai.com/docs/developers/configure/javascript-api.md).
* `window.PaperlinkAIChatInstance` is the widget instance that the tag creates. It exists only when the tag has `data-api-key`.
* `window.PaperlinkAIChatQueue` runs your functions when the script is ready.

## TypeScript types

The API serves a type declaration file next to the script. It declares the `window` properties above and the `paperlinkai:ready` event. It also declares the `PaperlinkAI` namespace with `InitOptions`, `ChatInstance` and `WidgetAnalyticsEvent`.

**1. Download the file**

Save the file in your project, for example as `types/paperlinkai-widget.d.ts`.

```bash theme={"dark"}
curl -o types/paperlinkai-widget.d.ts https://api.paperlinkai.com/widget.d.ts
```

**2. Include the file**

Make sure that the `include` setting of your `tsconfig.json` contains the file. The file has no imports or exports, so its types are global.

The file always matches the current script. To get new options, download it again.

> **Short declarations to paste**
>
> If you do not want to download a file, paste this block into a `.d.ts` file of your project. It declares only the parts that most pages use.
>
> ```ts types/paperlinkai-widget.d.ts theme={"dark"}
> export {};
>
> declare global {
>   namespace PaperlinkAI {
>     interface ChatInstance {
>       open(): void;
>       close(): void;
>       resetSession(): void;
>       destroy(): void;
>     }
>     interface InitOptions {
>       apiKey: string;
>       apiBaseUrl?: string;
>       mode?: 'floating' | 'inline';
>       container?: HTMLElement;
>       defaultOpen?: boolean;
>       historyLimit?: number;
>       onAnalyticsEvent?: (event: { name: string; [field: string]: unknown }) => void;
>     }
>     interface PaperlinkAIChatApi {
>       init(options: InitOptions): ChatInstance;
>     }
>     interface ReadyQueue {
>       push(...callbacks: Array<(api: PaperlinkAIChatApi) => void>): number;
>     }
>   }
>   interface Window {
>     PaperlinkAIChat?: PaperlinkAI.PaperlinkAIChatApi;
>     PaperlinkAIChatInstance?: PaperlinkAI.ChatInstance;
>     PaperlinkAIChatQueue?: PaperlinkAI.ReadyQueue;
>   }
> }
> ```

> [!NOTE]
>
> The script has no version number in its address. It always matches the API that Paperlink AI runs, so you never update the tag.

> **[Attributes and options](https://paperlinkai.com/docs/developers/configure/attributes-and-options.md)**
>
> See every attribute and option in one place.

> **[React, Next.js, Vue and others](https://paperlinkai.com/docs/developers/install/frameworks.md)**
>
> Start the widget in a framework component.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.