OAuth
Тип OAuth-интеграция подходит для внешнего сайта, которому нужен доступ к данным проекта StreamVi. Пользователь выбирает проект и подтверждает разрешения, а ваше приложение использует полученный доступ для запросов к API.
Справочник методов и параметров находится на dev.streamvi.io. Используйте описанный там контракт выбранного метода. Настройки приложения в кабинете находятся в Для разработчиков → приложение → Настройки.
Для API-запросов доступны SDK Axios и SDK Fetch. Если сервер уже использует Passport, прочитайте инструкцию библиотеки и ограничения её опубликованной версии. Примеры на GitHub показывают структуру серверного приложения; ниже приведён самостоятельный OAuth-поток с проверкой state и PKCE.
Подготовка приложения
Создайте плагин типа OAuth-интеграция, выберите нужные разрешения и настройте допустимые OAuth redirect URL. Для примера ниже нужно разрешение project:read. ID клиента и секретный ключ доступны в настройках приложения. Секрет и полученные токены храните на сервере своего приложения.
В примерах используется https://example.com/streamvi/callback. Замените его своим обработчиком и добавьте этот же адрес в настройки приложения. Все ID и токены в примерах вымышленные.
Начать подключение
Открывайте пользователю адрес https://streamvi.io/cabinet/oauth с параметрами из таблицы. Кабинет покажет выбор проекта и запрос разрешений.
| Параметр | Что передать |
|---|---|
client_id | ID клиента из настроек приложения |
redirect_uri | Полный адрес вашего обработчика возврата, совпадающий с разрешённым OAuth redirect URL |
response_type | code |
scope | Нужные коды разрешений через пробел, например project:read |
state | Новую случайную строку, связанную с текущей сессией пользователя в вашем приложении |
code_challenge | SHA-256 от code_verifier, закодированный в Base64url без = |
code_challenge_method | S256 для примера с PKCE |
project_id | Необязательный внешний ID проекта. Если его не передать, пользователь выберет проект в кабинете |
Следующий серверный пример на Node.js создаёт ссылку с PKCE S256. Для каждого подключения создавайте новую пару state и codeVerifier.
import { createHash, randomBytes } from 'node:crypto';
function beginOAuth(clientId, redirectUri) {
const state = randomBytes(32).toString('base64url');
const codeVerifier = randomBytes(32).toString('base64url');
const challenge = createHash('sha256').update(codeVerifier).digest('base64url');
const url = new URL('https://streamvi.io/cabinet/oauth');
url.search = new URLSearchParams({
client_id: clientId,
redirect_uri: redirectUri,
response_type: 'code',
scope: 'project:read',
state,
code_challenge: challenge,
code_challenge_method: 'S256',
}).toString();
return {
url: url.href,
transaction: { clientId, redirectUri, state, codeVerifier },
};
}
Вызовите beginOAuth с вашим ID клиента и адресом возврата. Сохраните transaction в серверной сессии пользователя, затем перенаправьте браузер на url. Задайте срок хранения этой записи и используйте её только для одного подключения. В ссылку отправляется code_challenge; исходный codeVerifier остаётся на вашем сервере до обмена кода.
Авторизация пользователя
Авторизацию начинает приложение. В открывшемся кабинете пользователь выбирает доступный проект и нажимает Продолжить.

Затем пользователь проверяет перечень запрашиваемых разрешений и, если согласен, нажимает Разрешить доступ. Чтобы отказаться, нажимает Отклонить. При переданном проекте экран разрешений может показываться сразу. Полученный доступ связан с выбранным проектом и разрешениями.

На снимках учебное приложение запрашивает чтение проекта. Состав прав зависит от приложения и его запроса; действие Разрешить выдаёт доступ, поэтому проверяйте его до подтверждения.
Если в запросе не передан отдельный список разрешений, кабинет использует права, настроенные для приложения. Запрос прав вне разрешённого приложению набора блокируется. При ошибке загрузки списка прав или недоступном проекте выдача доступа не продолжается.
Получить токен
После согласия браузер возвращается на redirect_uri с code и state. В обработчике возврата сначала получите сохранённую transaction из сессии того же пользователя и проверьте state. Проверку выполняет ваше приложение. При отсутствии сессии, несовпадении state или отказе пользователя не обменивайте код.
Обмен выполняется серверным POST на https://api-v2.streamvi.io/site/oauth/token с телом application/x-www-form-urlencoded. В примере с PKCE передаются grant_type=authorization_code, client_id, redirect_uri, code и сохранённый code_verifier.
async function finishOAuth(callbackUrl, transaction) {
if (!transaction) throw new Error('OAuth session missing');
const params = new URL(callbackUrl).searchParams;
if (!params.get('state') || params.get('state') !== transaction.state) {
throw new Error('OAuth state mismatch');
}
if (params.has('error')) throw new Error('OAuth authorization declined');
const code = params.get('code');
if (!code) throw new Error('OAuth code missing');
const response = await fetch('https://api-v2.streamvi.io/site/oauth/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'authorization_code',
client_id: transaction.clientId,
redirect_uri: transaction.redirectUri,
code,
code_verifier: transaction.codeVerifier,
}),
});
const data = await response.json();
if (!response.ok || typeof data.access_token !== 'string' || !data.access_token) {
throw new Error('OAuth token request failed');
}
return data;
}
Удалите запись transaction из сессии при обработке возврата, чтобы повторный callback не запускал тот же обмен. При ошибке начните новое подключение. Сохраните результат успешного обмена на сервере и свяжите его с пользователем вашего приложения и выбранным проектом StreamVi.
Пример ответа:
{
"access_token": "ACCESS_TOKEN",
"token_type": "Bearer",
"scope": "project:read",
"project_id": 12345,
"project_external_id": "87654321"
}
project_id в ответе - внутренний числовой ID проекта; project_external_id - внешний ID для адреса авторизации. Токен связан с выбранным проектом. Передача другого project_id в API-запросе не переключает проект и приводит к ошибке доступа.
Первый запрос API
Для чтения состояния трансляции используйте GET /method/project/live-status с разрешением project:read. В переменной STREAMVI_ACCESS_TOKEN ниже должен находиться полученный access_token.
curl --fail-with-body \
'https://api-v2.streamvi.io/method/project/live-status?v=1' \
--header "Authorization: Bearer $STREAMVI_ACCESS_TOKEN"
v=1 задаёт версию метода. Проект определяется по токену, поэтому в этом запросе отдельный project_id не нужен. Для других методов используйте их обязательные параметры и разрешения из справочника API. Токен интеграции предназначен для /method/; маршруты кабинета /site/ используют его собственную авторизацию.
Повторное подключение
Текущий OAuth-контракт поддерживает grant_type=authorization_code. Обмен через grant_type=refresh_token не поддерживается. Если доступ перестал действовать или требуется подключить другой проект, повторите авторизацию и сохраните новый токен после согласия пользователя.
Проверка интеграции
Сначала проверьте чтение доступных данных в нужном проекте. Для запроса изменения отдельно убедитесь, что пользователь разрешил соответствующую возможность. Выбор типа OAuth сам по себе не даёт приложению право менять или удалять данные.
При ошибке проверьте ID приложения, точное совпадение redirect URI, доступность проекта, разрешения и соответствие code_verifier исходному code_challenge. Аккаунт пользователя и выбранный проект должны быть активны. При ошибке oauth2.insufficient_scope проверьте разрешение конкретного метода и выданный scope; при version.not_provided добавьте версию метода. Не используйте ключ входящей трансляции как API-токен.
Для входящих событий приложения настройте вебхуки. Для проверки пользовательского согласия см. подключение плагина.