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

# Website widget

> A chat bubble on the merchant's own storefront.

```http theme={null}
GET|POST /api/v1/partner/tenants/{ref}/channels/website/
```

```json theme={null}
{ "allowed_origins": ["https://moticreations.com"], "brand_color": "#1f3c7a" }
```

The response carries a publishable key and a ready-to-paste snippet:

```html theme={null}
<script src="https://cdn.impellabs.tech/sdk/impel-chat.js"
  data-impel-key="…"
  data-api-base-url="https://api.impellabs.tech/api/v1"
  data-brand-color="#1f3c7a"
  defer></script>
```

`GET` returns `{"configured": false}` before the channel exists, rather than a
404 — on this API a 404 means "that tenant is not yours", and reusing it for
"not set up yet" would make the two indistinguishable.

### Pin the SDK version

`/sdk/impel-chat.js` is one file that always serves the current release. It is
convenient and it is also a moving target: a storefront embedding it gets a
different widget the next time the SDK is published, without the merchant
having changed anything and with no way to tell that it happened.

Every release is also served at a path of its own, and that path is never
rewritten:

```html theme={null}
<script src="https://cdn.impellabs.tech/sdk/0.0.1-alpha.29/impel-chat.js"
  data-impel-key="…"
  data-api-base-url="https://api.impellabs.tech/api/v1"
  data-brand-color="#1f3c7a"
  defer></script>
```

Rewrite the `src` in `embed_snippet` to a versioned path before handing it to a
merchant, and change it deliberately when you have tested the next release.
Everything else in the snippet stays as returned.

```http theme={null}
GET https://cdn.impellabs.tech/sdk/versions.json
```

```json theme={null}
{ "current": "0.0.1-alpha.29",
  "supported": ["0.0.1-alpha.29", "0.0.1-alpha.28", "0.0.1-alpha.27"],
  "deprecated": [] }
```

`current` is what the unversioned path serves. `supported` is what is served
and will keep being served; `deprecated` still works but is no longer getting
fixes. Nothing is removed without the pinned storefronts being checked first —
a `src` that stops resolving is a blank corner on a merchant's site, and the
browser reports nothing anybody is watching.

<Note>
  Appearance — colour, font, corners, placement — is fetched from
  `/chat/status` at runtime and outranks the `data-` attributes, so changing a
  merchant's branding does not require touching a pasted tag. The pinned version
  governs the widget's code, not its look.
</Note>

### allowed\_origins is required

<Warning>
  The widget key is **publishable** — it ships to browsers and is visible in page
  source. That is fine, and by design: it can only start a conversation. The
  origin allowlist is what stops it being lifted off one merchant's page and
  embedded somewhere else on their credit.

  An empty list is rejected at provisioning time rather than silently meaning
  "any site".
</Warning>

Include every host the storefront serves from, including `www.` if used.
Requests from anywhere else get a 403 with a named reason.

### Nothing answers until the assistant is live

A configured widget on a merchant with no active assistant returns 503 with
`reason: "no_agent"`. That is the [activate](/reseller/assistants) call, not a
misconfiguration.
