---
metadata:
  - name: generator
    content: Diplodoc Platform v5.52.0
  - property: og:type
    content: article
  - property: article:section
    content: Платформа плагинов
  - property: og:title
    content: API Reference - plugin-sdk-core
  - property: article:tag
    content: Техническая инструкция
alternate:
  - https://yandex.ru/support/tracker/en/plugins/tools/sdk/core.md
  - https://yandex.ru/support/tracker/ru/plugins/tools/sdk/core.md
  - href: en/plugins/tools/sdk/core.md
    type: text/markdown
    title: Markdown version
  - href: ../../../llms.txt
    type: text/markdown
    title: llms.txt
---
> **Documentation Index:** Fetch the complete configuration index at https://yandex.ru/support/tracker/en/llms.txt


# API Reference - @yandex-data-ui/tracker-plugin-sdk-core

## hostApi (HostApi)

API for interacting with the host (Tracker): plugin initialization, theme, language, slot context, window size, and readiness notification.

Exports the **`hostApi`** singleton. Usually used inside `TrackerPluginProvider` (react package); you can call it directly if needed.

### init()

Initializes the plugin (reads parameters from the URL, initializes the bridge, and performs auto-resize if necessary). Call once before using other methods.

**Parameters:** `options?: HostInitOptions` — options (for example `autoResize`, defaults to `true`).

**Throws:** `Error` — if the URL lacks required parameters (slot, parentOrigin, id, elementId).

```typescript
import { hostApi } from "@yandex-data-ui/tracker-plugin-sdk-core";

hostApi.init({ autoResize: true });
```

### getTheme()

Returns the host's current theme.

**Returns:** `Promise<Theme>`

```typescript
const theme = await hostApi.getTheme(); // 'light' | 'light-hc' | 'dark' | 'dark-hc' | 'system'
```

### getLanguage()

Returns the host's current language.

**Returns:** `Promise<string>` (for example `'ru'`, `'en'`).

```typescript
const language = await hostApi.getLanguage();
```

### getContext()

Returns the context of the slot where the plugin is running. The level of returned data is determined by the `contextLevel` parameter specified for the slot in `manifest.json` (see [Slot context levels](https://yandex.ru/support/tracker/en/plugins/common.md#context-levels)).

**Parameters:** `level: 'basic' | 'full'` (required)

**Returns:**

- For `level: 'basic'` — `Promise<BasicContext>`, where `BasicContext = { entityId: string; entityMeta?: Record<string, string> }`
- For `level: 'full'` — `Promise<SlotContextMap[TSlot]>`

```typescript
// Basic context (only entity identifier)
// Requires contextLevel: 'basic' in manifest.json for this slot
const basicContext = await hostApi.getContext("basic");
// basicContext.entityId — identifier of the current entity
// basicContext.entityMeta — additional metadata (optional)

// Full context (all entity data)
// Requires contextLevel: 'full' in manifest.json for this slot
const fullContext = await hostApi.getContext("full");
```

### updateContentSize()

Sends a request to the host to change the plugin window size.

**Parameters:** `payload: ContentSizeUpdateRequest` (fields `height` and `width` — at least one must be present).

**Returns:** `Promise<…>`

```typescript
await hostApi.updateContentSize({ height: 500 }); // sets the plugin window height
await hostApi.updateContentSize({ width: 800 }); // sets the plugin window width
await hostApi.updateContentSize({ height: 500, width: 800 }); // sets the plugin window height and width
```

The plugin window width is applied considering the embedding space constraints.

### notifyReady() {#notifyReady}

Notifies the host that the plugin is ready.

**Returns:** `Promise<…>`

```typescript
await hostApi.notifyReady();
```

### getSlot()

Returns the current slot. Call only after `init()`.

**Returns:** `TSlot` (key from SlotContextMap).

```typescript
const slot = hostApi.getSlot(); // for example 'issue.action'
```

### disableAutoResize()

Disables automatic container resizing based on content.

```typescript
hostApi.disableAutoResize();
```

### close()

Closes the plugin if it's displayed in a popup window.

```typescript
hostApi.close();
```

{% note info "Data transfer" %}

Some slots support processing data that will be passed as an argument to the `close` method.
See the documentation for [specific integration points](https://yandex.ru/support/tracker/en/plugins/slots/attachment-viewer-action.md) for exact types and functionality.

{% endnote %}

### preventClose() {{#preventClose}}

Protects the plugin from accidental closure by the user, for example, by pressing Esc or clicking the close button. If the `preventClose: true` flag is set, the host will block closure until the flag is cleared. Only works with plugins displayed in a modal window.

Use this method to prevent the loss of unsaved changes.

```typescript
import { hostApi } from "@yandex-data-ui/tracker-plugin-sdk-core";

// Block closure if there are unsaved changes
hostApi.preventClose({ preventClose: true });
```

**Parameters:** `{ preventClose: boolean }`

- `preventClose: true` — blocks the plugin from being closed by the user
- `preventClose: false` — removes the block

**Example usage with React:**

```tsx
import { hostApi } from "@yandex-data-ui/tracker-plugin-sdk-react";
import { useEffect, useState } from "react";

function MyEditor() {
    const [content, setContent] = useState("");
    const [saved, setSaved] = useState(true);

    const hasChanges = !saved;

    // Automatically set/remove the block when the state changes
    useEffect(() => {
        hostApi.preventClose({ preventClose: hasChanges });
    }, [hasChanges]);

    const handleSave = async () => {
        await saveContent(content);
        setSaved(true);
    };

    return (
        <div>
            <textarea
                value={content}
                onChange={(e) => {
                    setContent(e.target.value);
                    setSaved(false);
                }}
            />
            <button onClick={handleSave}>Save</button>
        </div>
    );
}
```

{% note info "Important" %}

- Remember to remove the block (`preventClose: false`) after saving data, otherwise the user won't be able to close the plugin.
- During forced closure (for example, navigating to another screen) the host may ignore the block.

{% endnote %}

## uiApi

API for interacting with the host application's user interface: showing notifications, opening pop-ups, etc.

### Toasts {#toasts}

Plugins can show toast notifications in the host application via `uiApi.toaster`. The API closely resembles `useToaster` from `@gravity-ui/uikit`.

{% note info "Permission" %}

The `tracker:ui:toaster` permission must be requested in `manifest.json`:

```json
{
    "permissions": {
        "ui": ["toaster"]
    }
}
```

{% endnote %}

```typescript
import { uiApi } from "@yandex-data-ui/tracker-plugin-sdk-core";

// Simple toast
uiApi.toaster.add({
    title: "Saved",
    theme: "success",
});

// Toast with text content and custom display time
uiApi.toaster.add({
    title: "Error",
    theme: "danger",
    content: "Failed to load data",
    autoHiding: 10000,
});

// Toast with an action button
uiApi.toaster.add({
    title: "Item deleted",
    theme: "info",
    content: "QUEUE-123",
    actions: [
        {
            label: "Undo",
            onClick: () => {
                // handle click
            },
        },
    ],
});
```

#### Parameters

| Parameter     | Type                                            | Default      | Description                                                                       |
| ------------ | ---------------------------------------------- | ------------ | ----------------------------------------------------------------------------- |
| `title`      | `string`                                       | —            | Toast title (required)                                                          |
| `name`       | `string`                                       | auto         | Unique key for deduplication. Generated automatically if not provided           |
| `theme`      | `'success' \| 'danger' \| 'warning' \| 'info'` | `'info'`     | Theme (color and icon)                                                         |
| `content`    | `string`                                       | —            | Text content below the title                                                    |
| `autoHiding` | `number`                                       | `5000`       | Display time in ms (from 1000 to 30000)                                         |
| `isClosable` | `boolean`                                      | `true`       | Show close button                                                               |
| `actions`    | `ToastAction[]`                                | —            | Action buttons (max. 2)                                                         |

**`ToastAction`:**

| Parameter | Type          | Description                          |
| --------- | ------------ | -------------------------------- |
| `label`   | `string`     | Button text (max. 50 characters)     |
| `onClick` | `() => void` | Callback on click                    |

**Returns:** `Promise<{ name: string }>` — toast name (for identification).

**Limitations:**

- `title` — max. 200 characters
- `content` — max. 500 characters
- `actions` — max. 2 buttons
- Rate limit — 5 toasts per 10 seconds per plugin

### Error handling

```typescript
import {
    trackerApi,
    PluginActionError,
} from "@yandex-data-ui/tracker-plugin-sdk-core";

try {
    await trackerApi.v3.get["/issues/{id}"]({ pathParams: { id: "BAD" } });
} catch (e) {
    if (e instanceof PluginActionError) {
        console.log(e.code, e.message, e.errorData);
    }
}
```

### Confirm Dialog {#confirm}

A plugin can show a modal confirmation dialog. The dialog is rendered **on the Tracker side** (not inside the iframe), so it overlays the entire application and focuses the user on making a decision.

{% note info "Permission" %}

The `tracker:ui:confirm` permission must be requested in `manifest.json`:

```json
{
    "permissions": {
        "ui": ["confirm"]
    }
}
```

{% endnote %}

```ts
import { uiApi } from "@yandex-data-ui/tracker-plugin-sdk-core";

const { confirmed } = await uiApi.confirm.show({ message: "Are you sure?" });
```

#### Parameters

| Parameter           | Type                    | Limit | Default         | Description                    |
| ------------------ | ---------------------- | ----- | --------------- | -------------------------- |
| `title`            | `string`               | ≤ 200 | —               | Dialog title                  |
| `message`          | `string`               | ≤ 500 | — (required)     | Confirmation text             |
| `textButtonApply`  | `string`               | ≤ 50  | `"OK"`          | Confirm button text           |
| `textButtonCancel` | `string`               | ≤ 50  | `"Cancel"`      | Cancel button text            |
| `theme`            | `'normal' \| 'danger'` | —     | `'normal'`      | Theme for the apply button    |

#### Limits and errors

- **1 active confirm per plugin.** Attempting to open a second dialog while the first is active rejects the promise with `CONFIRM_ALREADY_OPEN`.
- **Maximum 5 simultaneous dialogs in the shared queue** (from all plugins). If the queue overflows — `QUEUE_OVERFLOW`.
- **5-minute timeout.** If the user doesn't respond, the promise is rejected with `Request timeout`.
- **Closing the plugin iframe** (removing it from the screen) automatically resolves all pending confirm dialogs for that plugin as `{ confirmed: false }`.
- **Esc / clicking the close button** — `{ confirmed: false }`.

### Navigation {#navigate}

Programmatically open links

```typescript
uiApi.navigate({
    path: `/path`,
    params: { a: "testParam" },
    options: { newTab: true },
});
```

```typescript
type NavigateRequest = {
    path: string;
    params?: QueryParams;
    options?: {
        newTab?: boolean;
    };
};
```

{% note info "Handling link clicks" %}

1. Relative links and links to the plugin domain =\> open in the plugin

2. External links =\> are passed to Tracker via uiApi.navigate =\>

    links to Tracker =\> open in the current tab or a new tab depending on target="\_blank"
    external links =\> always open in a new tab

{% endnote %}

## trackerApi (TrackerApi)

A class for calling the Tracker Public API via the host (contract `api.tracker.call`). Access to endpoints is through the typed **v3** API.

For method descriptions and response formats, see: [Common format](https://yandex.ru/support/tracker/en/api-ref/common-format.md).

Exports the **`trackerApi`** singleton.

### v3

An object with HTTP methods: `get`, `post`, `put`, `patch`, `delete`. Keys are endpoint paths from OpenAPI (`@yandex-data-ui/tracker-pub-api-types`); when accessing a path, the IDE shows hints and JSDoc.

**Examples:**

```typescript
import { trackerApi } from "@yandex-data-ui/tracker-plugin-sdk-core";

// GET
const data = await trackerApi.v3.get["/issues/{id}"]({
    pathParams: { id: "QUEUE-123" },
    queryParams: { expand: ["COMMENTS"] },
});

// POST
await trackerApi.v3.post["/v2/issues"]({
    bodyParams: { queue: { key: "TASK" }, summary: "New issue" },
});

//POST with file
await trackerApi.v3.post["/attachments"]({
    bodyParams: { filename },
    file,
});
```

- **`v3.get[path](payload)`** — GET; `payload`: `pathParams`, optionally `queryParams`.
- **`v3.post[path](payload)`** / **put** / **patch** — `payload` includes `bodyParams` (and if necessary `pathParams`, `queryParams`).
- **`v3.delete[path](payload)`** — DELETE; `payload`: `pathParams`, optionally `queryParams`.

All requests via `trackerApi.v3` send **version: 'v3'** in the contract.

---

## storageApi {#storageApi}

A JSON storage at the organization level, mediated by the host — `storageApi.orgShared.get` / `storageApi.orgShared.patch`. A full description of the methods, `patch` merge semantics, versioning, and error codes is in the [Data storage](https://yandex.ru/support/tracker/en/plugins/storage.md) section.

```typescript
import { storageApi } from "@yandex-data-ui/tracker-plugin-sdk-core";

const record = await storageApi.orgShared.get("settings");
await storageApi.orgShared.patch({
    bucket: "settings",
    data: { theme: "dark" },
});
```

---

## hostApi.externalApi\* {#externalApi}

Methods for calling external (non-Tracker) HTTP APIs through the host's proxy with OAuth authorization support.

> **⚠️ Security policy:** direct HTTP requests from the plugin (`fetch`, `XMLHttpRequest`, etc.) are **forbidden** — the browser will block them due to CSP and iframe policy. All calls to external APIs **must** go through `hostApi.externalApiCall()`.

{% note info "Manifest permission" %}

Add the `permissions.external` section to `manifest.json` with a list of allowed domains:

```json
{
    "permissions": {
        "external": [
            {
                "domain": "api.example.com",
                "authorization": {
                    "type": "oauth",
                    "scopes": ["read", "write"],
                    "contextTypes": ["user"]
                }
            },
            {
                "domain": "cdn.example.com"
            }
        ]
    }
}
```

The `authorization` field is optional — you can omit it for domains that don't require authorization (for example, public CDNs). The `"token"` type is used for API keys and other non-OAuth tokens.

{% endnote %}

{% note warning "Network access (Puncher)" %}

Proxy requests are executed from the platform servers. To ensure requests reach your service, request network access in [Puncher](https://puncher.yandex-team.ru/) from the macro **`_STARTREK_PLUGINS_PLATFORM_PRODUCTION_NETS_`** to your services.

{% endnote %}

### externalApiCall() {#external-api-call}

Executes an HTTP request to an external API through the platform proxy. The URL must belong to a domain allowed in `permissions.external`; the host adds authorization headers.

**Parameters:**

| Parameter     | Type                                               | Default      | Description                           |
| ------------- | ------------------------------------------------- | ------------ | ---------------------------------- |
| `url`         | `string`                                          | —            | Full request URL (required)          |
| `method`      | `'GET' \| 'POST' \| 'PUT' \| 'PATCH' \| 'DELETE'` | —            | HTTP method (required)               |
| `headers`     | `Record<string, string>`                          | —            | Additional headers                   |
| `body`        | `Record<string, unknown>`                         | —            | Request body                         |
| `timeoutMs`   | `number`                                          | —            | Request timeout in milliseconds      |
| `contextType` | `'user' \| 'organization'`                        | —            | Credential context for the proxy     |

**Returns:** `Promise<{ status: number; headers?: Record<string, string>; body?: Record<string, unknown> }>`

If the proxy request fails, throws `PluginActionError` with code `EXTERNAL_API_CALL_ERROR` (`1013`); details are in `e.errorData`.

```typescript
import {
    hostApi,
    PluginActionError,
    EXTERNAL_API_CALL_ERROR,
} from "@yandex-data-ui/tracker-plugin-sdk-core";

// GET
const { status, body } = await hostApi.externalApiCall({
    url: "https://api.example.com/v1/items",
    method: "GET",
    contextType: "user",
});

// POST with body and timeout
const result = await hostApi.externalApiCall({
    url: "https://api.example.com/v1/items",
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: { name: "New item", value: 42 },
    contextType: "organization",
    timeoutMs: 10000,
});

// Error handling
try {
    await hostApi.externalApiCall({
        url: "https://api.example.com/data",
        method: "GET",
    });
} catch (e) {
    if (e instanceof PluginActionError && e.code === EXTERNAL_API_CALL_ERROR) {
        console.error("Proxy error:", e.errorData);
    }
}
```

### externalApiAuthCheckAndRequest()

Combines checking the authorization status and requesting credentials only for unauthenticated domains. If all domains are already authenticated — immediately returns `{ success: true }` without a dialog.

**Parameters:**

| Parameter     | Type                        | Default               | Description                     |
| ------------- | -------------------------- | ------------------ | ---------------------------- |
| `domains`     | `string[]`                 | all plugin domains  | Domains to check              |
| `contextType` | `'user' \| 'organization'` | —                  | Credential context type       |

**Returns:** `Promise<{ success: boolean }>` — `false` if the user closed the dialog or the timeout expired (~5 minutes).

```typescript
const { success } = await hostApi.externalApiAuthCheckAndRequest({
    domains: ["api.example.com"],
    contextType: "user",
});
if (!success) return;
```

### externalApiAuthGetStatus()

Returns the authorization status for domains.

**Parameters:**

| Parameter     | Type                        | Default               | Description                     |
| ------------- | -------------------------- | ------------------ | ---------------------------- |
| `domains`     | `string[]`                 | all plugin domains  | Domains to check              |
| `contextType` | `'user' \| 'organization'` | —                  | Credential context type       |

**Returns:** `Promise<{ domains: Array<{ domain: string; contextType: AuthContextType; authenticated: boolean }> }>`

```typescript
const { domains } = await hostApi.externalApiAuthGetStatus({
    domains: ["api.example.com"],
    contextType: "user",
});
const isAuthed = domains.every((d) => d.authenticated);
```

### externalApiAuthRequest()

Shows the user a dialog for entering credentials for the specified domains. If confirmed successfully, the host saves the credentials.

**Parameters:**

| Parameter  | Type                       | Default      | Description                           |
| --------- | ------------------------- | ------------ | ---------------------------------- |
| `domains` | `ExternalApiDomainInfo[]` | —            | Domains (required, at least one)    |

`ExternalApiDomainInfo`:

| Field          | Type                                      | Description                          |
| -------------- | ---------------------------------------- | --------------------------------- |
| `domain`       | `string`                                 | Domain from the manifest           |
| `instructions` | `string \| { en?: string; ru?: string }` | Hint in the dialog (optional)      |

**Returns:** `Promise<{ success: boolean }>` — `false` if the user closed the dialog.

```typescript
await hostApi.externalApiAuthRequest({
    domains: [
        {
            domain: "api.example.com",
            instructions: { ru: "Войдите в Example", en: "Sign in to Example" },
        },
    ],
});
```

### externalApiAuthRevoke()

Revokes the saved authorization for the specified domains.

**Parameters:**

| Parameter     | Type                        | Default      | Description                                      |
| ------------- | -------------------------- | ------------ | --------------------------------------------- |
| `domains`     | `string[]`                 | —            | Domains to revoke (required, at least one)     |
| `contextType` | `'user' \| 'organization'` | —            | Credential context type                        |

**Returns:** `Promise<{ success: boolean }>`

```typescript
await hostApi.externalApiAuthRevoke({
    domains: ["api.example.com"],
    contextType: "user",
});
```

---

## Types

### TrackerApiInitOptions

Options for creating a TrackerApi instance (if not using the singleton). Currently, only `trackerApi` is exported from core, and no options are passed.

```typescript
interface TrackerApiInitOptions {
    apiVersion?: string;
}
```

---

### TrackerApiCallOptions

Parameters for calling a v3 endpoint: `pathParams`, `queryParams`, `bodyParams`.

```typescript
interface TrackerApiCallOptions {
    pathParams?: Record<string, string>;
    queryParams?: Record<string, unknown>;
    bodyParams?: Record<string, unknown>;
}
```

---

### TrackerApiV3

Type of the `trackerApi.v3` object: get/post/put/patch/delete methods with typed paths (from `@yandex-data-ui/tracker-pub-api-types`).

---

### Theme

Host theme type.

```typescript
type Theme = "light" | "light-hc" | "dark" | "dark-hc" | "system";
```

---

### SlotContextMap

Mapping of slot names to **full** context types (`level: 'full'`). For example, the `issue.action` slot provides a context of type `Issue`. Context types (Issue, etc.) are defined by the `@yandex-data-ui/tracker-pub-api-types` package.

When `level: 'basic'`, instead of the full entity object, `BasicContext` is returned:

```typescript
type BasicContext = {
    /** Identifier of the current entity */
    entityId: string;
    /** Additional basic information.
     *  For example, for a comment, it contains the parent ticket identifier. */
    entityMeta?: Record<string, string>;
};
```

```typescript
// Basic context: only entityId and entityMeta
const basicContext = await hostApi.getContext("basic");
// basicContext.entityId — entity identifier

// Full context: for the 'issue.action' slot, returns Issue
// Requires contextLevel: 'full' in manifest.json
const fullContext = await hostApi.getContext("full");
```

---

### ContentSizeUpdateRequest

Request to change the plugin content size.

```typescript
type ContentSizeUpdateRequest = { height?: number };
```

---

### HostInitOptions

Host initialization options (passed to `hostApi.init()`).

```typescript
interface HostInitOptions {
    /** Auto-resize based on content, defaults to true */
    autoResize?: boolean;
}
```

---

## API error codes {#codeErrors}

When calling methods, the host may return an error with a code. Constants are exported from the package:

```typescript
import {
    EXTERNAL_API_CALL_ERROR,
    METHOD_NOT_SUPPORTED,
    MISSING_REQUIRED_SCOPE,
    PLUGIN_ID_IS_NOT_CORRECT,
    PLUGIN_ID_OR_SLOT_NOT_PROVIDED,
    UNKNOWN_ERROR,
    VALIDATION_ERROR,
} from "@yandex-data-ui/tracker-plugin-sdk-core";
```

| Constant                        | Code | Description                                                              |
| ------------------------------- | ---- | ------------------------------------------------------------------------ |
| `PLUGIN_ID_OR_SLOT_NOT_PROVIDED` | 1000 | Required plugin initialization parameters are missing.                   |
| `PLUGIN_ID_IS_NOT_CORRECT`       | 1001 | Incorrect or mismatched pluginId.                                        |
| `VALIDATION_ERROR`               | 1002 | Request validation error.                                                |
| `METHOD_NOT_SUPPORTED`           | 1003 | Method is not supported.                                                 |
| `MISSING_REQUIRED_SCOPE`         | 1004 | Insufficient permissions (scope).                                        |
| `EXTERNAL_API_CALL_ERROR`        | 1013 | Error occurred while executing an HTTP request via `hostApi.externalApiCall()`. |
| `UNKNOWN_ERROR`                  | 6666 | Unknown error.                                                           |

---

## Utils

### getLocalizedString()

Returns a localized string based on the language code. The `LocalizedString` type is exported from `@yandex-data-ui/tracker-pub-api-types` and re-exported from core.

```typescript
function getLocalizedString(
    value: LocalizedString,
    language: string,
    fallbackLanguage?: string,
): string;
```

### getField()

Extracts a value from an object using a dot notation path.

```typescript
function getField<T = unknown>(
    obj: Record<string, unknown>,
    path: string,
    defaultValue?: T,
): T | undefined;
```

---

## Handlers

**getHandler**, **setHandler**, types **HandlerFunction**, **Handlers**, **HttpMethod** are exported — for registering request handlers from the host side (see the contract and slots).

---

## Complete Example

```typescript
import {
    hostApi,
    trackerApi,
    getField,
    type Theme,
} from "@yandex-data-ui/tracker-plugin-sdk-core";

// Initialization is typically done in TrackerPluginProvider (react)
hostApi.init({ autoResize: true });

const theme: Theme = await hostApi.getTheme();
const language = await hostApi.getLanguage();
const context = await hostApi.getContext();

// Calling Tracker API v3 (version: 'v3' is sent in the payload)
const issue = await trackerApi.v3.get["/issues/{id}"]({
    pathParams: { id: "KEY-1" },
    queryParams: { expand: ["COMMENTS"] },
});

const summary = getField<string>(issue, "summary", "No summary");

await hostApi.notifyReady();
```

Request/response types for endpoints (Issue, types for creating issues, queues, etc.) are defined by the **@yandex-data-ui/tracker-pub-api-types** package.

```
