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

# SDKs

> Official Widgetic SDKs and libraries

Widgetic provides an SDK for calling the API from your server, an embed script for showing widgets on your pages, and a UI SDK for putting Widgetic's editors in your own page.

## Official SDKs

> [card] JavaScript / TypeScript API SDK
>
> The `@widgetic/api-sdk-ts` package on npm, for your server

> [card] Embed Script
>
> One script tag from the Widgetic CDN that shows published widgets. For a project that bundles its own JavaScript, the same code is on npm as `@widgetic/embed-sdk`

> [card] UI SDK (preview)
>
> The `@widgetic/ui-sdk` package on npm, for your customer's browser: the File Browser, the composition editor, the widget creator and Workflows in your own page

> [!TIP]
>
> Three packages are on npm: `@widgetic/api-sdk-ts` for your server, `@widgetic/ui-sdk` for Widgetic's editors in your page and `@widgetic/embed-sdk` for showing widgets from a project that bundles its own JavaScript. For other languages, use the multi-language code samples in the API Reference (or cURL).

## JavaScript / TypeScript API SDK

The primary SDK for interacting with the Widgetic API from your server.

### Installation

```bash npm theme={null}
npm install @widgetic/api-sdk-ts
```

```bash yarn theme={null}
yarn add @widgetic/api-sdk-ts
```

```bash pnpm theme={null}
pnpm add @widgetic/api-sdk-ts
```

### Basic Usage

```javascript theme={null}
import { WidgetsApi } from '@widgetic/api-sdk-ts';

// Initialize with API key
const widgets = new WidgetsApi(process.env.WIDGETIC_API_KEY);

// Fetch widgets
const result = await widgets.getWidgets({ page: 1, size: 20 });
console.log(result);
```

Every method takes one request object, for example `getWidgets({ page: 1, size: 20 })`, and the body of a create call sits under a named key, for example `createManagedUser({ newManagedUser: { ... } })`.

> [!TIP]
>
> You can use either API keys (recommended for server-side) or JWTs depending on your integration.
> See [Authentication](https://widgetic.com/docs/authentication.md) for details.

> [!WARNING]
>
> Call the SDK from your server, never from a browser page: a key in a page can be read by every visitor.

### Available APIs

| Class | Description |
| - | - |
| `WidgetsApi` | Widget management |
| `CompositionsApi` | Composition management |
| `CanvasesApi` | Canvas operations |
| `TokensApi` | Token validation |
| `EntitlementsApi` | Feature access |
| `UsersApi` | User management |
| `ManagedUsersApi` | Partner user management and editor sessions |
| `WorkflowsApi` | Workflows, including a partner's calls for one customer (Preview, see [Workflows](https://widgetic.com/docs/partners/workflows.md#from-your-server)) |
| `PartnersApi` | Partner operations: contract, billing overview, credits, storage, notifications, analytics and presets |
| `CreditsApi` | Account credit balance and ledger |
| `InvoicesApi` | Invoices |
| `PublicEmbedApi` | The public routes behind the embed script: embed state, frame, status and entries. These routes are not under `/v1`, so build it with the API address as its base path (below) |

The public embed routes are at `https://api.widgetic.com/embed`. The SDK's default base path ends in `/v1`, so pass the address without it:

```javascript theme={null}
import { Configuration, PublicEmbedApi } from '@widgetic/api-sdk-ts';

const embed = new PublicEmbedApi(new Configuration({ basePath: 'https://api.widgetic.com' }));
```

### Calls for One Customer

A call that takes the `X-Managed-User-Id` or `X-Managed-User-External-Id` header (see [Scoping a Composition Call to One Customer](https://widgetic.com/docs/partners/managed-users.md#scoping-a-composition-call-to-one-customer)) takes it as `xManagedUserId` or `xManagedUserExternalId` in the request object. The workflow calls also take the `workspaceId`, which is `personal` for one customer:

```javascript theme={null}
import { WorkflowsApi } from '@widgetic/api-sdk-ts';

const workflows = new WorkflowsApi(process.env.WIDGETIC_API_KEY);

const { data } = await workflows.listWorkspaceWorkflows({
  workspaceId: 'personal',
  xManagedUserId: managedUserId,
});
// data.items holds that customer's workflows and no one else's
```

### Sending an Idempotency-Key

Most calls that make or change something need an `Idempotency-Key` header, such as creating a composition, a widget or a managed user (see [Idempotency](https://widgetic.com/docs/reference/idempotency.md)). Send it as `idempotencyKey` in the request object, and send the same one when you retry that call:

```javascript theme={null}
import { randomUUID } from 'node:crypto';
import { CompositionsApi } from '@widgetic/api-sdk-ts';

const compositions = new CompositionsApi(process.env.WIDGETIC_API_KEY);

const composition = await compositions.createComposition({
  newComposition,
  // Reuse the same key when you retry this call
  idempotencyKey: randomUUID()
});
```

The SDK requires `idempotencyKey` in the request object on every call that takes the header; a request sent without the header is answered by the API with `400`.

### Request and Response Field Names

Every method returns the standard response envelope (`{ success, data, meta? }`) as sent by the API. Note that a few partner request bodies name their fields in snake\_case (`external_id`, `manager_id`, `expires_in_seconds`), while every answer from the API names its fields in camelCase (`externalId`, `managerId`, `expiresAt`). Read the camelCase name from an answer.

## Embed Script

To show a published widget on your pages, load the embed script from the Widgetic CDN and put a `<widgetic>` element where the widget should appear. There is nothing to install and no key in the page: showing a widget needs only the composition id.

```html theme={null}
<script src="https://cdn.widgetic.com/sdks/browser/embed-sdk.js?v=6"></script>
<widgetic composition-id="COMPOSITION_ID" resize="fill-width" width="800" height="450" autoscale="on" adaptive="480" embed-target="site"></widgetic>
```

* **Several widgets on one page** work with one script tag.
* **Responsive**: `resize` and `adaptive` control how the widget fits its container.
* **`embed-target`** is `site` to put the widget inside the page, `overlay` to show it as a pop-up, or `mixed` for both. Overlay is the default, so use `site` for an ordinary embed.
* **Allowed websites**: if you limited the websites that may show your widgets, the script shows nothing on other websites. Your own machine and Widgetic's own sites are always allowed, and so is a partner's platform website with all of its subdomains. See [Security](https://widgetic.com/resources/security.md#domain-validation).

When you cannot load a script, use the frame instead:

```html theme={null}
<iframe src="https://api.widgetic.com/embed/compositions/COMPOSITION_ID/frame" width="800" height="450" frameborder="0" allowfullscreen></iframe>
```

### In a project with a bundler

If you bundle your own JavaScript (Vite, webpack, Next.js) and would rather not add a third-party script tag, the same code is on npm:

```bash theme={null}
npm install @widgetic/embed-sdk
```

```javascript theme={null}
import { getSDK } from '@widgetic/embed-sdk';

// Loading the package in a browser starts the embed script: it finds the <widgetic> tags and watches for new ones.
// Calling getSDK() keeps your bundler from dropping the import.
getSDK();
```

Load it in the browser only: it scans the page, and a server has no page. In React or Next.js, call it from an effect: `import('@widgetic/embed-sdk').then(({ getSDK }) => getSDK())`. The `<widgetic>` tag and its attributes are the same as above. For a page, a CMS or a template where you can add a `<script>` tag, the script from the CDN stays the supported way. It is published separately from the package, so it can be a different build from the version you installed.

### Show a path of compositions in one place

A [workflow](https://widgetic.com/docs/partners/ui-components.md#workflows) chains compositions together, with filters between them. On your page it is still one `<widgetic>` tag: add `workflow-id` to the tag you already use, and keep `composition-id` for the composition a new visitor starts on. The Workflows screen gives you this tag as **Embed code**, in its **Settings**.

```html theme={null}
<widgetic workflow-id="WORKFLOW_ID" composition-id="FIRST_COMPOSITION_ID" resize="fill-width" width="800" embed-target="site"></widgetic>
```

When something happens (the visitor saves an entry, does something in the widget, your page tells the workflow, or a wait is over), the composition on screen is replaced by the next one, in place and without reloading the page. The box the widget sits in grows or shrinks to the height of the next composition: autoscale is always on for a workflow embed, so `autoscale="false"` and `fixed-height` are ignored, and the `autoscale-min-height`, `autoscale-max-height`, `autoscale-debounce`, `autoscale-threshold`, `autoscale-animate` and `autoscale-animation-duration` attributes still apply. A visitor whose device asks for reduced motion gets no animation.

* **The first composition shows as soon as the workflow is read, and never later than two seconds.** The workflow's answer says which language to show it in, so the composition the tag names (or the one a returning visitor was on) is built when the answer is in. If the answer is slower than two seconds, the composition is shown as it is, and swapped for its translation when the answer arrives.
* **Every step is in the visitor's language.** A composition that has translations (copies of it in other languages, made with Widgetic's Translations) is shown in the language of the visitor's browser, the way a translated embed shows it: the first of the visitor's languages that has a copy, in the browser's order (`fr-CA` before `fr`), then a copy in the same language family, and otherwise the composition as it was written. It applies to the composition of every step, not only the first, and each one is judged on its own: a visitor can read the second step in French and the third as it was written when only the second has a French copy. The copies come with the workflow, so a language you add to a translation shows up without publishing the workflow again, and a copy that cannot be shown is replaced by the composition itself. The workflow still names the compositions you put in it: counts, the visitor's place and the tag's events keep their ids, not those of the copies.
* **Every composition takes the tag's look and data.** `width`, `height`, `resize`, the theme attributes and the page's `values`, `context` and `media-resolver` apply to every composition of the workflow, and follow a change you make to them. What you wrote *inside* the tag for one composition (inline `design` and `content` overrides) applies to the composition the tag names, and to no other.
* **When it is not a workflow, it is a plain embed.** If the workflow is paused, does not exist, cannot be read, or does not contain the tag's `composition-id`, the tag shows that composition as any embed does. A workflow never keeps a page from showing something.
* **One tag for a workflow per page.** Two tags with the same `workflow-id` share one position.
* **Where the visitor is.** In their own browser, in `localStorage` under `widgetic_workflow_<workflowId>`: ids and times only, never a value and never who the visitor is. A visitor finishes the version they started on, even when a newer one is published, and after 30 days the position is forgotten and they start again on the latest version.
* **What a visitor types.** The values of an entry a visitor saves, and of an event your page sends, are read by the conditions of a published workflow and then forgotten: they are never stored and never sent back to Widgetic.
* **Counts.** The tag reports how many visitors reached a block, took a line, or could not be moved on, so the **Runs** tab can show them. A report holds ids and numbers only, never a visitor, a value, an address or a page. It is best effort and never delays the page.

**What moves a visitor.** A step starts with one of four triggers: an **input added** (an entry the widget saved), an **action in the widget** (a click, a submit, a play), an **event from your page**, or a **scheduled** wait or date. The first two work only with a widget that can supply them: a widget that keeps what visitors send (a Pro widget) for an input, a widget that reports actions for an action, and a widget published after workflows were added (an older one cannot report either). The editor enables a step only when the composition's widget can supply it, and says why when it cannot. An **event from your page** and a **scheduled** step work with any widget. To send an event from your page:

```javascript theme={null}
import { sendWorkflowEvent } from '@widgetic/embed-sdk';

// Returns true when the event was sent, and false (and nothing happens) when its name or values do not fit.
sendWorkflowEvent(document.querySelector('#signup'), 'checkout-started', { total: 42, member: true });
```

With the script from the CDN, send the same thing as a DOM event on the tag:

```javascript theme={null}
document.querySelector('#signup').dispatchEvent(
  new CustomEvent('widgetic:workflow-event', { detail: { name: 'checkout-started', values: { total: 42, member: true } } }),
);
```

A name, of an event or of a value, is 1 to 64 letters, digits, `_`, `.`, `:` or `-`. An event has up to 12 values, each a text (cut to 200 characters), a number or a yes/no. What does not fit is dropped before the workflow sees it.

**What the tag tells your page.** Besides the usual `widgetic:ready`, `widgetic:error` and `widgetic:submitted` of the composition on screen (their `compositionId` is the translation when the visitor is shown one), the tag fires `widgetic:workflow-step` with `{ workflowId, from, to }` (the ids of the compositions in the workflow, whatever language they are shown in) each time a visitor moves on. If the next composition cannot be shown, or does not appear within 8 seconds, the visitor stays on the one they are on, the tag fires `widgetic:error`, and one more try is made 30 seconds later.

### Show a workflow where you cannot add a tag

Some places take an address or an iframe and no script: a chat messenger, a link page, a site builder, a blog or a notes tool that follows oEmbed. For those, a workflow has a **frame**, as a composition has ([Embed Script](#embed-script)): one page of Widgetic's that holds the tag above with the embed script, so it runs the workflow from its first composition to its last and does what the tag does. Its address is

```text theme={null}
https://api.widgetic.com/embed/workflows/WORKFLOW_ID/frame
```

`WORKFLOW_ID` is the `workflow-id` of the tag that the workflow's **Embed code** gives you. Paste the address where the place asks for one, or put it in an iframe:

```html theme={null}
<iframe src="https://api.widgetic.com/embed/workflows/WORKFLOW_ID/frame" width="800" height="600" title="Widgetic interactive content" frameborder="0" allowfullscreen></iframe>
```

A place that follows oEmbed can ask for the card of the workflow instead, at `https://api.widgetic.com/oembed/workflows/WORKFLOW_ID`. It answers an oEmbed `rich` card in JSON whose `html` is that iframe, 800 by 600 at most: a `maxwidth` or a `maxheight` in the request lowers the size, and never raises it. `json` is the only `format` it gives. The frame page also links to the card in its head, for a place that finds it from the address of the frame. Whether a given place accepts an address it does not already know is that place's own rule.

* **A frame sees less than a page does.** A workflow in a frame moves a visitor on only by what the frame can see itself: the entries the visitor saves, an action in the widget, and waits. An **event from your page** never reaches it, because the events of a page do not cross a frame, so a step that waits for one does not start there. The `widgetic:workflow-step` event of the tag stays in the frame as well. A workflow that depends on events from your page needs the tag on your own page.
* **What the frame shows when there is nothing to run.** A workflow that is paused shows its first composition, as a plain embed. A workflow that is not published, is archived, or does not exist, and a workflow whose owner is no longer being served (a plan that has lapsed, for example), show one short page that says "This workflow is unavailable." with a `404`, and the same words for every reason. When Widgetic cannot read the workflow at that moment, the answer is `503`.
* **It is never kept by a cache.** Whether the frame can be shown depends on the state of the workflow and of its owner, so the answer carries `Cache-Control: no-store`.
* **The websites you list apply.** If you limit the [websites that may show your widgets](https://widgetic.com/resources/security.md#domain-validation), the frame is shown only on the websites that the owner of the workflow's **first composition** listed, and the card answers `403` with `DOMAIN_NOT_ALLOWED` to a website that is not on that list. Later compositions of the workflow are not asked about. Add the address of the place that will show the frame, for example the domain of the link page.
* **There are limits.** The frame and the card count together, for one network address on one workflow and for one workflow as a whole. Past a limit the answer is `429` with a `Retry-After` header.

## UI SDK (Partners)

> [!NOTE]
>
> **Preview.** The UI SDK and the pieces it mounts are new. They are built and tested, and you can try them now, but small details can still change while this label is on.

`@widgetic/ui-sdk` runs in your customer's browser. It downloads a piece (the File Browser, the composition editor, the widget creator or Workflows) from Widgetic's CDN and draws it in your page, inside a shadow root, so your styles and its own do not touch each other. It never holds your API key: your server makes an [editor session](https://widgetic.com/docs/partners/editor-sessions.md) and the page only gets the token (a signed-in person of your own team can use Workflows with their own token instead).

```bash theme={null}
npm install @widgetic/ui-sdk
```

```javascript theme={null}
import { mountModule } from '@widgetic/ui-sdk';

await mountModule('file-browser', {
  container: '#media-library',
  getToken: async () => (await fetch('/widgetic-session', { method: 'POST' })).json(), // { token, expiresAt }
  on: { select: ({ files }) => useFiles(files) },
});
```

See [UI Components](https://widgetic.com/docs/partners/ui-components.md) for the options and events, and [Canvas Embedding](https://widgetic.com/docs/partners/canvas-embedding.md) for the composition editor and the widget creator.

## Multi-Language Code Samples (API Reference)

Our [API Reference](https://widgetic.com/api-reference/introduction.md) includes code samples in **8 languages** for every public endpoint:

| Language | Sample Type |
| - | - |
| **cURL** | HTTP examples |
| **Node.js** | `@widgetic/api-sdk-ts` |
| **Python** | HTTP examples |
| **Go** | HTTP examples |
| **Ruby** | HTTP examples |
| **PHP** | HTTP examples |
| **Java** | HTTP examples |
| **C#** | HTTP examples |

These samples are maintained to stay in sync with the public API surface.

> [!NOTE]
>
> Want an official SDK published for your language (PyPI, Maven, NuGet, RubyGems, Packagist, etc.)?
> Tell us your target registry and preferred package name/versioning.

## Need Help?

* [API Reference](https://widgetic.com/api-reference/introduction.md)
* [Code Examples](https://widgetic.com/resources/examples.md)
* [GitHub Issues](https://github.com/widgetic/issues)


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