# How to use the Extensions SDK package

## Getting started

To work with app integration in Struct PIM you will need to install the extension SDK package in your project. This is required to establish a connection with the PIM:

```bash
npm install @structdk/extension-sdk
```

From here you need to create an SDK instance in order to use the package to connect with the PIM:

```typescript
import { createStructSDK } from '@structdk/extension-sdk';

const struct = createStructSDK({ hostOrigin: 'https://your-struct-instance.struct.com' });
```

Optionally you can pass the `hostOrigin` of your Struct PIM instance to restrict message acceptance to that origin only.

{% hint style="warning" %}
If `hostOrigin` is not provided, all origins are accepted and a warning is printed to the console.
{% endhint %}

With this package intalled and instance created, your app is now able to retrieve context from the PIM as well as send and receive messages via actions and events.

## Actions (struct.actions)

The app will be communicating with the PIM through a message API. The extension SDK package includes objects used to manage the messaging functionlity in the app. Below are some coding examples mentioned in the [npm package documentation](https://www.npmjs.com/package/@structdk/extension-sdk).

### Accessing context (getContext)

In order to get current context from Struct PIM you will need to use the function `getContext`. Returns a promise that resolves with the context payload for the current extension point. This is the primary way to retrieve the session context (slug, language, user, entity info, etc.):

```typescript
import { createStructSDK } from '@structdk/extension-sdk';
import type { TabContextPayload } from '@structdk/extension-sdk';

const struct = createStructSDK();
const ctx = await struct.actions.getContext<TabContextPayload>();
console.log('Entity:', ctx.entityType, ctx.entityId);
console.log('Slug:', ctx.slug);
```

The payload type returned depends on the entension point type and some types have extra fields.

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

### Opening a modal (openModal)

You can render external or local content inside the Struct PIM UI by opening a modal. The modal loads a given URL inside an iframe:

```typescript
struct.actions.openModal({
  id: 'my-modal',
  url: 'https://your-extension.example.com/modal',
  placement: 'center', // 'center' | 'left' | 'right'
  size: 'medium',      // 'small' | 'medium' | 'large'
});
```

#### Parameters

* **`id`**: A unique identifier for the modal. This is required to reference the modal.
* **`url`**: The URL that will be loaded inside the modal iframe.
* **`placement`**: Controls where the modal appears in the UI.
* **`size`**: Controls the size of the modal.

### Closing a modal (closeModal)

To close a modal, use the following action:

```typescript
struct.actions.closeModal({ id: 'my-modal' });
```

### Closing a dialog (clostHostContainer)

In exporter and searchAction extension points you can dismiss the dialog window with the following:

```typescript
struct.actions.closeHostContainer();
```

{% hint style="warning" %}
This closes the the host dialog that contains the extension iframe itself.
{% endhint %}

### Display a message notification (showSnackbarMessage)

Show a temporary notification (snackbar) to the user. This can be useful for quick feedback on user action such as save:

```typescript
struct.actions.showSnackbarMessage({
    message: 'Hello World clicked!',
    placement: 'top',    // 'top' | 'bottom'
    isError: false,
    durationMs: 3000,    // optional
});
```

#### Parameters

* **`message`**: The text that should be displayed in the message.
* **`placement`**: The placement of the message.
* **`isError`**: Define if the message should be shown as an error.
* **`durationMs`**: How long the message should be displayed.

### Resizing the container (resizeContainer)

For Tab, Section, Property and Sidebar Widget extentions you can use the `resizeContainer` action to manually set the height of the iframe container in pixels:

```typescript
struct.actions.resizeContainer({ height: 400 });
```

### Enable auto resizing of container (enableAutoResize)

EnableAutoResize uses a ReziseObserver which allows for the iframe to automatically adjust the iframe height based on content. This action it suppored on Tab, Section, Property, and Sidebar Widget extension points. Only one auto-resize observer can be active at a time:

```typescript
struct.actions.enableAutoResize({
  maxHeight: 800,    // optional — cap the height
  debounceMs: 200,   // optional — debounce delay (default 100ms)
});
```

#### Parameters

* `maxHeight`: Sets a cap to the height of the container.
* `debounceMs`: Delays the resizing of the container.

## Events (struct.events)

Events allow your app to react to changes happening in Struct PIM. Each event listener returns an unsubscribe function.

### Changes to entity (onEntityChangedEvent)

Fired whenever the entity the extension is associated with is saved/updated. Relevant for tab, section, sidebar widget, and property extension points:

```typescript
const unsubscribe = struct.events.onEntityChangedEvent((payload) => {
    console.log(payload.entityType, 'with id', payload.entityId, 'changed');
});
```

### Change in language (onLanguageChangedEvent)

Fired whenever the user switches the active language in Struct PIM. Use this to re-fetch localized data or update the UI:

```typescript
struct.events.onLanguageChangedEvent((payload) => {
    console.log('Language changed to:', payload.currentLanguage);
});
```

### Change in segment (onSegmentChangedEvent)

Fired whenever the active segment selection changes in Struct PIM:

```typescript
struct.events.onSegmentChangedEvent((payload) => {
    console.log('Segments changed:', payload.currentSegments);
});
```

### Handle rejected actions (onActionRejectedEvent)

Fired when the host rejects an action (e.g., a resize on an unsupported extension point):

```typescript
struct.events.onActionRejectedEvent((payload) => {
    console.warn(`Action rejected: ${payload.rejectedAction} — ${payload.reason}`);
});
```

## Cleanup

Call `destroy()` to unsubscribe all event listeners and stop any active auto-resize observer:

```typescript
struct.destroy();
```

## Versioning

The SDK version is available at runtime via `ExtensionSdkVersion`:

```typescript
import { ExtensionSdkVersion } from '@structdk/extension-sdk';

console.log('SDK version:', ExtensionSdkVersion);
```

## Package

More info and the package can be found here:

<https://www.npmjs.com/package/@structdk/extension-sdk>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.struct.com/developer/app-integration/how-to-use-the-extensions-sdk-package.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
