# Oniroco documentation

Welcome to Oniroco's developer docs, where you can learn more about Oniroco's API, SDK and developer tooling. You can use Oniroco's SDK to embed our projects into your apps and websites.

{% hint style="info" %}
Stay up to date with the [latest updates in Oniroco documentation](/whats-new-in-the-oniroco-docs).
{% endhint %}

## Get started

<table data-view="cards"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Chathive SDK</strong></td><td>Start with embedding a Oniroco project into your projects</td><td></td><td></td></tr><tr><td><strong>API documentation</strong></td><td>Learn how to work with the Oniroco API</td><td></td><td><a href="https://documenter.getpostman.com/view/21518222/2s9YC31uAP">https://documenter.getpostman.com/view/21518222/2s9YC31uAP</a></td></tr><tr><td><strong>Crawler configuration</strong></td><td>Learn how to create advanced crawlers</td><td></td><td><a href="/pages/npD5rZxQDvoT2rmcXmbI">/pages/npD5rZxQDvoT2rmcXmbI</a></td></tr><tr><td><strong>Tools</strong></td><td>Enhance enhance your AI with custom tools</td><td></td><td><a href="/pages/gbJuIzVnTXVdcTBeOStc">/pages/gbJuIzVnTXVdcTBeOStc</a></td></tr><tr><td>Triggers</td><td>Trigger your agent when changes happen in your apps<br></td><td></td><td><a href="/pages/iNY8EOGQQJJGiaZUItGq">/pages/iNY8EOGQQJJGiaZUItGq</a></td></tr></tbody></table>


# What's new in the Oniroco docs?

The most recent updates includes file upload to both Chatbot and AI form.

## January 2026

* [Tool timeouts](/tools/overview#timeout)
* [Tool response body limit](/tools/overview#response-size)

## September 2025

* Fetch private projects through API
* Configure conversation timezone
* [Agent triggers api](/triggers/api-trigger)
* [Custom SDK events](/sdk/custom-tool-events)

## June 2025

* Allow file upload in the chatbot or AI form
* Layout changes to accommodate the file upload changes
* Crawler config changes
  * New config
    * **followRedirect** let's the crawler follow a redirected url and not see it as deleted
  * Updated config
    * **pathsToMatch** has been changed to a array to allow for more simpler regex patterns
    * **pathsToExclude** has been changed to a array to allow for more simpler regex patterns
  * Crawler will now log any errors with incorrectly configured  **pathsToMatch** or **pathsToExclude** regex patterns
* [Analytics REST API](/api/rest-api#analytics-endpoints)
  * Get conversation statistics&#x20;

## May 2025

* [Crawler login playbook](/crawler/crawler-config/login#playbook)
* Extended [Tools template variabels](/tools/overview#template-variabels) with conversation object

## April 2025

* Manage tags through the API

## February 2025

* [Oniroco tools](/tools/overview)
* **Link** field add to customer&#x20;

## November 2024

* [Crawler overview page](/crawler/overview)
  * Fixed user agent
  * List with approved IP addresses
* Crawler can now crawl documents
  * Excel
  * Microsoft Word, Google Docs and LibreOffice
  * PDF
  * Powerpoint
  * Text, Markdown, richText
* Crawler config has been expended
  * &#x20;documentsToExclude
  * documentsToInclude

## October 2024

* [Sessions REST API](/api/rest-api#session-endpoints)
* AI form SDK [static methods](/sdk/ai-form/methods#static-methods)

## September 2024

* Updated Oniroco's developer documentation
* [AI form SDK](/sdk/ai-form)

## August 2024

* [Crawler config](/crawler/crawler-config) added

## April 2024

* [Embed widget](/sdk/chatbot#embed-in-your-page) into your app
* Open widget on init
* Provide [customer data](/sdk/attributes#customer-data) to the SDK to identify you customers&#x20;
* Provide [context](/sdk/chatbot/methods#context) to the SDK to give the agent where information about the current customer

## March 2024

* New mobile design, Widget is now fullscreen when opened
* Add new SDK methods to [enable or disable notifications](/sdk/chatbot/methods#notifications)


# REST API

{% embed url="<https://documenter.getpostman.com/view/21518222/2s9YC31uAP>" %}

## Analytics endpoints

Get analytics from your Oniroco organisations

{% embed url="<https://documenter.getpostman.com/view/21518222/2s9YC31uAP#ae702bcb-b9e5-4469-8dc7-cef00e504fc5>" %}

## Chat endpoints

Build custom solutions on top of our API when the [SDK](/sdk/getting-started) doesn’t quite hit the mark.&#x20;

{% hint style="info" %}
The chat endpoint uses the public API key that can be found under\
***project > Implementation***
{% endhint %}

{% embed url="<https://documenter.getpostman.com/view/21518222/2s9YC31uAP#8ac66b55-307a-4312-a95c-f8aebebfdc4d>" %}

## Document endpoints

Push and edit your data to your Oniroco organisation with ease

{% embed url="<https://documenter.getpostman.com/view/21518222/2s9YC31uAP#1066c1df-8169-4533-b896-bbbd09ea3203>" %}

## Session endpoints

Get and update AI form sessions

{% embed url="<https://documenter.getpostman.com/view/21518222/2s9YC31uAP#24f86077-7849-4687-88b4-47a460bc6964>" %}

## Tag endpoints

Get, create, update and delete tags&#x20;

{% embed url="<https://documenter.getpostman.com/view/21518222/2s9YC31uAP#f06aef04-54e1-41f5-aef6-af6d8b1aa9da>" %}


# Overview

The Oniroco crawler retrieves content from your website, internal knowledge bases, or other online documentation and processes it for your AI assistant. By providing a list of start URLs or a sitemap, the crawler will:

1. Visit each specified page.
2. Identify and follow additional links within your defined URL range.
3. Remove irrelevant data to focus on essential content.
4. Save or update your data in the knowledge base.

The crawler is included in all [pricing plans](https://chathive.co/pricing) although advanced configuration options are only available in higher-tier plans.

### Verify Oniroco crawler

To verify that a web crawler accessing your servers is genuinely the Oniroco crawler, you can check its user agent or IP address agains our [list of IP addresses](https://chathive.app/ipranges/crawler.json).

#### User agent

By default, we use the following user agent `OnirocoCrawler/1.0`. However if you have specific requirements, you can customise the user agent that will be used by the crawler.

[<br>](https://www.algolia.com/doc/tools/crawler/getting-started/create-crawler/)


# Crawler config

### Parameters

<table data-header-hidden><thead><tr><th width="224"></th><th></th></tr></thead><tbody><tr><td>schedule<br><br><br><br><br><br><br></td><td><p>How often a complete crawl should be performed.</p><ul><li>once</li><li>monthly <code>growth</code></li><li>weekly <code>advanced</code></li><li>workDays <code>professional</code></li><li>daily <code>professional</code></li></ul></td></tr><tr><td>executeAt<br></td><td>At which time the crawler should be executed. Formatted <code>hh:mm</code><br>Example: <code>executeAt: 18:30</code></td></tr><tr><td>startUrls<br></td><td>Array of URLs the crawler uses as entry points.<br>Example:<code>startUrls: ["https://example.com"]</code></td></tr><tr><td>sitemaps<br><br></td><td>Array of URLs pointing to a sitemap. URLs found in these sitemaps will be used as entry points.<br>Example: <code>sitemaps: ["https://example.com/sitemap.xml"]</code></td></tr><tr><td>ignoreQueryParams<br><br></td><td>Filters out specified query parameters from crawled URLs. This can help you avoid indexing duplicate URLs. <br>Example: <code>ignoreQueryParams: ["key", "q"]</code></td></tr><tr><td>ignoreAllQueryParams<br></td><td>Filters out all query parameters from crawled URLs, defaults to true.<br>Example:<code>ignoreAllQueryParams: true</code></td></tr><tr><td>extractUrls<br><br></td><td>Crawlers will extract urls from crawled data and continue to crawl these urls. Only urls that match with any of the start urls will be extracted. default to true. <br>Example: <code>extractUrls: true</code></td></tr><tr><td>concurrency<br><br></td><td>Number of concurrent tasks the crawler can run. Running multiple concurrent tasks may let your server throw 429 error. Excepts a value between 1 and 5, default to 1. <br>Example:<code>concurrency: 1</code></td></tr><tr><td><p>ignoreNoFollowTo</p><p><br></p></td><td>Whether the Crawler should follow links with the <code>rel=”nofollow”</code>defaults to true.<br>Example:<code>ignoreNoFollowTo: true</code></td></tr><tr><td>followRedirect</td><td>Wether the crawler should follow a redirect url or not.<br>If redirect is disabled the current url will be seen as deleted<br><code>followRedirect</code> default to true<br>Example:<code>followRedirect: true</code></td></tr><tr><td>maxDepth<br><br><br><br><br><br><br></td><td><p>Limits how deep we can crawl into the website. <code>maxDepth: 1</code><br>For example, you have a max depth of three:</p><ul><li>http://example.com <strong>depth = 1 ✅</strong></li><li>http://example.com/products <strong>depth = 2 ✅</strong></li><li>http://example.com/products/category <strong>depth = 3 ✅</strong></li><li>http://example.com/products/category/detail <strong>depth = 1 ❌</strong></li></ul></td></tr><tr><td>maxRetries<br></td><td><p>How many times the crawler should retry a failed url. Excepts a value between 0 and 8, default to 5.</p><p>Example: <code>maxRetries: 5</code></p></td></tr><tr><td>maxUrls<br><br></td><td><p>Limits the number  of urls the crawler will process, also applies to the startUrls. Excepts a value greater or equal to 1</p><p>Example: <code>maxUrls: 1</code> </p></td></tr><tr><td><p>characterLimit</p><p><br><br></p></td><td><p>Limits the number of characters the crawler can use. Can be helpful to keep your costs under control. Excepts a value greater then 500</p><p>Example: <code>characterLimit: 10000</code></p></td></tr><tr><td>delay<br><br><br><br><br><br></td><td><p>Time, in milliseconds, the crawler waits before crawling the next URL. This can help to avoid 429 errors.</p><ul><li>Value between 0 or 30 000 <code>delay: 4000</code></li><li>Range <code>delay: {min: 500, max: 30000}</code></li></ul><p>Range will randomly generate a delay between your set range on each new crawl.</p></td></tr><tr><td>timeout<br><br><br><br></td><td><p>Time, in milliseconds, the crawler waits to get a response from each URL. When the timeout period expires, document will be marked as failed.<br>Accepts a value between 0 and 30 000, default to 30 000.</p><p>Example: <code>timeout: 30000</code></p></td></tr><tr><td><p>renderJavaScript</p><p><br><br></p></td><td><p>When enabled all web pages are rendered with a chrome headless browser. This is slower but crawls pages in the most realistic form.<br>Defaults to true</p><p>Example: <code>renderJavaScript: true</code></p></td></tr><tr><td>pathsToMatch<br><br></td><td><p>Only urls that match with <strong>one</strong> of  the regex pattern defined in the array will be crawled.  <em>Urls must also match with any of your startUrls</em></p><p>Example: <code>pathsToMatch: ["/products\/*/i"]</code> </p><p><em>the regex must be enclosed in a string</em> and can contain flags</p></td></tr><tr><td>pathsToExclude<br></td><td><p>Urls that match with <strong>one</strong> of  the regex pattern defined in the array  will not be crawled. </p><p>Example: <code>pathsToExclude: ["/products\/*/i"]</code><br><em>the regex must be enclosed in a string</em> and can contain flags</p></td></tr><tr><td><p>documentsToInclude</p><p></p><p></p><p><br><br></p></td><td><p>Documents will only be crawled if it's extension, content-type, mime-type or <a href="/pages/BB9lzWwYSrMsIQvbv00r#document-types">document type</a> is included in the list.</p><p>If provide a empty array all documents will be ignored<br></p><p>Example: <code>documentsToInclude: ["word", "text/plain", "csv"]</code></p></td></tr><tr><td><p>documentsToExclude</p><p><br><br></p></td><td>Documents will only be crawled if it's extension, content-type, mime-type or <a href="/pages/BB9lzWwYSrMsIQvbv00r#document-types">document type</a> is <strong>not</strong> included in the list. <br>Example: <code>documentsToExclude: ["word", "text/plain", "csv"]</code></td></tr><tr><td><p>htmlParser</p><p><br><br><br><br><br><br><br></p></td><td><p>Define how the html of your webpage should be parsed. The parsing process might impact the performance of your agent.</p><p>Default to smart. <br>Example: <code>htmlParser: smart</code></p><p>Parser types:</p><ul><li><code>plain</code>: dumb html parser</li><li><code>smart</code>: Perserve document structure which can be important for context</li></ul></td></tr><tr><td><p>headers</p><p><br><br><br></p></td><td>HTTP headers that will be added to every request your crawler makes.<br>Example:  <code>headers: { "authentication": "JWT token" }</code><br><br><em>Only available for <code>renderJavaScript: true</code></em></td></tr><tr><td>userAgent<br><br><br></td><td><p>Customize the userAgent for the crawler. </p><p>Example: <code>userAgent: OnirocoCrawler/1.0</code></p><p><br><em>Only available for <code>renderJavaScript: true</code></em></p></td></tr><tr><td><p>languages<br></p><p><br><br><br><br><br><br></p></td><td><p>Crawl only webpages that match your configured languages.</p><ul><li><strong>Languages</strong>: Array of languages <code>ISO6391</code> codes</li><li><strong>Strict</strong>: <br>if false documents that don't have a language will be crawled<br>if true only documents that have a language that matches your list will be crawled</li></ul><p>Example: <code>languages: {languages: ["nl", "en"],strict: false}</code></p></td></tr><tr><td>restoreDeletedPages<br><br><br></td><td><p>Defines if the crawler must restore a document that has been crawled previously but has been deleted in Oniroco.</p><p>default to false.</p><p>Example: <code>restoreDeletedPages: false</code></p></td></tr><tr><td>acceptCookieConsent<br><br><br><br></td><td><p>Accept cookie consent policy to prevent it from being crawled.<br>Uses html querySelector to accept the cookie policy.</p><p>Example: <code>acceptCookieConsent: { selector: "#buttonId" }</code></p><p><br><em>Only available for <code>renderJavaScript: true</code></em></p></td></tr><tr><td>localStorage<br><br><br></td><td><p>Crawler will pre-fill the webpage local storage on crawl. </p><p>Example: <code>localStorage: { "key": "value" }</code></p><p><br><em>Only available for <code>renderJavaScript: true</code></em></p></td></tr><tr><td>sessionStorage<br><br><br></td><td><p>Crawler will pre-fill the webpage session storage on crawl. </p><p>Example: <code>sessionStorage: { "key": "value" }</code></p><p><br><em>Only available for <code>renderJavaScript: true</code></em></p></td></tr><tr><td>cookies<br><br><br><br><br></td><td><p>Crawler will set cookies for the webpage on crawl, can be helpful to crawl behind a login wall.</p><p>Example: <code>cookies: [{ name: "key", value: "value",  domain: "example.com" }]</code></p><p><br><em>Only available for <code>renderJavaScript: true</code></em></p></td></tr><tr><td><p>credentials</p><p><br><br><br><br></p></td><td><p>Provide HTTP authentication credentials to the crawler, can be helpful to crawl behind a login wall.</p><p>Example: <code>credentials: { username: "name", password: "pass" }</code></p><p><br><em>Only available for <code>renderJavaScript: true</code></em></p></td></tr><tr><td><a href="/pages/AMxlOzNEuBCXBFIBbBcJ">login</a><br><br></td><td><p>Configure complex login methods to crawl behind a login wall.</p><p><br><em>Only available for <code>renderJavaScript: true</code></em></p></td></tr><tr><td>projectIds<br><br></td><td><p>Define to which project the crawler must save the crawled documents. Id can be found in the url of your project.</p><p>Example: <code>projectIds: ["66769ce07734ec30a64090e2"]</code></p></td></tr><tr><td>advancedLogs<br><br><br></td><td>Log more steps and actions your crawler did. Is helpful for debugging or beter understanding your crawler but might make the log files harder to navigate.<br>Example: <code>advancedLogs: false</code></td></tr><tr><td><p>dryRun<br></p><p><br></p></td><td><p>In dry run mode crawled documents will not be saved, this setting is purely for debugging/testing your config without wasting resources.</p><p>Example: <code>dryRun: false</code></p></td></tr><tr><td>debug<br><br><br><br></td><td><p>In debug mode the crawler will run as dryRun mode. But it will only crawl 5 documents and log the contents of the documents. Can be helpful to debug your parser or other settings that depend on the document content.</p><p>Example: <code>debug: false</code></p></td></tr></tbody></table>


# Login

This property defines how the crawler can authenticate it self to protected websites. Currently only the playbook is supported our must versatile and flexible authentication option.

## Playbook

In the playbook you define a step by step guide how the authentication needs to be completed.

### Playbook types

#### GOTO

Go to a specific url during authentication or start the authentication at a specific url

#### TYPE

Type in the value into a input field or type in a generated value

* Selector: HTML query selector to select the specific field
* Value: Field value
* Action: Action that must be taken on the value (generate TOTP)

#### CLICK

Click on element on the page to continue example the submit button of a form

* Selector: HTML query selector to select the element that must be clicked

#### WAIT

Wait for a specific event to be completed before continuing to the next step

* waitForSelector: Wait for a specific element to be visible on the page
* waitForNavigation: Wait until crawler has navigated to another page
* waitForTimeout: Wait for a pre set timeout

### Examples

Simple login form without field id's

{% code overflow="wrap" %}

```jsonp
{
 "login": {
    "playbook": [
      // Navigate to the login page
      {
        "type": "goto",
        "url": "https://example.com/login"
      },
      // Type in the required fields
      {
        "type": "type",
        "selector": "input[type='email']",
        "value": "developers@oniroco.app",
      },
      {
        "type": "type",
        "selector": "input[type='password']",
        "value": "Your_password",
      },
      // Submit form
      {
        "type":"click",
        "selector": "input[type='submit']",
      },
      // Wait until form submit is completed
      {
        "type": "wait",
        "action": "waitForNavigation"
      }
    ]
  },
}
```

{% endcode %}

With TOTP token beining asked on a next page

{% code overflow="wrap" %}

```jsonp
{
"login": {
    "playbook": [
      // Navigate to the login page
      {
        "type": "goto",
        "url": "https://example.com/login"
      },
      // Type in the required fields
      {
        "type": "type",
        "selector": "#username",
        "value": "developers@oniroco.app"
      },
      {
        "type": "type",
        "selector": "#password",
        "value": "Your_password"
      },
      {
        "type": "click",
        "selector": "#submitForm"
      },
      // Wait until form is submitted and TOTP field becomes visible
      {
        "type": "wait",
        "action": "waitForSelector",
        "selector": "#totpToken"
      },
      {
        "type": "type",
        "selector": "#totpToken",
        "action": "generateTOTP",
        "totp": {
          "secret": "TOTP_SECRET",
          "algorithm": "SHA-1"
        }
      },
      {
        "type": "click",
        "selector": "button[type=\"submit\"]"
      },
      // Wait until form submit is completed
      {
        "type": "wait",
        "action": "waitForNavigation"
      }
    ]
  }
}
```

{% endcode %}

### Best practices&#x20;

* Always specify a goto url as first step
* Use **wait** step as last to be sure login succeeded and credentials are provided


# Attributes

This page outlines the attributes that can be used to configure your crawler.

## Document types

Use these types to support multiple extensions and content types

<table><thead><tr><th width="135">Type</th><th>Extension</th><th width="434">Content type</th></tr></thead><tbody><tr><td>excel</td><td>xls, xlsx, csv</td><td>application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, text/csv</td></tr><tr><td>html</td><td>html</td><td>text/html</td></tr><tr><td>pdf</td><td>pdf</td><td>application/pdf</td></tr><tr><td>powerPoint</td><td>ppt, pptx</td><td>application/vnd.openxmlformats-officedocument.presentationml.presentation, application/vnd.ms-powerpoint</td></tr><tr><td>richText</td><td>rtf</td><td>text/richtext, text/rtf</td></tr><tr><td>text</td><td>md, txt</td><td>text/markdown, text/plain</td></tr><tr><td>word</td><td>doc, docx</td><td>application/vnd.openxmlformats-officedocument.wordprocessingml.document,  application/msword</td></tr></tbody></table>


# Getting started

The Oniroco JavaScript SDK provides functions that allow you to easily embed Oniroco projects into your apps or websites and manage their behavior.

## 1. Install

To install the SDK on your website, copy and paste the snippet below right before the closing `</head>` tag on every page where you want the SDK and widget to appear.

```html
<script src="https://sdk.chathive.app"></script>
```

{% hint style="info" %}
**Good to know:** If you have a single page app make sure this script is loaded before your try to accessing the SDK
{% endhint %}

## 2. Get your API key

You can find your api key in your dashboard under the `implementation` tab.

## 3. Init your project

Follow the initialization steps for the project type that matches your project.

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><h3>Chatbot project</h3></td><td>Learn how to add a Chatbot project onto your website</td><td></td><td><a href="/pages/0kTCSfbZHE6Bhp4FBzHP">/pages/0kTCSfbZHE6Bhp4FBzHP</a></td></tr><tr><td><h3>AI Form project</h3></td><td>Learn how to embed a AI form into your website or app</td><td></td><td><a href="/pages/OJdrXA2UCzBewslND5xv#installation">/pages/OJdrXA2UCzBewslND5xv#installation</a></td></tr><tr><td><h3>Triggers</h3></td><td>Learn how you can use the SDK to execute a trigger from within your website or app</td><td></td><td></td></tr></tbody></table>


# Chatbot

A chatbot project can be added to your app or website in 2 ways.&#x20;

1. [As a widget](#initialise-as-widget)
2. [Embedded](#embed-in-your-page)

## Initialise as widget

After[ installing the Oniroco SDK](/sdk/getting-started), you’ll need to start up the Widget. Use the code snippet below to make sure the Widget launches every time the page is refreshed.

Place this code in the `</body>` tag on every page where you want to show the widget.

```html
<script>
    Chathive.widget.init({ apiKey: "YOUR_API_KEY" });
</script>
```

{% hint style="info" %}
**Good to know:** If you have a single page app make sure this is executed after the SDK has been loaded&#x20;
{% endhint %}

## Embed in your page

Sometimes a widget doesn't fit into your design. for these purposes we also made it possible to embed the widget into your page.

Once you’ve [installed the Oniroco SDK](/sdk/getting-started), you’ll need to specify which HTML tag should contain the widget. Place the following code just before the `</body>` tag, making sure it comes after the HTML tag where you want to embed the widget."

```html
<script>
    Chathive.widget.embed({
        apiKey: "YOUR_API_KEY",
        selector: "html_tag_selector",
    });
</script>
```

### Example

```markup
<body>
    <div id="embedding"></div>
    <script>
        Chathive.widget.embed({
            apiKey: "YOUR_API_KEY",
            selector: "#embedding",
        });
    </script>
</body>
```

## Limitations

* Currently only 1 chatbot project can be added to your app or website.


# Methods

The Oniroco JavaScript SDK provides an JavaScript object with a few methods. These allow you to interact with the widget and customize it's behaviour

## Widget

### Chathive.widget.init

The primairy use-case of the SDK is to show the Oniroco widget on your website. This can be done by calling the init method. By default we will immediately show the widget trigger on your website if you don't want this you can provide the hide attribute to hide the widget by default.

```typescript
Chathive.widget.init({
    apiKey: "YOUR_API_KEY",
    // Optional attributes
    language: "en",
    hide: false,
    config: { notificationsEnabled: true }
}) 
```

*see more init options in the* [*attributes*](/sdk/chatbot/attributes#widget-init-attributes) *section.*

### Chathive.widget.embed

Instead of showing a widget on your screen, this method will embed your widget into your app.

<pre class="language-typescript"><code class="lang-typescript">Chathive.widget.embed({
    apiKey: "YOUR_API_KEY",
<strong>    selector: "YOUR_HTML_TAG",
</strong>    // Optional attributes
    language: "en",
    hide: false,
}) 
</code></pre>

*see more init options in the* [*attributes*](/sdk/chatbot/attributes#widget-embed-attributes) *section.*

### Chathive.widget.isWidgetLoaded

Check if the widget has been initialised and is ready to be used. This will return a boolean

```typescript
Chathive.widget.isWidgetLoaded();
```

### Chathive.widget.open

This will open the widget, if the widget was hidden it will be shown.

```typescript
Chathive.widget.open();
```

&#x20;If you want to keep the widget hidden, set show attribute to false.&#x20;

```typescript
Chathive.widget.open({ show: false });
```

### Chathive.widget.close

This will close the widget and keep the trigger visible.

```typescript
Chathive.widget.close();
```

If you also want to hide the widget set hide attribute to true.&#x20;

```typescript
Chathive.widget.open({ hide: true });
```

### Chathive.widget.hide

Hide the widget from your website

```typescript
Chathive.widget.hide();
```

### Chathive.widget.isHidden

Check if the widget is hidden. This will return a boolean

```typescript
Chathive.widget.isHidden();
```

### Chathive.widget.show

Show the widget on your website

```typescript
Chathive.widget.show();
```

### Chathive.widget.destroy

Remove the widget from your website.\
f you want to re-enable the widget you need to recall the init method.

```typescript
Chathive.widget.destroy();
```

## Messages

### Chathive.widget.sendMessage

Send a message as the website visitor.

```typescript
Chathive.widget.sendMessage("YOUR MESSAGE");
```

## Language

### Chathive.widget.getCurrentLanguage

Get the current language that is used in the widget. By default we will use the language that is marked as default in your dashboard

```typescript
Chathive.widget.getCurrentLanguage();
```

### Chathive.widget.setLanguage

Set or change the language of the widget. We support all [ISO 639-1 language codes](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes).

```typescript
Chathive.widget.setLanguage("nl");
```

## Text <a href="#text" id="text"></a>

Most static text that you see in the form can be customised

#### getText <a href="#gettext" id="gettext"></a>

Get the text configuration that has been set

```
Chathive.widget.getText();
```

#### setText <a href="#settext" id="settext"></a>

Set or change the text of your interface. *More info about* [*text configuration*](https://developers.chathive.app/sdk/ai-form/configuration#text-customization)

```
Chathive.widget.setText(TextObject);
```

## Settings

### isFileUploadAllowed

Check if file upload has been allowed

```javascript
Chathive.widget.getIsFileUploadAllowed()
```

### setIsFileUploadAllowed

Change if customers are allowed to upload files into the conversation. Will only work if file upload has been enabled in the project.

```javascript
Chathive.widget.setIsFileUploadAllowed(allowed: boolean);
```

## Timezone

Customize the timezone for your conversation. By default, the project's timezone will be used.

### getTimezone

Returns the current timezone

```typescript
Chathive.widget.getTimezone();
```

### setTimezone

Set or update timezone for the current form interface.

```typescript
Chathive.widget.setTimezone("Europe/Brussel");
```

## Notifications

### Chathive.widget.disableNotifications

Don't get notifications when the widget is closed. Is usefull on mobile devices

```typescript
Chathive.widget.disableNotifications();
```

### Chathive.widget.enableNotifications

Allow notifications to be shown when widget is closed.

```typescript
Chathive.widget.enableNotifications();
```

## Context

### Chathive.widget.getContext

Get the current context of the conversation

```typescript
Chathive.widget.getContext();
```

### Chathive.widget.setContextField

Set or update a new key in the conversation context.\
If you set a value to `undefined` this key will be removed from the context

```typescript
Chathive.widget.setContextField({
    key: string;
    value: Boolean | number | string | undefined,
});
```

## Customer data

### Chathive.widget.getCustomerData

Get the data from the current customer

```typescript
Chathive.widget.getCustomerData();
```

### Chathive.widget.updateCustomerData

Set or update the customer data for the current session. This will help you to identify the customer behind a conversation

```typescript
Chathive.widget.updateCustomerData(CustomerData| undefined);
```

*More info about* [*customerData*](/sdk/attributes#customer-data)


# Events

You can listen for emitted events by subscribing to them using the on method with your custom callback. For example, your function can be executed every time the widget is opend

## Chathive.widget.on

Subscribes to emitted events, which are described below.\
This function returns a subscription id that can be used to unsubscribe.

```typescript
Chathive.widget.on(eventName, () => void);
```

## Chathive.widget.off

Unsubscribes from emitted events, which are described below.

```typescript
Chathive.widget.off(subscriptionId);
```

## Events list

<table><thead><tr><th width="232">Event name</th><th>Description</th></tr></thead><tbody><tr><td>widget.init</td><td>Widget has been initialised and is ready to be used</td></tr><tr><td>widget.opened</td><td>Widget is opened</td></tr><tr><td>widget.closed</td><td>Widget is closed</td></tr><tr><td>message.inbound</td><td>New message is received.<br><em>Messages are send partially and need to be reconstructed</em></td></tr><tr><td>message.outbound</td><td>Message is send by the user</td></tr><tr><td>tool.called</td><td>Event is emitted when ever a tool is called or ended</td></tr><tr><td>tool.custom.event</td><td>Event is emitted when ever your custom event emitter tool is called</td></tr><tr><td>typing.started</td><td>Is typing is triggered by the agent</td></tr><tr><td>typing.stopped</td><td>Is typing stopped</td></tr></tbody></table>


# Attributes

This page details the possible attributes that can be used when Installing the widget

## Widget <a href="#messenger-attributes" id="messenger-attributes"></a>

### Widget init attributes

These attributes will modify the behaviour of the widget and how the agent will respond to messages.&#x20;

<table><thead><tr><th width="160">Attribute</th><th width="180">Type</th><th>Description</th></tr></thead><tbody><tr><td>apiKey</td><td>string</td><td>The API key of your project can be found in your <mark style="color:purple;">project/implementation</mark> page. </td></tr><tr><td>language</td><td><a href="https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes">ISO 639-1 language code</a></td><td>The current language of your website visitor. Must be <a href="https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes">ISO 639-1 </a></td></tr><tr><td>open</td><td>boolean</td><td>Standard open the widget</td></tr><tr><td>hide</td><td>boolean</td><td>Hide or show the widget on your website.</td></tr><tr><td>config</td><td><a href="#config-attribute">config attribute</a></td><td>Widget specific configuration. This will change the behaviour of your widget</td></tr><tr><td>context <br><br></td><td>record&#x3C;string, Boolean | number | string | undefined></td><td>Extra context that should be used by the agent to provide accurate answers. </td></tr><tr><td>customerData</td><td><a href="/pages/mWLnkjQXMREDYDh6K2jy#customer-data">customer data</a></td><td>Data to identify the current customer.</td></tr><tr><td>useNewDomain</td><td>boolean</td><td>opt-in to our new domain names to prevent cookie tracking, but can be blocked by strict enterprise firewalls</td></tr></tbody></table>

### Widget embed attributes

These attributes will modify the behaviour of the widget and how the agent will respond to messages.&#x20;

<table><thead><tr><th width="160">Attribute</th><th width="180">Type</th><th>Description</th></tr></thead><tbody><tr><td>apiKey</td><td>string</td><td>The API key of your project can be found in your <mark style="color:purple;">project/implementation</mark> page. </td></tr><tr><td>selector</td><td>string</td><td><p>Select the HTML tag where in the widget must be embedded. </p><p><em>Works the same as <code>document.querySelector</code></em></p></td></tr><tr><td>language</td><td><a href="https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes">ISO 639-1 language code</a></td><td>The current language of your website visitor. Must be <a href="https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes">ISO 639-1 </a></td></tr><tr><td>context </td><td>record&#x3C;string, Boolean | number | string | undefined></td><td>Extra context that should be used by the agent to provide accurate answers.</td></tr><tr><td>customerData</td><td><a href="/pages/mWLnkjQXMREDYDh6K2jy#customer-data">customer data</a></td><td>Data to identify the current customer. </td></tr></tbody></table>

### Config attribute

These attributes are used to change the behaviour of your widget

<table><thead><tr><th width="207">Attribute</th><th width="108">Type</th><th>Description</th></tr></thead><tbody><tr><td>notificationsEnabled</td><td>boolean</td><td>Allow notifications to be shown when widget is closed. Default this is enabled.</td></tr></tbody></table>

## Text customization <a href="#text-customization" id="text-customization"></a>

Most of the static text displayed in the form can be customized. However, text that is set in the form configuration or generated by your assistant cannot be altered.

The following text options can be customized during initialization or using `setText()`:

#### Text object <a href="#text-object" id="text-object"></a>

| launcherAriaLabelClose                | Close chat widget                                                                                                                          | ARIA label for the button that closes the chat widget (when the widget is open).                     |
| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------- |
| launcherAriaLabelOpen                 | Open chat widget                                                                                                                           | ARIA label for the button that opens the chat widget (when the widget is closed).                    |
| closeAriaLabel                        | Close chat widget                                                                                                                          | ARIA label for the primary close button inside the chat window header.                               |
| clearNotifications                    | Close chat notifications                                                                                                                   | Text or ARIA label for dismissing or clearing notification badges.                                   |
| leadGenerationTitle                   | Talk to a real person                                                                                                                      | Title of the lead generation or "Contact Me" form/modal.                                             |
| leadGenerationDescription             | Provide your email address and one of our colleagues will reach out to you.                                                                | Description or instructional text for the lead generation form.                                      |
| leadGenerationCloseAriaLabel          | Close contact me modal                                                                                                                     | ARIA label for the close button of the contact form modal.                                           |
| leadGenerationSubmitButton            | Contact me                                                                                                                                 | Text for the submission button on the lead generation form.                                          |
| leadGenerationNotificationFailed      | We were unable to process your request at this time. Please try again later or explore our available resources for immediate assistance.   | Error message shown when the lead generation submission fails.                                       |
| leadGenerationButton                  | Contact me                                                                                                                                 | Text for the button that triggers/opens the lead generation flow.                                    |
| isOptionalLabel                       | (optional)                                                                                                                                 | Label appended to form fields that are optional.                                                     |
| errorIsRequired                       | This field is required                                                                                                                     | Error message displayed when a required field is left empty.                                         |
| errorMaxLength                        | Text cannot be longer then {maxLength, plural, =1 {# character} other {#characters}}                                                       | Error message when text input exceeds the maximum length. (`{maxLength}` is a placeholder).          |
| errorUnsafeNumber                     | Number is to big                                                                                                                           | Error message for number inputs that exceed safe JavaScript limits.                                  |
| errorInvalidEmail                     | It seems like the email address you've entered is invalid                                                                                  | Error message for invalid email format validation.                                                   |
| messageToLong                         | Your message is too long. Please try to shorten it.                                                                                        | Warning message when a user attempts to send a chat message that is too long.                        |
| sendButtonAriaLabel                   | Send message                                                                                                                               | ARIA label for the message send button.                                                              |
| sourcesLabel                          | Sources                                                                                                                                    | Label displayed above the list of knowledge sources/citations.                                       |
| sourcesShowMoreAriaLabel              | Show all sources                                                                                                                           | ARIA label for the button to expand and show all hidden sources.                                     |
| positiveVoteAriaLabel                 | This answer is helpful                                                                                                                     | ARIA label for the positive (e.g., thumbs-up) feedback button.                                       |
| negativeVoteAriaLabel                 | This answer is not helpful                                                                                                                 | ARIA label for the negative (e.g., thumbs-down) feedback button.                                     |
| dropzoneTitle                         | Add files                                                                                                                                  | Title displayed in the file upload dropzone area.                                                    |
| dropzoneDescription                   | Drop any file here to add it to the conversation                                                                                           | Description displayed in the file upload dropzone area.                                              |
| fileErrorLimitReached                 | Only {limit} files can be uploaded                                                                                                         | Error message when the file count limit is reached. (`{limit}` is a placeholder).                    |
| fileErrorSizeLimit                    | You've reached the {sizeLimit} upload limit for this message.                                                                              | Error message when the message's total file size limit is reached. (`{sizeLimit}` is a placeholder). |
| fileErrorOrganizationLimitReached     | We're unable to accept file uploads at the moment. Please check back soon.                                                                 | Error message when file uploads are disabled due to organization limits.                             |
| fileErrorUnsupportedType              | File type is not supported.                                                                                                                | Error message when an unsupported file type is uploaded.                                             |
| fileErrorCloseButtonAriaLabel         | Hide error                                                                                                                                 | ARIA label for the file upload error banner close button.                                            |
| fileFailedAriaLabel                   | Failed to upload file                                                                                                                      | ARIA label for the failed file upload icon/status.                                                   |
| fileIsUploadingAriaLabel              | Uploading file                                                                                                                             | ARIA label for the file uploading status indicator.                                                  |
| fileDeleteAriaLabel                   | Delete file                                                                                                                                | ARIA label for the button to delete an uploaded file.                                                |
| uploadAttachmentButtonAriaLabel       | Upload attachment                                                                                                                          | ARIA label for the button to open the file upload dialog.                                            |
| carouselPreviousControlAriaLabel      | View previous file                                                                                                                         | ARIA label for the control to view the previous file in a file carousel.                             |
| carouselNextControlAriaLabel          | View next file                                                                                                                             | ARIA label for the control to view the next file in a file carousel.                                 |
| messageToolCallFailedTooltip          | Failed                                                                                                                                     | Tooltip text displayed when an agent's tool call fails.                                              |
| messageToolCallFailedScreenReader     | Failed                                                                                                                                     | Screen reader text for a failed agent tool call status.                                              |
| messageToolCallSucceededTooltip       | Succeeded                                                                                                                                  | Tooltip text displayed when an agent's tool call succeeds.                                           |
| messageToolCallSucceededScreenReader  | Succeeded                                                                                                                                  | Screen reader text for a successful agent tool call status.                                          |
| conversationErrorContentFilter        | Your request couldn't be processed due to our content guidelines. Please try a different question.                                         | Error message when a user's message is blocked by content filters.                                   |
| conversationErrorUnknown              | An unexpected error stopped me from responding. Please try again.                                                                          | Generic error message for an unexpected conversation failure.                                        |
| conversationErrorNotResponding        | {name} is currently experiencing some technical difficulties and can't provide an answer at the moment. Please try again in a few minutes. | Error message when the AI assistant is temporarily unavailable. (`{name}` is a placeholder).         |
| conversationErrorMessageLimitExceeded | An unexpected error stopped me from responding. Please try again.                                                                          | Error message displayed when the user/session has exceeded a message limit.                          |
| errorApiOverloaded                    | The agent is temporarily busy, please try again in a few minutes.                                                                          | Error message when the AI model is temporarily overloaded.                                           |


# AI form

The AI Form SDK makes it easy to embed your AI form into your application. It offers powerful features to customize the look and feel, ensuring the form blends seamlessly with your app.

## Installation

The AI form is already included with the Oniroco SDK. If you haven't installed it into your application, first follow the [SDK installation guide](/sdk/getting-started).

## Setup <a href="#installation" id="installation"></a>

To setup the AI form, call the constructor to initialise your AI form. There are many options you can pass to the constructor. See the [configuration documentation](/sdk/ai-form/configuration) for more details.&#x20;

```typescript
const aiForm = new Chathive.AIForm({ apiKey: "YOUR_API_KEY" });
```

{% hint style="info" %}
**Good to know:** For single-page apps, ensure this is executed after the SDK has fully loaded.
{% endhint %}

After initializing your AI form, you can embed it into your application. Ensure this is done after the `selector` element has rendered. The `selector` is a required parameter and uses `document.querySelector` to locate the HTML tag where you want to embed the form.

{% code overflow="wrap" %}

```typescript
aiForm.embed({ selector: "#embed" })
    .then(() => console.log("AI form is embedded"));
```

{% endcode %}


# Configuration

Learn about general AI form configuration fields.

Embedded AI form

The embedded AI form offers plenty of customization options to help it blend seamlessly into your application.

The following options can be configured in the constructor:

<table><thead><tr><th width="156">Key</th><th width="211">Type</th><th>Description</th></tr></thead><tbody><tr><td>apiKey</td><td><code>string</code></td><td>The API key of your project can be found in your <mark style="color:purple;">project/implementation</mark> page. </td></tr><tr><td>language</td><td><a href="https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes">ISO 639-1 language code</a></td><td>The current language of your website visitor. Must be <a href="https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes">ISO 639-1</a>.</td></tr><tr><td>colorScheme</td><td><code>auto</code> | <code>light</code> | <code>dark</code></td><td>Shows the color theme choices. <code>auto</code> will use your OS color scheme.</td></tr><tr><td>context</td><td><code>record&#x3C;string, Boolean|number |string|undefined></code></td><td>Extra context that can be used to pre-fill the form with data from your customer.</td></tr><tr><td>customerData</td><td><a href="/pages/mWLnkjQXMREDYDh6K2jy#customer-data">customer data</a></td><td>Data to identify the current customer.</td></tr><tr><td>theme</td><td><code>Partial&#x3C;Theme></code></td><td>Customise the theme of your form.</td></tr><tr><td>text</td><td><code>Partial&#x3C;Text></code></td><td>Customise the text you see in the form.</td></tr><tr><td>useNewDomain</td><td>boolean</td><td>opt-in to our new domain names to prevent cookie tracking, but can be blocked by strict enterprise firewalls</td></tr></tbody></table>

## Theme customization <a href="#css-customization" id="css-customization"></a>

You can customize the theme of your AI form either during initialization or at any time throughout its lifecycle. The example below demonstrates how to override the default background colors for both light and dark themes.

<pre class="language-typescript"><code class="lang-typescript">aiForm.setTheme({
    light: {
        background: "#DCDCDC",
    }
    dark: {
      <a data-footnote-ref href="#user-content-fn-1">  background: "#1F1F1F",</a>
    },
});
</code></pre>

<figure><img src="/files/6xlui492vlWJ3I6XbL8J" alt=""><figcaption></figcaption></figure>

### Theme object

<table><thead><tr><th width="172">Key</th><th width="128">Default light</th><th width="130">Default dark</th><th>Description</th></tr></thead><tbody><tr><td>accentColor</td><td>#002140</td><td>#215E8A</td><td>Background color for the button and user message bubbel (overrides color configured in dashboard).</td></tr><tr><td>accentFontColor</td><td>#ffffff</td><td>#ffffff</td><td>Text color when background has accent color (overrides color configured in dashboard).</td></tr><tr><td>background</td><td>#ffffff</td><td>#1F1F1F</td><td>Background color</td></tr><tr><td>cardBackground</td><td>#ffffff</td><td>#181818</td><td>Background message bubble assistant and input field.</td></tr><tr><td>borderColor</td><td>#e5e7eb</td><td>#424242</td><td>Border color used in header and around message bubble assistant.</td></tr><tr><td>errorColor</td><td>#e03131</td><td>#fa5252</td><td>Color used for error related components.</td></tr><tr><td>fontColor</td><td>#000000</td><td>#ffffff</td><td>Text color</td></tr><tr><td>warningColor</td><td>#ffa500</td><td>#fab005</td><td>Color used for warning related components.</td></tr><tr><td>excelIconColor</td><td>#40c057</td><td>#40c057</td><td>Color used in the Excel file icon</td></tr><tr><td>pdfIconColor</td><td>#e03131</td><td>#e03131</td><td>Color used in the PDF file icon</td></tr><tr><td>presentationIconColor</td><td>#ffa500</td><td>#ffa500</td><td>Color used in the Presentation file icon</td></tr><tr><td>wordIconColor</td><td>#228BE6</td><td>#228BE6</td><td>Color used in the Word file icon</td></tr><tr><td>textIconColor</td><td>#002140</td><td>#002140</td><td>Color used in the Text file icon</td></tr></tbody></table>

### Theme priority

Theme settings applied during initialisation or by `setTheme()` will override the theme configured in your project's dashboard.&#x20;

However, if you have custom CSS configured in your dashboard, it will always take precedence over any theme settings applied through the SDK or  dashboard.

The priority order is as follows:

1. Custom CSS
2. `setTheme()`
3. Project theme

## Text customization

Most of the static text displayed in the form can be customized. However, text that is set in the form configuration or generated by your assistant cannot be altered.

The following text options can be customized during initialization or using `setText()`:

### Text object

<table><thead><tr><th width="256.7442626953125">Key</th><th width="250">Default</th><th>Description</th></tr></thead><tbody><tr><td>errorNotResponding</td><td>{name} is currently experiencing some technical difficulties and can't provide an answer at the moment. Please try again in a few minutes.</td><td>The message displayed when  no response can be generated or connection is lost. ({name} will be replaced with the name of your AI assistant)</td></tr><tr><td>errorMessageLimitExceeded</td><td>{name} is currently not available at the moment. Please try again in a few minutes.</td><td>Error message displayed when no response can be generated because you have exceeded your message limit</td></tr><tr><td>errorMaxResponseCredits</td><td>{name} currently stopt responding, please try again.</td><td>Error message displayed when the agent stopt responing because it hit your credit limit</td></tr><tr><td>errorProfanity</td><td>Your request couldn't be processed due to our content guidelines. Please try a different prompt.</td><td>Error message displayed when the AI models detects the user requested harmful or illegal content or other malicious message.</td></tr><tr><td>errorApiOverloaded</td><td>The agent is temporarily busy, please try again in a few minutes.</td><td>Error message when the AI model is temporarily overloaded.</td></tr><tr><td>fallbackTitle</td><td>Currently Unavailable</td><td>The title of the fallback page when AI form cannot be loaded</td></tr><tr><td>fallbackDescription</td><td>The AI form isn't available at this time</td><td>The message displayed on fallback page </td></tr><tr><td>replyFieldTip</td><td>TIP: Press enter to send</td><td>Tip displayed under reply field</td></tr><tr><td>sendButtonAriaLabel</td><td>Send reply</td><td>The ARIA label of the send button</td></tr><tr><td>sourcesShowMoreButtonAriaLabel</td><td>Show all sources</td><td>The aria label of the show more source button. Once clicked will show all hidden sources</td></tr><tr><td>sourcesLabel</td><td>Sources</td><td>Title above the sources</td></tr><tr><td>warningInputToLong</td><td>Your input is a bit too long. Please shorten it and try again.</td><td>The message displayed when user input is to long</td></tr><tr><td>continueButtonLabel</td><td>Continue</td><td>Button shown when the assistant's last message is not fully typed. By error or by threshold timeout.</td></tr><tr><td>dropzoneTitle</td><td>Add files</td><td>Title in dropzone area when user uploads a file</td></tr><tr><td>dropzoneDescription</td><td>Drop any file here to add it to the conversation</td><td>Description in dropzone area when user uploads a file</td></tr><tr><td>fileErrorLimitReached</td><td>Only {limit} files can be uploaded</td><td>Error message when user tries to upload more then 5 files per message.</td></tr><tr><td>fileErrorSizeLimit</td><td>You've reached the {sizeLimit} upload limit for this message.</td><td>Error message when user tries to upload a file that is bigger then 25MB or the sum of all uploaded files sizes in the message is bigger then 25MB</td></tr><tr><td>fileErrorUnsupportedType</td><td>File type is not supported.</td><td>Error message file is uploaded with unsupported file type</td></tr><tr><td>fileErrorOrganizationLimitReached</td><td>We're unable to accept file uploads at the moment. Please check back soon.</td><td>Error message when user cannot upload any files because organisation has reached it's storage limit</td></tr><tr><td>fileErrorCloseButtonAriaLabel</td><td>Hide error</td><td>File error banner close button ARIA label.</td></tr><tr><td>fileFailedAriaLabel</td><td>Failed to upload file</td><td>File failed to upload icon ARIA label.</td></tr><tr><td>fileIsUploadingAriaLabel</td><td>Uploading file</td><td>File is uploading icon ARIA label.</td></tr><tr><td>fileDeleteAriaLabel</td><td>Delete file</td><td>File delete button ARIA label.</td></tr><tr><td>uploadAttachmentButtonAriaLabel</td><td>Upload attachment</td><td>Upload button ARIA label.</td></tr><tr><td>carouselPreviousControlAriaLabel</td><td>View previous file</td><td>ARIA label carousel back button</td></tr><tr><td>carouselNextControlAriaLabel</td><td>View next file</td><td>ARIA label carousel next button</td></tr><tr><td>messageToolCallFailedTooltip</td><td>Failed</td><td>Tooltip message when tool call has failed</td></tr><tr><td>messageToolCallFailedScreenReader</td><td>Failed</td><td>Screen reader message when tool call has failed</td></tr><tr><td>messageToolCallSucceededTooltip</td><td>Succeeded</td><td>Tooltip message when tool call has succeeded</td></tr><tr><td>messageToolCallSucceededScreenReader</td><td>Succeeded</td><td>Screen reader message when tool call has succeeded</td></tr></tbody></table>

[^1]:


# Methods

The AI form instance offers various methods to help you interact with and customize it.

## Instance

### Embed

Embed the AI form instance into your application. The **selector** is required, and is document querySelector to find the HTML-tag into which you want to embed the form.

<pre class="language-typescript"><code class="lang-typescript"><strong>aiForm.embed({ selector: "#embed" })
</strong></code></pre>

### isLoaded

Returns `true` if the instance has been loaded and embedded into your application.

<pre class="language-typescript"><code class="lang-typescript"><strong>aiForm.isLoaded()
</strong></code></pre>

### getVersion

Returns the current version of the SDK

```typescript
aiForm.getVersion()
```

### destroy

Remove the form interface from your application.

```typescript
aiForm.destroy();
```

## Styling

### getColorScheme

Get the current colorScheme.

```typescript
aiForm.getColorScheme();
```

### setColorScheme

Sets your preferred color theme choices. `auto` will use your OS color scheme.

```typescript
aiForm.setColorScheme("auto" | "light" | "dark");
```

### getTheme

Get the theme configuration that has been set

```typescript
aiForm.getTheme();
```

### setTheme

Set or change the theme of your interface. *More info about* [*theme configuration*](/sdk/ai-form/configuration#css-customization)

```typescript
aiForm.setTheme({
    light: ThemeObject,
    dark: ThemeObject,
});
```

## Settings

### isFileUploadAllowed

Check if file upload has been allowed

```javascript
aiForm.isFileUploadAllowed
```

### setIsFileUploadAllowed

Change if customers are allowed to upload files into the conversation. Will only work if file upload has been enabled in the project.

```javascript
aiForm.setIsFileUploadAllowed(allowed: boolean);
```

## Text

Most static text that you see in the form can be customised

### getText

Get the text configuration that has been set

```typescript
aiForm.getText();
```

### setText

Set or change the text of your interface. *More info about* [*text configuration*](/sdk/ai-form/configuration#text-customization)

```typescript
aiForm.setText(TextObject);
```

## Language

### getLanguage

Get the current language that is used. By default we will use the language that has been set as default in your project

```typescript
aiForm.getLanguage();
```

### setLanguage

Set or change the language of your interface. We support all [ISO 639-1 language codes](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes).

```typescript
aiForm.setLanguage("nl");
```

## Context

Context allows you to supply pre-existing information to the form, helping the assistant avoid asking your customer unnecessary questions.

### getContext

Get the context that have been set in the form instance.

```typescript
aiForm.getContext();
```

### updateContextField

Set or update a new key in the form instance context. \
If you set a value to `undefined` this key will be removed from the context.

```typescript
aiForm.updateContextField(
    { key: "value" }: Record<string, Boolean | number | string | undefined>
);
```

## Customer data

Customer data helps you to identify the customer behind a form session.

### getCustomer

Returns the data we known about your customer.

```typescript
aiForm.getCustomer();
```

### setCustomer

Set or update customer data for the current form interface.

```typescript
aiForm.setCustomer(CustomerData | undefined);
```

*More info about* [*customerData*](/sdk/attributes#customer-data)

## Timezone

Customize the timezone for your conversation. By default, the project's timezone will be used.

### getTimezone

Returns the current timezone

```typescript
aiForm.getTimezone();
```

### setTimezone

Set or update timezone for the current form interface.

```typescript
aiForm.setTimezone("Europe/Brussel");
```

## Static methods

### generateSessionId

Generate a unique session id

```typescript
Chathive.AIForm.generateSessionId()
```


# Events

You can listen for emitted events by subscribing to them using the on method with your custom callback. For example, your function can be executed every time a new message is received

## on

Subscribes to emitted events, which are described below.\
This function returns a subscription id that can be used to unsubscribe.

```typescript
aiForm.on(eventName, (payload) => void);
```

## off

Unsubscribes from emitted events, which are described below.

```typescript
aiForm.off(subscriptionId);
```

## Events list

<table><thead><tr><th width="232">Event name</th><th>Description</th></tr></thead><tbody><tr><td><code>initialized</code></td><td>AI form has been initialised and is ready to be used</td></tr><tr><td><code>error</code></td><td>Unexpected error has occurred</td></tr><tr><td><code>message.inbound</code></td><td>New message is received.<br><em>Messages are send partially and need to be reconstructed</em></td></tr><tr><td><code>message.outbound</code></td><td>Message is send by the user</td></tr><tr><td><code>session.completed</code></td><td>User has filled in all necessary fields. Form session has been marked as completed</td></tr><tr><td><code>tool.called</code></td><td>Event is emitted when ever a tool is called or ended</td></tr><tr><td><code>tool.custom.event</code></td><td>Event is emitted when ever your custom event emitter tool is called</td></tr><tr><td><code>typing.started</code></td><td>Is typing is triggered by the agent</td></tr><tr><td><code>typing.stopped</code></td><td>Is typing stopped</td></tr></tbody></table>


# Custom tool events

Your AI agent can emit custom events to the SDK whenever it determines an action needs to be handled. By creating a custom tool, you can give your agent the ability to trigger these events.

With the event emitter you can give your AI agent the tools to interact with the website it's embedded on. Give it the ability to navigate to open popups, navigate to product details or even open your dedicated live chat.

## Create event tool

* In your project's **Tools** section, select **Create Tool**.
* Choose `build your own tool`&#x20;

<figure><img src="/files/Cm9qKXG1eOsm3MUw5Try" alt=""><figcaption></figcaption></figure>

### Tool setup

In this step, you’ll provide the core details of your tool:

* **Name**: A unique name (within the project). This name will also be used when the event is emitted, allowing you to identify which event was triggered.
* **Description**: A short explanation of the tool’s purpose.
* **When to Call Instructions**: Guidance for the agent on when it should call the tool, giving it the context needed to use the tool correctly.

<figure><img src="/files/NeJwcBlWlDyqim4Ny8TB" alt=""><figcaption></figcaption></figure>

### Tool parameters

in the [parameters](/tools/parameters) section you can use JSON schema to define the data your agent should request from the user before emitting the event.

* If parameters are defined, the agent will prompt the user for that data.
* If left empty, no additional user input will be required.

All defined parameters will be included in the emitted event.

### Configure action

After setting up the tool and its parameters:

1. Select **Emit Event** as the action type.
2. Save your tool.

Your agent can now emit this custom event to your SDK.

<figure><img src="/files/6vxL8UMXdWMfb7h5SIHF" alt=""><figcaption></figcaption></figure>

## Receive event

How you listen for events may vary slightly depending on whether you’re using the [chatbot](/sdk/chatbot/events) or  [AI from](/sdk/ai-form/events)  SDK, but the process is essentially the same.

Once the SDK is initialized, create a subscription to `tool.custom.event`.\
Each time the event is emitted, your callback function will receive the following data:

* **Name**: The unique tool name you defined.
* **Parameters**: All user-provided parameters plus system parameters.
* **Context**: The current conversation context.
* **Customer**: Customer information related to the conversation.
* **Project**: The associated project name.
* **Organization**: The associated organization name.
* **Conversation**: Conversation details, including messages and transcriptions.

```javascript
Chathive.widget.on("tool.custom.event", ({ name, parameters }) => {
    console.log("Event name:", name);
    console.log("Parameters:", parameters);
});
```


# Attributes

This page outlines the attributes that can be used or configured in both chatbot and AI form projects.

## Customer data

These attributes are used to identify the current customer:

<table><thead><tr><th width="135">Attribute</th><th width="90">Type</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td>string</td><td>The id of the customer in your system</td></tr><tr><td>email</td><td>string</td><td>Customers emails</td></tr><tr><td>firstName</td><td>string</td><td>Customers first name</td></tr><tr><td>lastName</td><td>string</td><td>Customers last name</td></tr><tr><td>avatar</td><td>string</td><td>Avatar to display for the customer</td></tr><tr><td>link</td><td>string</td><td>Link that redirects users to this customer inside your CRM system </td></tr></tbody></table>

{% hint style="warning" %}
Ensure compliance with GDPR laws when setting customer data.
{% endhint %}


# Overview

Tools enhance your AI by connecting it to various apps and services, enabling it to fetch real-time information, update your CRM, send notifications, and much more. They keep your AI up to date and help you get things done efficiently!

## How to create a tool

Tools are contained within your project to ensure that sensitive tools aren’t accidentally activated in public projects. You can create a custom tool directly within your project or start with one of our templates.

A custom tool relies on an API request executed by the AI model. You can set this up easily using our step-by-step wizard in just 3 simple steps.

### Tool Prompts

* **Name:** Give your tool a unique name within your project.
* **Description:** Clearly explain what your tool does and what kind of response it will generate.
* **When to Call:** Specify exactly when the model should use this tool.

Example:

```
name: "get_current_weather"
description: "Get the current weather in a given location"
when to call: "When the users ask for the weather use get_current_weather"
```

### Parameters

Specify the parameters your AI model must provide to your tool. These parameters are defined using a [JSON schema](https://json-schema.org/), allowing you to leverage its rich features for validation and structure.

If no parameters are defined, the AI model will execute your tool without passing any parameters.

{% content-ref url="/pages/cJCkyXJBkEGTWSHC0ctM" %}
[Parameters](/tools/parameters)
{% endcontent-ref %}

### API configuration

In the final step, you can configure your API using our **API builder**.

![Screenshot of the api tool setup with a example how to use template variable in the url field and body](/files/qfJPgCgkxk4kLU68s9mQ)<br>

By default, parameters are passed directly into the request body. However, you can override this with a custom request body if needed. This allows you to include additional information, such as conversation context or other values, without requiring the AI model to request them from the user.

#### Template variabels

In your API setup, you can use **variables** in the **URL**, **query parameters**, **headers**, and **body**. These templates will automatically be replaced with the corresponding values when the tool is called.

<table><thead><tr><th width="275.51702880859375">Template key</th><th>Description</th></tr></thead><tbody><tr><td>{{<em>parameter_key</em>}}</td><td>Access your parameters</td></tr><tr><td>{{context.<em>your_key</em>}}</td><td>Access the context you've provided to the SDK</td></tr><tr><td>{{customer.id}}</td><td>Get the id of the conversations customer</td></tr><tr><td>{{customer.email}}</td><td>Get the email of the conversations customer</td></tr><tr><td>{{customer.firstName}}</td><td>Get the first name of the conversations customer</td></tr><tr><td>{{customer.lastName}}</td><td>Get the last name of the conversations customer</td></tr><tr><td>{{customer.avatar}}</td><td>Get the avatar of the conversations customer</td></tr><tr><td>{{project._id}}</td><td>Get the id of the project</td></tr><tr><td>{{project.name}}</td><td>Get name of the project</td></tr><tr><td>{{organization._id}}</td><td>Get the organization id</td></tr><tr><td>{{organization.name}}</td><td>Get the name of the organization</td></tr><tr><td>{{conversation.language}}</td><td>Get the language of the conversation</td></tr><tr><td>{{conversation.sessionId}}</td><td>Get the sessionId of the conversation</td></tr><tr><td>{{conversation.createdAt}}</td><td>Get the datetime the conversation was created</td></tr><tr><td>{{conversation.updatedAt}}</td><td>Get the datetime the conversation was last updated</td></tr><tr><td>{{conversation.lastMessageAt}}</td><td>Get the datetime the last message was send</td></tr><tr><td>{{conversation.tagIds}}</td><td>Get <code>,</code> -seperated list with all tag ids in the conversation</td></tr></tbody></table>

### Response restrictions

#### Timeout

To keep your agents running smoothly, tools have a **5-minute** response window before timing out.\
We will lower this timeout in the future to improve performance.

#### Response size

To keep things running smoothly and avoid overloading the agent, there is a **25MB limit** on all responses. If a tool tries to return more data than that, the call will be stopped and the agent will receive an error message explaining that the response was too big.


# Parameters

When you configure your tool, you can define the parameters your AI model should provide. These parameters follow a [**JSON schema**](https://json-schema.org/), ensuring structured and validated inputs.

### **Define Parameters in JSON Schema**

Each parameter should include:

* **name**: The parameter's key.
* **type**: The expected data type (`string`, `number`, `boolean`, etc.).
* **description**: A brief explanation of the parameter.
* **required**: Whether the parameter is mandatory.

Here’s an example schema for the **get\_weather** tool:

```json
{
  "type": "object",
  "properties": {
    "location": {
      "type": "string",
      "description": "The name of the city or geographic coordinates for weather lookup."
    },
    "unit": {
      "type": "string",
      "enum": ["metric", "imperial"],
      "description": "The temperature unit: 'metric' for Celsius, 'imperial' for Fahrenheit."
    }
  },
  "required": ["location"],
  "additionalProperties": false,
}
```

***

### **How the AI Uses These Parameters**

When the AI calls the **get\_weather** tool, it provides values based on the defined schema. For example, the AI might generate the following request:

```json
{
  "location": "New York",
  "unit": "metric"
}
```

* If a parameter is marked as **required**, the AI will always provide it.
* Optional parameters, like `unit`, will only be included if the AI model thinks it is necessary.

***

### **Returning the Response**

Once the tool processes the request, it should return a structured response, which can also be formatted before passing it back to the AI.

{% content-ref url="/pages/Uz2fvGxXKDE5A1Tl43SB" %}
[Format response](/tools/format-response)
{% endcontent-ref %}


# Format response

If your tool returns complex, unstructured, or excessive information, you can format the response before passing it to the AI model. This helps improve the accuracy of the AI’s response and context bloating.

You can format the response by writing JavaScript code that modifies the tool’s output. Write your code into the editor, and it will execute once the tool has run successfully.

The tool's response is accessible through the **`response`** variable, which is always a string. If you expect a JSON object, you’ll need to parse it first.

Once you've formatted the response, ensure you return it as a string to achieve the best results.

<figure><img src="/files/xS9P3uEO97h795NUo3Ce" alt=""><figcaption><p>Example code how to format the response of the weather tool</p></figcaption></figure>

### Variables

We provide three string variables:

* **Response**: A stringified output returned by the tool.
* **Session**: A stringified JSON object containing session metadata:
* <pre class="language-json"><code class="lang-json">{ 
      user: object;
      sessionId: string;
      language: string;
  <strong>    createdAt: string;
  </strong>    updatedAt: string;
      customer: object;
      context: object;
      projectId: string;
      organizationId: string;
  }
  </code></pre>
* **Parameters**: A stringified JSON object containing all parameters passed to the tool.

### Tip

To ensure the AI model can process the response accurately and effectively.  We encourage you to follow these tips:

* **For simple data:** Return it as a string that clearly explains the data and its fields.
* **For complex data:** If the data cannot be easily formatted into a string, include a description explaining how the AI model should interpret it. Then, return both the description and data as a single string.


# API trigger

Trigger your agent directly from you apps or websites with the API trigger.

## Create trigger

* API triggers are created inside **agent projects**.
* Each API trigger must have a **unique name** and **unique key** within the project.
* The trigger key is **case-insensitive** and can be customised to match an identifier meaningful for your application.

> **Note:** Make sure the key is something easy to reference when making API calls.

<figure><img src="/files/rqusTIYyCio519WkAla0" alt=""><figcaption></figcaption></figure>

### Create API key

API triggers are secured by [API keys](https://chathive.app/api_key) that are managed by your organization.

* The API key must have at least the permission `project.trigger`

<div align="left"><figure><img src="/files/jlmdVjs7Tp3FQWTR5uUp" alt="" width="375"><figcaption></figcaption></figure></div>

#### Best practices

* Only grant the API key access to the specific projects it needs.
* Limit the permissions to only what’s required.

## Send a request

To call your trigger, send a **POST** request to its unique URL.

```
https://api.oniroco.app/api/v1.0/project/:projectId/trigger/:key
```

This URL can be found in the trigger settings, or construct it using your project ID and trigger key.

Optionally, include a JSON body with instruction and configuration. The body will be passed to your filters.

* Be processed by the trigger’s filters.
* Be passed to your agent as input.

The api key you created must be included in the headers of the post request.

```url
curl -X POST "https://api.oniroco.app/api/v1.0/project/:projectId/trigger/:key" \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{ "key": "value" }'
```

### Request body

You can include a body with the trigger to give your AI agent more context when executing your request. The following fields are supported:

<table><thead><tr><th width="190.47210693359375">Status</th><th width="174.94775390625">Value</th><th>Description</th></tr></thead><tbody><tr><td>instruction<br></td><td>string | object</td><td>Instruction that will be provided to the agent, can be a string or object</td></tr><tr><td>sessionId<br><br><br></td><td>string<br><br><br></td><td>Unique string generated by you to distinguished conversations. When sessionId changes all previous conversation context will be lost and it will be like a new conversation has started</td></tr><tr><td>environment<br></td><td>string<br></td><td>Identify in the analytics from where the request came. Default: "api"</td></tr><tr><td>language<br></td><td><a href="https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes">ISO 639-1 language code</a></td><td>The current language of your website visitor. Must be <a href="https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes">ISO 639-1 </a></td></tr><tr><td>timezone<br><br><br></td><td>string<br><br><br></td><td>Accepted but request timed out before agent completed it's task. Is only returned when <code>wait for response</code> has been enabled and request took to long.</td></tr><tr><td>customer</td><td><a href="/pages/mWLnkjQXMREDYDh6K2jy#customer-data">customer data</a></td><td>Data to identify the current customer.</td></tr><tr><td>context<br><br></td><td>record&#x3C;string, Boolean | number | string | undefined></td><td>Extra context that should be used by the agent to provide accurate answers. <br></td></tr></tbody></table>

### Response

<table><thead><tr><th width="190.47210693359375">Status</th><th>Description</th></tr></thead><tbody><tr><td>200<br></td><td>Request has been accepted and agent completed it's task.<br>Body will be included with final response.</td></tr><tr><td>202</td><td>Request has been accepted but agent is stil executing the task. Is only returned when  <code>wait for response</code> has been disabled. /</td></tr><tr><td>400</td><td>Event has been dropped. The body doesn't match the filters</td></tr><tr><td>404<br><br></td><td><ul><li>Trigger does not exist</li><li>Trigger has been paused</li><li>Trigger has been deleted</li></ul></td></tr><tr><td>408<br><br><br></td><td>Accepted but request timed out before agent completed it's task. Is only returned when <code>wait for response</code> has been enabled and request took to long.</td></tr></tbody></table>

## Advanced Settings

### Customize trigger key

Customize the trigger key used in the API to clearly indicate which trigger is being executed in your code. Some key guidelines:

* Must be unique within your organization.
* Can only contain the following characters: `a-zA-Z0-9_-`.

<figure><img src="/files/tPM47zN7CPFbeVOPy5rt" alt=""><figcaption></figcaption></figure>

### Ignore duplicate triggers

To prevent executing the same trigger multiple times and waisting AI credits, you can enforce it to only execute triggers with a unique body. Once this is turned on, every trigger that is executed with the same body will be dropped. This will only check triggers that are executed with a body.

<figure><img src="/files/UNvmnaVhJjLk7B9WE91k" alt=""><figcaption></figcaption></figure>

### Strict body

When you don't have control on how the [request body](#request-body) is send to the trigger. You can disable the strict body option. This will pass the request body completely to the AI agent. \
We recommend to use strict body as much as possible.

### Wait for response

For tasks that take a long time (minutes, hours, or days), you can configure the trigger to immediately return a $$(202)$$ success response once the task is accepted.

This way, your server doesn't have to wait for the task to finish.

<figure><img src="/files/nzejGSkcF4kA8ceDZSHI" alt=""><figcaption></figcaption></figure>


