Актуальная аутентификация ShopStory API
На сегодняшний день все production интеграции используют applicationId в query параметрах. Переход на Bearer токены находится в закрытой бете и будет объявлен отдельно, когда станет доступен всем клиентам.
Планируемое окно публичного релиза — H1 2026; следите за апдейтами в релиз-нотах и на этой странице.
Эта страница помогает:
- безопасно работать с текущим методом
applicationId - защитить идентификатор от конкурентов и ботов
- подготовиться к миграции на Bearer токены, когда она станет доступной
🔓 Production метод: applicationId
applicationId — это идентификатор вашего магазина/приложения в ShopStory.
GET https://app.shopstory.live/v3/streams?applicationId=your-app&limit=20
Лучшие практики защиты
- 🔐 Держите значение в секрете: храните в переменных окружения или секрет-хранилищах CI/CD
- ♻️ Используйте уникальные значения для dev/staging/prod окружений
- 🔄 Ротируйте идентификатор при смене команды или подозрении на утечку
- 💻 Не размещайте в публичном фронтенд-коде — проксируйте запросы через бэкенд
- 📊 Следите за аномальными запросами по логам и rate-limit событиям
Пример бэкенд-прокси (Node.js)
import fetch from 'node-fetch';
import express from 'express';
const app = express();
const APPLICATION_ID = process.env.SHOPSTORY_APPLICATION_ID;
app.get('/api/shopstory/streams', async (req, res) => {
const search = new URLSearchParams({
applicationId: APPLICATION_ID,
limit: req.query.limit ?? '12',
offset: req.query.offset ?? '0'
});
const upstream = await fetch(`https://app.shopstory.live/v3/streams?${search}`);
const payload = await upstream.json();
res.status(200).json(payload);
});
Как минимизировать риск угадывания applicationId
- Используйте длинные случайные значения (например,
shop_ab12cd34efвместо бренда в чистом виде) - Не используйте одинаковый ID на production и demo сайтах
- Включите дополнительную проверку referrer/IP на своем прокси, чтобы ограничить выдачу каталога
- Рассмотрите rate limiting на своей стороне: блокируйте IP, делающие подозрительно много запросов
- Получайте уведомления об ошибках 401/404 — они часто появляются во время подбора идентификаторов
🚧 Bearer токены (закрытая бета)
Bearer токены — целевая модель аутентификации. Сейчас она доступна ограниченному числу клиентов. Когда функциональность станет публичной, мы обновим документацию и отправим инструкции по миграции.
Что уже готово
- ✅ Архитектура токенов и маршрутов проверена с пилотными клиентами
- ✅ Бэкенд поддерживает параллельную работу токенов и
applicationId - ⚠️ UI для управления токенами находится в разработке
- ⚠️ Аудит, IP whitelist и scopes появятся одновременно с публичным релизом
Формат токена
sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxx
Как запросить доступ
Свяжитесь с вашим Customer Success менеджером или напишите на support@shopstory.live. Команда оценит готовность и согласует пилот.
📋 Как будет выглядеть миграция
⚠️ Эта секция описывает план на релиз. Выполняйте его только после официального уведомления о запуске токенов.
Чек-лист подготовки
- Обновите SDK/бэкенд, чтобы принимать оба способа (query и заголовок)
- Создайте конфигурацию для токена (переменная окружения, секрет в Vault и т.д.)
- Настройте мониторинг 401/403 ошибок
- Запл анируйте ротацию токена сразу после GA-релиза
- Сообщите команде поддержки о переходе, чтобы закрыть старые
applicationId
🚨 Обработка ошибок
400 Bad Request
{
"status": 400,
"body": {
"error": {
"code": "InvalidApplication",
"message": "Unknown applicationId"
}
}
}
Когда возникает:
applicationIdне указан или содержит опечатку- ID кли ента отключен или удалён
Как исправить:
- Проверьте переменные окружения и конфигурацию прокси
- Убедитесь, что значение действительно существует в ShopStory
- Для продакшена используйте отдельные ID на каждое окружение
401 Unauthorized (β)
После релиза токенов 401 будет возвращаться, если заголовок Authorization отсутствует или токен отозван. Следите за обновлениями в релиз-нотах.
429 Rate Limit
{
"status": 429,
"body": {
"error": {
"code": "RateLimitExceeded",
"message": "Too many requests"
}
}
}
Совет: Реализуйте экспоненциальный бэкофф и не параллельте запросы больше лимитов. См. Rate limiting.
💡 Примеры использования
React приложение
import { useState, useEffect } from 'react';
// Фронтенд обращается к вашему безопасному прокси
export function useShopStoryAPI(endpoint, options = {}) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
async function fetchData() {
try {
const response = await fetch(
`/api/shopstory${endpoint}`,
{
headers: {
'Accept': 'application/json'
},
...options
}
);
const result = await response.json();
if (result.status !== 200) {
throw new Error(result.body?.error?.message || 'API Error');
}
setData(result.body);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
}
fetchData();
}, [endpoint, options]);
return { data, loading, error };
}
// Использование
function StreamsList() {
const { data, loading, error } = useShopStoryAPI('/v3/streams?limit=10');
if (loading) return <div>Загрузка...</div>;
if (error) return <div>Ошибка: {error}</div>;
return (
<div>
{data.availableStreams.map(stream => (
<div key={stream.id}>{stream.name}</div>
))}
</div>
);
}
Node.js Backend
class ShopStoryClient {
constructor({ applicationId, apiToken } = {}) {
if (!applicationId) {
throw new Error('applicationId is required for production');
}
this.applicationId = applicationId;
this.apiToken = apiToken; // будет использоваться, когда токены станут доступны
this.baseURL = 'https://app.shopstory.live';
}
buildUrl(endpoint, params = {}) {
const url = new URL(`${this.baseURL}${endpoint}`);
Object.entries(params).forEach(([key, value]) => {
if (value !== undefined && value !== null) {
url.searchParams.set(key, String(value));
}
});
if (this.apiToken) {
// Bearer токен в будущем заменит query параметр
return { url: url.toString(), headers: { Authorization: `Bearer ${this.apiToken}` } };
}
url.searchParams.set('applicationId', this.applicationId);
return { url: url.toString(), headers: {} };
}
async request(endpoint, { params = {}, method = 'GET', body } = {}) {
const { url, headers } = this.buildUrl(endpoint, params);
const response = await fetch(url, {
method,
headers: {
'Content-Type': 'application/json',
...headers
},
body
});
const data = await response.json();
if (data.status !== 200) {
const error = new Error(data.body?.error?.message || 'API Error');
error.code = data.body?.error?.code;
error.status = data.status;
throw error;
}
return data.body;
}
getStreams(params = {}) {
return this.request('/v3/streams', { params });
}
getQuickState(translationId) {
return this.request('/v3/translation/quick-state', {
params: { translationId }
});
}
}
// Использование
const client = new ShopStoryClient({
applicationId: process.env.SHOPSTORY_APPLICATION_ID,
apiToken: process.env.SHOPSTORY_API_TOKEN // появится позже
});
const streams = await client.getStreams({ limit: 20 });
console.log('Streams:', streams.availableStreams);
📚 Дополнительные ресурсы
- Быстрый старт - первые запросы к API
- Безопасность - лучшие практики
- Лимиты запросов - управление трафиком
- Примеры интеграций - готовые решения
❓ FAQ
Можно ли использовать один токен для нескольких приложений?
Token функциональность пока недоступна публично. Когда она станет активной, мы порекомендуем уникальные токены на приложение/окружение.
Что делать если токен утек?
Доступ в закрытой бете. На этапе production-релиза появится UI для отзывов. До тех пор полагайтесь на защиту applicationId и обращайтесь в поддержку.
Как часто нужно менять токены?
Рекомендации по ротации будут опубликованы в релиз-нотах, когда токены станут общедоступными.
Можно ли ограничить токен по IP?
Функциональность IP whitelist находится в разработке.
Сколько токенов можно создать?
Ограничения и квоты будут объявлены вместе с релизом токенов.
Готовы начать? Перейдите к Quickstart, настройте интеграцию с applicationId и подготовьте код к будущей миг рации.