Внешние API
Плагин может обращаться к внешним HTTP API двумя способами:
- Запросы через платформу — плагин вызывает
hostApi.externalApiCall(), а прокси платформы выполняет запрос со своего бекенда. Это основной способ: платформа авторизует запрос, ведет аудит, ограничивает частоту запросов и блокирует небезопасные направления. - Прямые запросы — плагин отправляет запрос из браузера с помощью
fetchилиXMLHttpRequest. Платформа в таких запросах не участвует, поэтому они не поддерживают авторизацию и не рекомендуются к использованию.
Способ доступа к каждому домену задается в манифесте.
Разрешение в манифесте
Добавьте в manifest.json секцию permissions.external с перечнем разрешенных доменов и способов доступа к ним:
{
"permissions": {
"external": [
{
"domain": "api.example.com",
"access": ["proxy"],
"authorization": {
"type": "oauth",
"scopes": ["read", "write"],
"contextTypes": ["user"]
},
"instructions": {
"ru": "Создайте токен с правами read и write в настройках Example API",
"en": "Create a token with the read and write permissions in Example API settings"
}
}
]
}
}
В поле domain укажите имя хоста без протокола, пути и порта. Каждый домен объявляйте один раз.
Поле access задает способ доступа к домену:
proxy— запросы через платформу с помощьюhostApi.externalApiCall();direct— прямые запросы из браузера. Платформа добавляет домен в директивуconnect-srcполитики CSP плагина.
Если поле access не указано, разрешены оба способа. Указывайте access явно и разрешайте только тот способ, который использует плагин, — как правило, ["proxy"]. Домен с access: ["proxy"] не добавляется в CSP, поэтому прямой запрос к нему браузер заблокирует.
Поле authorization опционально — его можно опустить для доменов без авторизации.
Авторизация прокси
Поле authorization описывает, какой токен нужен для домена и как его подставить в запрос, но не содержит сам токен:
type—oauthдля OAuth-токена илиtokenдля API-ключа и других не-OAuth токенов;scopes— минимальные права токена, которые нужны плагину. Поле только декларирует права и не выдает их токену;contextTypes— контекст хранения токена. Всегда указывайте["user"]: поддерживаются только личные токены пользователя.
В поле instructions укажите для пользователя, где получить токен и какие права ему выдать, на русском и английском языках.
Авторизация проходит на стороне Трекера:
- Плагин вызывает
hostApi.externalApiAuthCheckAndRequest()с контекстомuser. - Если у пользователя еще нет токена для домена, Трекер показывает диалог ввода токена с инструкцией из манифеста.
- Трекер сохраняет токен для текущего пользователя и домена. Плагин получает только результат
{ success: boolean }— сам токен в плагин не попадает. - При вызове
hostApi.externalApiCall()платформа подставляет токен в запрос и выполняет его со своего бекенда.
Если токен перестал работать, например, истек, пользователю нужно ввести новый токен.
Запросы через платформу
Основной способ обращения к внешним API. Плагин передает параметры запроса — URL, метод, заголовки и тело — в hostApi.externalApiCall(), а платформа выполняет запрос со своего бекенда и возвращает результат. При этом платформа:
- подставляет в запрос токен, если для домена настроено поле
authorization. Токен не передается в iframe плагина; - блокирует запросы к небезопасным направлениям: приватным сетям,
localhostи неразрешенным редиректам; - ведет аудит запросов;
- ограничивает частоту запросов по плагину и организации.
Чтобы отправлять запросы к домену через платформу, укажите для него в манифесте access: ["proxy"].
Базовое использование
Типичный сценарий — проверить авторизацию, при необходимости запросить ее у пользователя, затем вызвать API:
import {
hostApi,
PluginActionError,
EXTERNAL_API_CALL_ERROR,
} from "@weavix/tracker-plugin-sdk-react";
async function fetchItems() {
// Проверить авторизацию и показать диалог, если нужно
const { success } = await hostApi.externalApiAuthCheckAndRequest({
domains: ["api.example.com"],
contextType: "user",
});
if (!success) {
// Пользователь закрыл диалог или истек таймаут
return;
}
// Вызвать внешний API через прокси платформы
const { status, body } = await hostApi.externalApiCall({
url: "https://api.example.com/v1/items",
method: "GET",
contextType: "user",
});
// status — HTTP-статус ответа
// body — тело ответа (Record<string, unknown>)
}
POST с телом и таймаутом:
const { status, body } = 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,
});
Обработка ошибок
При сетевой ошибке или ответе с ошибочным статусом платформа возвращает PluginActionError с кодом EXTERNAL_API_CALL_ERROR (1013). Детали — в e.errorData:
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 проверяет авторизацию и при необходимости показывает диалог в одном вызове, см. пример выше.
Ручное управление. Если нужен более тонкий контроль — используйте отдельные методы:
// Проверить статус по доменам
const { domains } = await hostApi.externalApiAuthGetStatus({
domains: ["api.example.com"],
contextType: "user",
});
const isAuthed = domains.every((d) => d.authenticated);
// Показать диалог авторизации с подсказкой
if (!isAuthed) {
await hostApi.externalApiAuthRequest({
domains: [
{
domain: "api.example.com",
instructions: {
ru: "Войдите в Example",
en: "Sign in to Example",
},
},
],
});
}
// Отозвать сохраненные учетные данные
await hostApi.externalApiAuthRevoke({
domains: ["api.example.com"],
contextType: "user",
});
Подробнее о методах — в разделе hostApi.externalApi*.
Прямые запросы
Важно
Прямые запросы не поддерживают авторизацию и не рекомендуются к использованию. Используйте запросы через платформу.
Если в access домена указано значение direct, плагин может отправлять запросы к нему из браузера с помощью fetch или XMLHttpRequest:
{
"permissions": {
"external": [
{
"domain": "cdn.example.com",
"access": ["direct"]
}
]
}
}
const response = await fetch("https://cdn.example.com/data.json");
const data = await response.json();
Платформа только добавляет домен в директиву connect-src политики CSP плагина и в запросе не участвует:
- не подставляет токены — поле
authorizationдля такого домена указать нельзя; - не блокирует небезопасные направления, не ведет аудит и не ограничивает частоту запросов.
Внешний сервис должен поддерживать CORS для источника (origin) плагина. Способ direct расширяет только директиву connect-src: загрузка изображений, скриптов и стилей с домена по-прежнему заблокирована.