Skip to content

Аутентификация ​

Каждый вызов Wildberries Seller API требует bearer JWT в заголовке Authorization. Клиенты сами подставляют заголовок; вы передаёте только токен.

Откуда берётся токен ​

Токены выпускаются в кабинете продавца:

  1. seller.wildberries.ru → раздел Интеграции по API.
  2. + Создать токен → вкладка Для интеграции вручную → выберите тип токена: персональный, базовый или тестовый для песочницы.
  3. Заполните название, выберите категории методов (Контент, Маркетплейс, Аналитика, …) и уровень доступа — Чтение и запись или Только чтение.
  4. Создать → Скопировать и закрыть. Токен показывают один раз — сохраните его сразу.

Каждой выбранной категории примерно соответствует один или несколько под-модулей в клиенте. Если пришёл 403 — токен валиден, но прав не хватает; перевыпустите с нужной категорией.

Какой тип токена выбрать:

  • Персональный — для собственных программ и on-premise систем (включая локальные версии 1С). Даёт доступ к чувствительным данным, поэтому его нельзя передавать третьим лицам и использовать в облачных сервисах.
  • Базовый — доступ к ограниченному набору данных. Подходит для проверки интеграции на реальных данных и для случаев, когда персональный использовать нельзя.
  • Тестовый — работает только с песочницей WB API и сгенерированными тестовыми данными; доступа к реальным данным продавца нет.
  • Сервисный — создаётся для конкретного облачного сервиса из каталога «Решения для бизнеса»; категории и уровни доступа заполняются автоматически.

Любой токен живёт 180 дней с момента создания, после чего нужно выпустить новый. Проверить валидность токена и его категории можно, декодировав JWT — это строка по RFC 7519. Не вставляйте токен в онлайн-декодеры: так его может перехватить кто угодно.

Обёртки SecretString ​

Получив токен, не носите его по коду как обычную строку. Каждый клиент оборачивает значение в языко-специфичный «секретный» тип — он маскирует токен в логах, print-выводе, отладчике и дампах ошибок, пока вы явно не запросите значение.

ЯзыкОбёрткаСеттерМаскируется вЯвное значение
Pythonpydantic.SecretStrConfiguration(access_token=…)print(cfg.access_token) → **********.get_secret_value()
TypeScriptвстроенный класс SecretStringConfiguration.setAccessToken(…)console.log(new SecretString("…")) → <REDACTED>.exposeSecret()
Gosecrecy.SecretStringConfiguration.SetAccessToken(…)fmt.Printf("%v", cfg.AccessToken) → <!SECRET_LEAKED!>.ExposeSecret()
JavaSecretString в каждом под-пакетеApiClient.setAccessToken(String)System.out.println(s) → <REDACTED>.exposeSecret()
PHPSecretString в каждом под-пространствеConfiguration::setAccessToken(string)var_dump($config) → '<REDACTED>'$config->getAccessToken()
C#SecretString в каждом пространстве имёнConfiguration.SetAccessToken(…)Console.WriteLine(new SecretString("…")) → <REDACTED>.ExposeSecret()
OneScriptкласс СекретнаяСтрокаКонфигурация.УстановитьТокен(…)Сообщить(Настройки.Токен()) → СекретнаяСтрока.Раскрыть()
RustSecretString в каждом модулеConfiguration::set_access_token(…)println!("{s:?}") / {} → <REDACTED>.expose_secret()

Зачем это нужно ​

Реальные ситуации, ради которых это сделано:

  • Логгер-middleware, который в трейсе ошибки дампит всю конфигурацию запроса.
  • print(config), оставленный в коде после отладки.
  • Исключения, сериализованные в Sentry / трекер вместе с полным контекстом HTTP-клиента.
  • Отладчик IDE, показывающий поля объекта на демо-встрече по шаринг-скрину.

Обёртка превращает каждый из этих сценариев из утечки токена в безобидную метку <REDACTED>. Цена — одна строка кода в точке ввода.

Как это выглядит на практике ​

python
from wb_api_client.items import Configuration
cfg = Configuration(access_token="eyJhbGciOi...")
print(cfg.access_token)                       # SecretStr('**********')
print(cfg.access_token.get_secret_value())    # eyJhbGciOi...  (по запросу)
ts
import { Configuration } from "@valeryverkhoturov/wb-api-client/items";
const cfg = new Configuration({});
cfg.setAccessToken("eyJhbGciOi...");
console.log(cfg.accessToken);                 // SecretString { <REDACTED> }
console.log(cfg.accessToken.exposeSecret());  // eyJhbGciOi...  (по запросу)
go
import wbitems "github.com/ValeryVerkhoturov/wb-api-client-go/items"
cfg := wbitems.NewConfiguration()
cfg.SetAccessToken("eyJhbGciOi...")
fmt.Printf("%v\n", cfg.AccessToken)           // <!SECRET_LEAKED!>
fmt.Println(cfg.AccessToken.ExposeSecret())   // eyJhbGciOi...  (по запросу)
java
import io.github.valeryverkhoturov.wbapi.items.SecretString;
SecretString s = new SecretString("eyJhbGciOi...");
System.out.println(s);                        // <REDACTED>
System.out.println(s.exposeSecret());         // eyJhbGciOi...  (по запросу)
php
use ValeryVerkhoturov\WbApiClient\Items\SecretString;
$s = new SecretString('eyJhbGciOi...');
var_dump($s);                                 // object(...) { ['value']=> '<REDACTED>' }
echo $s->exposeSecret();                      // eyJhbGciOi...  (по запросу)
bsl
С = Новый СекретнаяСтрока("eyJhbGciOi...");
Сообщить(С);                                  // СекретнаяСтрока
Сообщить(С.Раскрыть());                       // eyJhbGciOi...  (по запросу)
csharp
var s = new SecretString("eyJhbGciOi...");
Console.WriteLine($"{s}");                    // <REDACTED>
Console.WriteLine(s.ExposeSecret());          // eyJhbGciOi...  (по запросу)
rust
use wb_api_client::items::apis::configuration::SecretString;
let s = SecretString::new("eyJhbGciOi...");
println!("{s:?}");                            // <REDACTED>
println!("{}", s.expose_secret());            // eyJhbGciOi...  (по запросу)

Один токен на несколько под-модулей ​

Если в процессе вы используете сразу несколько под-модулей, у каждого — свой Configuration / ApiClient. Так задумано: openapi-generator создаёт полностью изолированные SDK на каждую спецификацию. Переиспользуйте строку токена, но конструируйте конфиг на каждый модуль.

python
from wb_api_client.items import Configuration as ItemsCfg, ApiClient as ItemsClient
from wb_api_client.orders_fbs import Configuration as OrdCfg, ApiClient as OrdClient

TOKEN = "<ваш JWT WB>"
items_api = ItemsClient(ItemsCfg(access_token=TOKEN))
orders_api = OrdClient(OrdCfg(access_token=TOKEN))
ts
import { Configuration as ItemsCfg } from "@valeryverkhoturov/wb-api-client/items";
import { Configuration as OrdCfg } from "@valeryverkhoturov/wb-api-client/orders_fbs";

const TOKEN = "<ваш JWT WB>";
const itemsCfg = new ItemsCfg({}); itemsCfg.setAccessToken(TOKEN);
const ordCfg   = new OrdCfg({});   ordCfg.setAccessToken(TOKEN);

Ротация токенов ​

Токены WB не ротируются сами и живут максимум 180 дней — их нужно заменять вручную. Хорошая практика:

  1. Держите токен в секрет-менеджере (SSM, Vault, GitHub Actions secret) — не в исходниках.
  2. Читайте в переменную окружения при старте процесса и конструируйте конфиг один раз.
  3. На ротации: убейте процесс (или пул соединений) и запустите заново с новым токеном. Клиент кэширует токен на уровне экземпляра Configuration.

Типичные ошибки авторизации ​

ОтветЗначение
401 Unauthorized — token expiredСрок токена истёк; выпустите новый
401 Unauthorized — invalid signatureНеверный формат заголовка Authorization или токен от другой среды (sandbox / prod)
403 Forbidden — no access to resourceТокен валиден, прав не хватает — перевыпустите с правильной галочкой
429 Too Many RequestsRate-limit; сам токен в порядке

Ретраи и работа с ошибками — в руководстве по обработке ошибок.

wb-api-client mascot

Распространяется под лицензией Apache 2.0.