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

# Web SDK reference

> Every option and call in the Feddy web widget.

The widget is one script with no dependencies. Loading it defines a global `Feddy` object with four methods and one callback, and this page is the complete list.

```html theme={null}
<script src="https://core.feddy.app/sdk/feddy.js"></script>
```

The script can be loaded from any site; it's served with a one-hour cache and open CORS. The widget draws itself inside a shadow root attached to `div#feddy-widget`, which means it keeps its own styles: your page's CSS never affects it and its CSS never affects your page. Keyboard events inside the widget don't reach your page either.

## `Feddy.init(options)`

```js theme={null}
Feddy.init({ projectId: 'fd_XXXXXXXXXXXXXXXX' })
```

Sets the widget up on the page. It only takes effect once per page load; later calls do nothing. If the page is still loading when you call it, the widget waits and appears once the page is ready. Without a project ID it logs `[Feddy] init requires a projectId` and does nothing.

| Option | Type | Default | Description |
| - | - | - | - |
| `projectId` | `string` | required | Copied from **Settings → Install** in the dashboard. Public by design. |
| `apiUrl` | `string` | `https://core.feddy.app` | Point at a local server during development. |
| `launcher` | `boolean` | `true` | Show the floating chat button bottom-right. Set `false` to open the panel from your own element instead. |
| `sounds` | `boolean` | `true` | Play a chime when a reply arrives. |
| `replyPopups` | `boolean` | `true` | Show a card above the floating button when a reply the visitor hasn't seen is waiting. Set `false` to rely on the badge alone. |
| `locale` | `string` | `navigator.language` | Force a language with a code such as `'ja'` or `'zh-TW'`. |

## `Feddy.identify(options)`

```js theme={null}
Feddy.identify({
  userId: 'u_123',
  email: 'user@example.com',
  name: 'Ada',
  avatarUrl: 'https://cdn.example.com/avatars/u_123.png',
  attributes: { plan: 'pro', credits_left: 42 },
})
```

Tells Feddy which of your users is on this browser. You can call it before `init`; the call is held and sent once the widget is ready. Does nothing without `userId`. If something goes wrong, it logs a warning with `console.warn` and never throws. What happens on the server, including how records from different devices merge, is in [Identify users](https://feddy.app/docs/guides/identify-users.md).

| Field | Type | Description |
| - | - | - |
| `userId` | `string` | Your own stable ID for the user, 1 to 128 characters. |
| `email` | `string` | Optional. Lets replies reach the user by email once your project has a verified email domain. |
| `name` | `string` | Optional. Shown in the inbox. |
| `avatarUrl` | `string` | Optional. An `http(s)` URL of a picture you already have of the user, shown in the inbox. Anything else is ignored. |
| `attributes` | `object` | Optional facts about the user, such as their plan: a flat object of strings, numbers, and booleans. Limits are listed in [Identify users](https://feddy.app/docs/guides/identify-users.md). |

## `Feddy.open()` and `Feddy.close()`

```js theme={null}
document.querySelector('#help').addEventListener('click', () => Feddy.open())
```

Open or close the panel from your own element. `open()` shows the user's conversations and a button to start a new one. Both do nothing until `init` has set the widget up.

## `Feddy.onUnreadCountChanged`

```js theme={null}
Feddy.onUnreadCountChanged = (count) => {
  badge.textContent = count > 0 ? String(count) : ''
}
```

A function the widget calls whenever the unread count changes. The widget checks every 45 seconds and again each time the tab becomes visible. Use it to drive your own badge when the floating button is off.

## What happens on its own

* **Identity**: the first time the widget runs, it creates an anonymous ID and stores it in `localStorage` under `feddy_anon_id`. Clearing site data resets it, which is why the widget offers to collect an email after a first message when your project has a verified email domain.
* **Language**: the widget ships in English, Simplified Chinese, Traditional Chinese, Japanese, Korean, German, French, Spanish, Brazilian Portuguese, and Russian, and follows the browser language. `zh-TW`, `zh-HK`, and `zh-MO` resolve to Traditional Chinese; `pt` resolves to Brazilian Portuguese. Other languages fall back to English. Text you write in the dashboard, such as topics, is translated on the server according to your project settings.
* **Attachments**: up to 5 images per message, 10 MB each before resizing. The browser resizes them so the longest edge is 2000 px and converts them to WebP before upload.
* **Screenshots**: a camera button in the message box attaches a picture of the page as the visitor sees it, with the widget itself left out. It's made in the browser with no permission prompt. Images from other sites, videos, and embedded frames show as grey boxes, and web fonts fall back to system fonts, which is enough to show which screen and what state. The button is hidden when attachments aren't available on your plan.
* **Branding**: the name, accent color, and logo users see come from the dashboard. The accent color is applied as `--fd-accent` inside the shadow root, and the widget picks a readable text color to go with it.
* **Reply popups**: when a reply the visitor hasn't seen is waiting, a card appears above the floating button saying who replied, with the first two lines of the latest reply. Clicking it opens that conversation; the close button dismisses it. If several replies are waiting, only the newest shows. Each reply shows at most once per browser, only replies from the last 14 days, and never while the panel is open. It checks shortly after the page loads, when the tab becomes visible again, and when a new reply arrives.
* **Floating button**: fixed bottom-right, 56 px, with an unread count badge. Its `z-index` is `2147483000`, so it sits above everything on the page.


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