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

# Code Examples

> Example code for common Widgetic integrations

This page provides practical code examples for common integration scenarios. Run them on your server: a key in a browser page can be read by every visitor.

## Quick Start

### Initialize the SDK

```typescript theme={null}
import { 
  WidgetsApi, 
  CompositionsApi, 
  CanvasesApi 
} from '@widgetic/api-sdk-ts';

// Initialize with API key
const widgets = new WidgetsApi(process.env.WIDGETIC_API_KEY);
const compositions = new CompositionsApi(process.env.WIDGETIC_API_KEY);
const canvases = new CanvasesApi(process.env.WIDGETIC_API_KEY);
```

### Using Async Token Provider

For short-lived tokens that rotate (see [Authentication](https://widgetic.com/docs/authentication.md) for token exchange):

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

const widgets = new WidgetsApi({
  accessToken: async () => {
    // Fetch a fresh short-lived token from your backend, which makes it with token exchange
    const response = await fetch('/api/widgetic-token');
    const { token } = await response.json();
    return token;
  }
});
```

## Fetching Data

### List Every Widget with Pagination

`GET /widgets` takes `page` and `size`, and is always newest first. `meta.hasNextPage` says whether to ask for another page:

```typescript theme={null}
async function listEveryWidget() {
  const allWidgets = [];
  let page = 1;
  let hasMore = true;

  while (hasMore) {
    const { data, meta } = await widgets.getWidgets({ page, size: 100 });

    allWidgets.push(...(data ?? []));
    hasMore = (meta as { hasNextPage?: boolean } | null)?.hasNextPage ?? false;
    page++;
  }

  return allWidgets;
}
```

### Batch Fetch Multiple Widgets

```typescript theme={null}
const widgetIds = [
  '123e4567-e89b-12d3-a456-426614174000',
  '223e4567-e89b-12d3-a456-426614174001',
  '323e4567-e89b-12d3-a456-426614174002'
];

// A widget that cannot be returned comes back in `errors`, with the reason
const { widgets: batchedWidgets, errors } = await widgets.getWidgetsBatch({
  getWidgetsBatchRequest: { widgetIds }
});
```

## Managing Canvases

### Create and Update a Canvas

```typescript theme={null}
// Create a new canvas
const canvas = await canvases.createCanvas({
  createCanvasRequest: {
    persistenceKey: `project_${projectId}_canvas_${Date.now()}`,
    canvasContent: {
      version: 1,
      elements: [],
      settings: {
        background: '#ffffff',
        gridSize: 10
      }
    }
  }
});

console.log('Created canvas:', canvas.id);

// Update the canvas
const updated = await canvases.updateCanvas({
  id: canvas.id,
  updateCanvasRequest: {
    canvasContent: {
      version: 2,
      elements: [
        {
          id: 'text-1',
          type: 'text',
          content: 'Hello World',
          position: { x: 100, y: 100 }
        }
      ],
      settings: {
        background: '#f5f5f5',
        gridSize: 10
      }
    }
  }
});
```

## Partner Integration

### Create Managed Users

A managed user is a record of one of your customers. It is not a login, and it does not own anything. See [Managed Users](https://widgetic.com/docs/partners/managed-users.md).

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

const managedUsers = new ManagedUsersApi(process.env.WIDGETIC_PARTNER_KEY);

// Create a managed user for your customer. Leave manager_id out: it defaults to you.
// The API needs an Idempotency-Key header: send it as idempotencyKey in the request object.
const user = await managedUsers.createManagedUser({
  // Reuse the same key when you retry this call
  idempotencyKey: randomUUID(),
  newManagedUser: {
    external_id: `myapp_user_${customerId}`,
    metadata: {
      firstName: customer.firstName,
      lastName: customer.lastName,
      email: customer.email,
      plan: customer.subscriptionPlan
    }
  }
});

// Store the mapping
await db.widgeticUsers.create({
  customerId,
  widgeticUserId: user.id
});
```

To keep each customer's work apart, send `managedUserId` (or your own id as `managedUserExternalId`) when you create a composition, a widget or an upload, and send the same field when you list. See [Filing Content Under a Managed User](https://widgetic.com/docs/partners/managed-users.md#filing-content-under-a-managed-user).

### Mount an Editor in Your Page

> [!NOTE]
>
> **Preview.** The editors are new, and small details can still change while this label is on. See [UI Components](https://widgetic.com/docs/partners/ui-components.md).

Your server makes an [editor session](https://widgetic.com/docs/partners/editor-sessions.md) for the customer who is on the page, and the page mounts the editor with the token. The API key stays on your server.

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

const managedUsers = new ManagedUsersApi(process.env.WIDGETIC_PARTNER_KEY);

// On your server, when the page that holds the editor opens for one of your customers.
const session = await managedUsers.createManagedUserEditorSession({
  id: widgeticUserId,
  newEditorSession: {
    surfaces: ['editor', 'files'],
    expires_in_seconds: 3600,
    allowed_origin: 'https://app.example.com'
  }
});

// Send session.token to that customer's browser, and nothing else of yours.
```

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

// In your page. /widgetic-session is the endpoint of yours that makes the session and returns { token, expiresAt }.
const editor = await mountModule('composition-editor', {
  container: '#editor',
  compositionId, // a composition your server made with managedUserId set to this customer
  getToken: async () => (await fetch('/widgetic-session', { method: 'POST' })).json()
});
```

## Error Handling

### Robust API Client

The SDK throws a `ResponseError`. The HTTP status is `error.response.status`, and `error.code` holds the machine-readable code from the API's answer:

```typescript theme={null}
import { CompositionsApi, ResponseError } from '@widgetic/api-sdk-ts';

class WidgeticClient {
  private compositions: CompositionsApi;
  
  constructor(apiKey: string) {
    this.compositions = new CompositionsApi(apiKey);
  }

  async getComposition(id: string, attempt = 1) {
    try {
      const { data } = await this.compositions.getCompositionById({ id });
      return data;
    } catch (error) {
      if (!(error instanceof ResponseError)) {
        throw error;
      }
      const status = error.response.status;
      if (status === 404) {
        return null; // Composition not found
      }
      if (status === 401) {
        throw new Error('Invalid API key');
      }
      if (status === 429 && attempt < 4) {
        // Wait for as long as the API asks, then try again
        const retryAfterSeconds = Number(error.response.headers.get('retry-after')) || 5 * attempt;
        await this.sleep(retryAfterSeconds * 1000);
        return this.getComposition(id, attempt + 1);
      }
      throw error;
    }
  }

  private sleep(ms: number) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }
}
```

## Embedding Widgets

A widget is shown on a page through a composition, and the page needs only the composition id. There is no key in the page.

### Basic Embed

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

### Embed as a Pop-up

`embed-target` decides where the widget appears: `site` inside the page, `overlay` as a pop-up, and `mixed` both. The overlay is the default. These attributes come from the composition's `embedSettings`, so build them from the saved settings (see [Compositions](https://widgetic.com/docs/api/compositions.md#embedding-compositions)):

```html theme={null}
<script src="https://cdn.widgetic.com/sdks/browser/embed-sdk.js?v=6"></script>
<widgetic composition-id="YOUR_COMPOSITION_ID" resize="fill-width" width="800" height="450" autoscale="on" adaptive="480" embed-target="overlay" overlay="enabled" overlay-position="center-center" event-trigger="exit-intent" overlay-backdrop="false"></widgetic>
```

## Next Steps

> [card] [SDKs](https://widgetic.com/resources/sdks.md)
>
> Explore our SDK options

> [card] [API Reference](https://widgetic.com/api-reference/introduction.md)
>
> Complete endpoint documentation


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