---
metadata:
  - name: generator
    content: Diplodoc Platform v5.66.1
  - 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: https://yandex.ru/support/tracker/en/plugins/tools/sdk/core.md
    type: text/markdown
    title: Markdown version
  - href: https://yandex.ru/support/tracker/en/llms.txt?revision=r22077802
    rel: describedby
---
> **Documentation Index:** Fetch the complete configuration index at https://yandex.ru/support/tracker/en/llms.txt?revision=r22077802


# API Reference - @weavix/tracker-plugin-sdk-core

<a id="hostapi-hostapi"></a>

## hostApi (HostApi) {#host-api}

API for interacting with the Tracker application: 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() {#init}

Initializes the plugin (reads parameters from the URL, establishes a connection with Tracker, 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 "@weavix/tracker-plugin-sdk-core";

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

<a id="gettheme"></a>

### getTheme() {#get-theme}

Returns the current Tracker theme.

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

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

<a id="getlanguage"></a>

### getLanguage() {#get-language}

Returns the current Tracker language.

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

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

### getUserAvatars() {#get-user-avatars}

Gets user avatars in a single request through Tracker.

**Parameters:** `users: Array<{ uid?: string; login?: string }>` — 1–100 users. For each user, provide a non-empty string `uid`, `login`, or both.

**Returns:** `Promise<Array<string | null>>`. Results follow the input order. Each item is an absolute HTTP(S) avatar URL or `null` if the avatar is unavailable.

```typescript
const [aliceAvatar, bobAvatar] = await hostApi.getUserAvatars([
    { login: "alice" },
    { uid: "123" },
]);
```

If the app does not support the method, the request may fail with `METHOD_NOT_SUPPORTED`. Show the user's initials if the URL is missing, the request fails, or the image cannot load.

The image domain must be allowed by the plugin's CSP `img-src` directive.

<a id="getcontext"></a>

### getContext() {#get-context}

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");
```

<a id="updatecontentsize"></a>

### updateContentSize() {#update-content-size}

Sends a request to Tracker 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.

{% note info "Scrolling inside a plugin" %}

If the iframe expands to the full content height, it has no scrollable area. As a result, `element.scrollIntoView()` and `window.scrollTo()` don't scroll the plugin document.
To scroll programmatically inside a plugin, disable automatic resizing with `hostApi.disableAutoResize()`. Then use `hostApi.updateContentSize()` to set the iframe height below the content height.

{% endnote %}

### notifyReady() {#notifyReady}

Notifies Tracker that the plugin is ready.

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

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

<a id="getslot"></a>

### getSlot() {#get-slot}

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

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

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

<a id="disableautoresize"></a>

### disableAutoResize() {#disable-auto-resize}

Disables automatic container resizing based on content.

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

### close() {#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 %}

<a id="preventClose}"></a>

### 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, Tracker 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 "@weavix/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 "@weavix/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) Tracker may ignore the block.

{% endnote %}

<a id="uiapi"></a>

## uiApi {#ui-api}

API for interacting with Tracker's user interface: showing notifications, displaying pop-ups, and more.

### Toasts {#toasts}

Plugins can show toast notifications in the Tracker interface 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 "@weavix/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
            },
        },
    ],
});
```

<a id="parameters"></a>

#### Parameters {#toasts-params}

#|
|| 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 {#error-handling}

```typescript
import {
    trackerApi,
    PluginActionError,
} from "@weavix/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 "@weavix/tracker-plugin-sdk-core";

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

<a id="parameters1"></a>

#### Parameters {#confirm-params}

#|
|| 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    ||
|#

<a id="limits-and-errors"></a>

#### Limits and errors {#confirm-limits}

- **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 %}

<a id="trackerapi-trackerapi"></a>

## trackerApi (TrackerApi) {#tracker-api}

A class for calling the Tracker Public API via the platform (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/common-format.md).

Exports the **`trackerApi`** singleton.

### v3 {#v3}

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

**Examples:**

```typescript
import { trackerApi } from "@weavix/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}

Platform JSON storage at the organization level — `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 "@weavix/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 platform's proxy with OAuth authorization support.

{% note warning "Direct requests" %}

Call external APIs through `hostApi.externalApiCall()`. Direct HTTP requests from the plugin (`fetch`, `XMLHttpRequest`) are only possible to domains with `access: ["direct"]`, but they don't support authorization and aren't recommended. For more information, see [External APIs](https://yandex.ru/support/tracker/en/plugins/externalApi.md#direct-access).

{% endnote %}

Add the `permissions.external` section to `manifest.json` with a list of allowed domains. For requests through the platform, set the `access` field to `proxy`:

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

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.

Only the user's personal tokens are supported: specify `"user"` in the manifest `contextTypes` and in the `contextType` parameter of the methods. The `"organization"` value exists in the SDK types, but the platform doesn't support it. For more information about authorization, see [Proxy authorization](https://yandex.ru/support/tracker/en/plugins/externalApi.md#proxy-auth).


### 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 platform 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 "@weavix/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: "user",
    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);
    }
}
```

<a id="externalapiauthcheckandrequest"></a>

### externalApiAuthCheckAndRequest() {#external-api-auth-check-and-request}

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;
```

<a id="externalapiauthgetstatus"></a>

### externalApiAuthGetStatus() {#external-api-auth-get-status}

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);
```

<a id="externalapiauthrequest"></a>

### externalApiAuthRequest() {#external-api-auth-request}

Shows the user a dialog for entering credentials for the specified domains. If confirmed successfully, the platform 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" },
        },
    ],
});
```

<a id="externalapiauthrevoke"></a>

### externalApiAuthRevoke() {#external-api-auth-revoke}

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 {#types}

<a id="trackerapiinitoptions"></a>

### TrackerApiInitOptions {#tracker-api-init-options}

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;
}
```

---

<a id="trackerapicalloptions"></a>

### TrackerApiCallOptions {#tracker-api-call-options}

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

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

---

<a id="trackerapiv3"></a>

### TrackerApiV3 {#tracker-api-v3}

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

---

### Theme {#theme}

Tracker theme type.

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

---

<a id="slotcontextmap"></a>

### SlotContextMap {#slot-context-map}

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 `@weavix/tracker-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>;
};

// 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");
```

---

<a id="contentsizeupdaterequest"></a>

### ContentSizeUpdateRequest {#content-size-update-request}

Request to change the plugin content size.

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

---

<a id="hostinitoptions"></a>

### HostInitOptions {#host-init-options}

Options for initializing interaction with Tracker (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 platform 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 "@weavix/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 {#utils}

<a id="getlocalizedstring"></a>

### getLocalizedString() {#get-localized-string}

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

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

<a id="getfield"></a>

### getField() {#get-field}

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 {#handlers}

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

---

## Complete Example {#complete-example}

```typescript
import {
    hostApi,
    trackerApi,
    getField,
    type Theme,
} from "@weavix/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 **@weavix/tracker-api-types** package.
