СБИС API: ключи, токены и авторизация — пошаговая настройка

Как создать внешнее приложение в СБИС, получить app_client_id, app_secret и secret_key, запросить токен и выполнять API-запросы. Разбираем сервисную авторизацию, интерактивный OAuth 2, права доступа, хранение секретов, Symfony-клиент, повторную авторизацию и типичные ошибки интеграции.

При интеграции СБИС с 1С, CRM, интернет-магазином, ERP или собственной информационной системой первый вопрос обычно возникает ещё до работы с контрагентами и документами: как правильно авторизовать внешнее приложение в СБИС?

На практике здесь важно не перепутать несколько разных сущностей: идентификатор приложения, защищённый ключ, сервисный ключ, токен доступа и сессию. Если смешать их в одном месте, интеграция начинает работать нестабильно: токен получают перед каждым запросом, секреты оказываются в Git, а при ошибке авторизации непонятно, какой именно уровень системы нужно проверять.

В актуальной документации Saby для сервисной авторизации внешнего приложения используются app_client_id, app_secret и secret_key. По этим данным приложение получает токен доступа, который затем передаётся в API-запросах через заголовок X-SBISAccessToken.

В этой статье разберём именно серверный сценарий, когда интеграция работает в фоне без постоянного участия пользователя: например, 1С автоматически получает сведения о контрагентах, отправляет документы или синхронизирует данные с СБИС.

Коротко: как устроена авторизация СБИС API

В упрощённом виде цепочка выглядит так:

Внешнее приложение
        ↓
app_client_id + app_secret + secret_key
        ↓
POST /oauth/service/
        ↓
Токен доступа
        ↓
X-SBISAccessToken: <token>
        ↓
Saby API
        ↓
JSON-RPC / API Gateway
        ↓
Данные и команды

То есть секреты используются для получения токена, а сам токен — для последующих запросов. Бизнес-код приложения не должен каждый раз заново проходить весь процесс получения credentials.

Главная мысль: ключи приложения и токен доступа — разные вещи. Ключи нужны для авторизации приложения, токен — для работы с API.

Какие данные нужны для СБИС API

Для сервисной авторизации используются три значения. Их назначение удобно разделять сразу:

Параметр Что это Где используется
app_client_id Идентификатор внешнего приложения При получении токена
app_secret Защищённый ключ приложения При сервисной авторизации
secret_key Сервисный секретный ключ При сервисной авторизации
token Полученный токен доступа В последующих API-запросах

В интерфейсе Saby эти данные появляются после создания и настройки внешнего приложения. Сам сервисный ключ генерируется системой и может быть выгружен из карточки приложения.

Шаг 1. Создать внешнее приложение в СБИС

Сначала в Saby нужно зарегистрировать внешнюю систему, которая будет обращаться к API. Это важнее, чем кажется: права доступа назначаются именно приложению, а не отдельному HTTP-запросу.

В актуальной инструкции Saby путь выглядит следующим образом:

  1. Открыть настройки Saby.
  2. Перейти в раздел безопасности.
  3. Открыть «Подключения к Saby».
  4. Добавить внешнее приложение.
  5. Указать название и описание приложения.
  6. Настроить разрешённые адреса или IP, если это требуется.
  7. Включить сервисный доступ.
  8. Выбрать необходимые права.
  9. Настроить авторизацию по сервисному ключу.
  10. Сохранить приложение.

Для production-интеграции лучше сразу использовать принцип минимально необходимых прав. Если сервису требуется только чтение данных контрагентов, не стоит выдавать ему полный доступ ко всем операциям СБИС.

Шаг 2. Настроить права внешнего приложения

Один из наиболее частых вопросов при интеграции — почему авторизация успешна, но конкретная команда API возвращает ошибку доступа.

Причина обычно не в токене. Токен подтверждает, что приложение авторизовано. Отдельно существуют права, которые определяют, что именно этому приложению разрешено делать.

Поэтому диагностику удобно разделять на два уровня:

Уровень 1
Credentials
app_client_id
app_secret
secret_key
        ↓
Авторизация
        ↓
Token

Уровень 2
Token + права приложения
        ↓
Конкретная команда API
        ↓
Доступ разрешён / запрещён

Это особенно важно для интеграций с 1С: приложение может успешно получить токен, но не иметь права выполнять отдельную операцию с документами или организацией.

Шаг 3. Получить app_client_id, app_secret и secret_key

После настройки приложения в его карточке доступны необходимые параметры. В конфигурации интеграции они будут выглядеть примерно так:

SBIS_APP_CLIENT_ID=...
SBIS_APP_SECRET=...
SBIS_SECRET_KEY=...

Здесь важно не перепутать название переменной с названием параметра API. Например, мы можем назвать переменную окружения SBIS_SECRET_KEY, но при формировании HTTP-запроса передать её значение как поле secret_key.

Эти значения нельзя хранить в публичном репозитории, передавать в браузер или выводить в обычный production-лог.

Шаг 4. Получить токен доступа

Для сервисной авторизации Saby указывает endpoint:

POST https://online.saby.ru/oauth/service/

Тело запроса передаётся в JSON и содержит три параметра:

{
    "app_client_id": "YOUR_APP_CLIENT_ID",
    "app_secret": "YOUR_APP_SECRET",
    "secret_key": "YOUR_SECRET_KEY"
}

Полный пример через cURL:

curl -X POST 'https://online.saby.ru/oauth/service/' \
    -H 'Content-Type: application/json; charset=utf-8' \
    -d '{
        "app_client_id": "YOUR_APP_CLIENT_ID",
        "app_secret": "YOUR_APP_SECRET",
        "secret_key": "YOUR_SECRET_KEY"
    }'

При успешной авторизации Saby возвращает данные, необходимые для дальнейшего обмена. В актуальной документации сервисной авторизации токен представлен полем token.

{
    "token": "YOUR_ACCESS_TOKEN"
}

В некоторых материалах и сценариях Saby встречается термин access_token. В конкретной реализации интеграции ориентируйтесь на фактический формат ответа используемого endpoint и актуальную документацию Saby.

Шаг 5. Передать токен в API-запросе

Полученный токен используется в заголовке:

X-SBISAccessToken: YOUR_ACCESS_TOKEN

Для API Gateway запросы выполняются по HTTP, а данные команды передаются в формате JSON-RPC. В текущей документации API Gateway используется endpoint версии API, например:

https://online.saby.ru/apigate/v1/

Базовая структура JSON-RPC-запроса:

{
    "jsonrpc": "2.0",
    "method": "METHOD.NAME",
    "params": {},
    "id": 1
}

Таким образом, минимальный HTTP-запрос состоит из endpoint, заголовка авторизации и JSON-RPC тела.

Первый тестовый запрос

После получения токена полезно сначала проверить сам контур авторизации, не подключая сразу бизнес-методы, документы и 1С.

curl -X POST 'https://online.saby.ru/apigate/v1/' \
    -H 'Content-Type: application/json; charset=utf-8' \
    -H 'X-SBISAccessToken: YOUR_ACCESS_TOKEN' \
    -d '{
        "jsonrpc": "2.0",
        "method": "APIGatewayObject.Echo",
        "params": {
            "message": "Hello world!"
        },
        "id": 1
    }'

Если тестовый вызов проходит, можно переходить к конкретному методу API. Это хороший диагностический приём: сначала проверяем транспорт и авторизацию, затем права, затем параметры бизнес-команды.

JSON-RPC: что находится внутри API-запроса

Для интегратора важно не смешивать две вещи: авторизацию и бизнес-команду. Заголовок сообщает API, каким токеном авторизован запрос, а тело описывает, какую команду нужно выполнить.

Поле Назначение
jsonrpc Версия протокола JSON-RPC
method Имя вызываемой команды
params Параметры конкретной команды
id Идентификатор запроса

Ответ также содержит JSON-структуру. При успешном выполнении результат находится в result, а при ошибке сервер возвращает объект error с кодом, сообщением и дополнительными данными.

{
    "jsonrpc": "2.0",
    "id": 1,
    "result": {}
}

Ошибочный ответ концептуально выглядит так:

{
    "jsonrpc": "2.0",
    "id": 1,
    "error": {
        "code": 123,
        "message": "Ошибка",
        "details": "Подробное описание",
        "data": "ErrorType"
    }
}

Сервисная и интерактивная авторизация — в чём разница

Saby поддерживает разные сценарии авторизации. Для backend-интеграции чаще всего нужен сервисный сценарий, но его нельзя автоматически применять к пользовательскому входу.

Сценарий Подход Участие пользователя
Фоновый обмен 1С ↔ СБИС Сервисная авторизация Не требуется
CRM ↔ СБИС Сервисная авторизация Не требуется
Серверная синхронизация документов Сервисная авторизация Не требуется
Пользователь входит в Saby через внешний сайт Интерактивный OAuth 2 Требуется

Интерактивный сценарий нужен тогда, когда приложение должно работать от имени пользователя и получить его согласие через браузер. Для серверного обмена 1С с СБИС обычно нет смысла заставлять пользователя регулярно проходить такой процесс.

Где хранить ключи СБИС в Symfony

В Symfony-проекте credentials лучше отделить от исходного кода приложения. Минимальный вариант — переменные окружения:

SBIS_APP_CLIENT_ID=...
SBIS_APP_SECRET=...
SBIS_SECRET_KEY=...

В конфигурации приложения эти значения можно передавать в сервис авторизации. В production вместо обычного файла окружения можно использовать секретное хранилище инфраструктуры, если оно доступно в проекте.

Особенно важно не делать так:

final class SbisClient
{
    private string $secretKey = 'very-secret-value';
}

И не добавлять реальные credentials в fixtures, README, тестовые конфигурации или примеры, которые затем попадут в публичный репозиторий.

Как разделить SbisAuthClient и SbisApiClient

Для небольшой интеграции можно начать с одного класса, но в production-коде удобнее разделить получение токена и выполнение API-команд.

final class SbisAuthClient
{
    public function getToken(): string
    {
        // POST /oauth/service/
        // app_client_id + app_secret + secret_key
    }
}

final class SbisApiClient
{
    public function call(string $method, array $params): array
    {
        // X-SBISAccessToken
        // JSON-RPC request
    }
}

Тогда бизнес-сервис не знает, как именно получается токен. Он работает с API-клиентом, а тот уже решает задачу авторизации.

CompanyService
      ↓
SbisApiClient
      ↓
TokenProvider
      ↓
Saby

Это особенно полезно, когда интеграция постепенно растёт: сначала нужны контрагенты, затем документы, ЭДО, статусы, события и другие команды API.

Не нужно получать новый токен перед каждым запросом

Плохая архитектура выглядит так:

API request
    ↓
получить token
    ↓
выполнить запрос
    ↓
получить token
    ↓
следующий запрос

Так делать не стоит. Авторизацию нужно выделить в отдельный компонент, который умеет переиспользовать действующие данные авторизации и получать новые только тогда, когда это действительно необходимо.

В документации Saby для сервисной авторизации указано ограничение: одновременно для приложения может быть открыто не более пяти активных сессий. При создании новой сессии сверх лимита самая старая завершается автоматически.

Поэтому массовое создание новых авторизаций из каждого worker или каждого HTTP-запроса — плохая идея ещё и с точки зрения эксплуатации.

Пять параллельных запросов — важный нюанс для интеграции

В документации API Saby отдельно указано ограничение на количество параллельных потоков: при большом числе одновременных вызовов система может ограничивать выполнение или блокировать сессию пользователя.

Поэтому если интеграция работает через очередь, недостаточно просто поставить Messenger или другой worker pool и увеличить количество consumers. Параллелизм запросов к Saby нужно контролировать.

Queue
 ├── Worker 1 ──→ Saby
 ├── Worker 2 ──→ Saby
 ├── Worker 3 ──→ Saby
 ├── Worker 4 ──→ Saby
 └── Worker 5 ──→ Saby

      controlled concurrency

Для больших обменов это лучше учитывать на уровне архитектуры, а не пытаться исправить проблему после появления блокировок.

Что делать, если токен перестал работать

Ошибку авторизации не стоит сразу трактовать как «СБИС не работает». Нужно определить, на каком этапе произошёл сбой.

Симптом Что проверить первым
Не получается получить токен app_client_id, app_secret, secret_key
Токен получен, но API его не принимает Заголовок X-SBISAccessToken и endpoint
Авторизация успешна, метод запрещён Права внешнего приложения
Работает вручную, не работает на сервере IP/адрес приложения, окружение, secrets
После увеличения worker появились проблемы Параллелизм и количество активных сессий
API отвечает ошибкой JSON-RPC method, params, id и формат запроса

Почему не стоит смешивать 401, права и ошибки метода

При диагностике удобно разделить ошибки на несколько уровней:

HTTP / transport
        ↓
Авторизация
        ↓
Права приложения
        ↓
JSON-RPC
        ↓
Параметры метода
        ↓
Бизнес-данные

Например, если credentials неверные, бессмысленно проверять структуру params. Если авторизация успешна, но конкретный раздел запрещён, изменение JSON-RPC тоже не решит проблему. И наоборот: корректный токен не исправит неправильное имя метода.

Retry: как повторять запросы правильно

Сетевые ошибки и временная недоступность внешнего API — нормальная часть интеграции. Но retry должен быть ограниченным и управляемым.

Business Command
      ↓
  Saby API
      │
      ├── success ─────────→ result
      │
      └── temporary error
                ↓
             retry #1
                ↓
             retry #2
                ↓
             retry #3
                ↓
              DLQ

Для production-интеграции полезно иметь как минимум:

  • ограниченное число повторов;
  • exponential backoff;
  • разделение временных и постоянных ошибок;
  • журналирование request id и технического контекста;
  • очередь проблемных сообщений;
  • идемпотентность бизнес-операций.

Сам токен при этом не должен автоматически обновляться на любую ошибку API. Если проблема в параметрах метода или правах, бесконечное получение новых токенов только усложнит диагностику.

Идемпотентность важнее, чем кажется

Представим интеграцию, которая отправляет документ из 1С в СБИС. Запрос завершился сетевым timeout. Интеграция не знает, был ли документ принят на стороне Saby.

Если просто повторить операцию, можно получить дубль или другое нежелательное состояние. Поэтому для критичных операций нужно хранить внешний идентификатор, состояние обмена и результат последней попытки.

1С
 ↓
Integration Service
 ↓
Operation ID
 ↓
Saby API
 ↓
┌─────────────────────────┐
│ success                 │
│ temporary error → retry │
│ permanent error → DLQ  │
└─────────────────────────┘

СБИС API и 1С: типовая архитектура

Если интеграция небольшая, 1С может напрямую обращаться к API. Но по мере роста количества методов появляется отдельный интеграционный слой.

┌──────────────────┐
│      1С:ERP      │
└────────┬─────────┘
         │
         ↓
┌────────────────────────────┐
│     Integration Layer      │
│                            │
│  Auth                       │
│  API Client                 │
│  Mapping                    │
│  Validation                 │
│  Retry                      │
│  Idempotency                │
│  Logging                    │
└────────────┬───────────────┘
             │
             ↓
┌────────────────────────────┐
│          Saby API           │
└────────────────────────────┘

В такой модели 1С не нужно знать детали авторизации и повторных запросов. Она передаёт бизнес-команду интеграционному сервису, а тот отвечает за технический контур.

Когда достаточно прямой интеграции 1С → СБИС

Прямой вызов из 1С может быть вполне разумным решением, если обмен небольшой:

  • одна конфигурация 1С;
  • небольшое количество методов;
  • небольшой объём данных;
  • нет сложной очереди;
  • нет нескольких внешних систем;
  • ошибки можно обрабатывать внутри прикладного решения.

Отдельный Integration Layer начинает окупаться, когда появляется несколько источников данных, много параллельных операций, сложные правила повторов, централизованное логирование или необходимость подключить к тому же СБИС API CRM, сайт и другие сервисы.

СБИС API: авторизация через Symfony HttpClient

В Symfony техническую часть можно реализовать через стандартный HTTP-клиент. Упрощённый вариант получения токена:

use Symfony\Contracts\HttpClient\HttpClientInterface;

final class SbisAuthClient
{
    public function __construct(
        private HttpClientInterface $httpClient,
        private string $appClientId,
        private string $appSecret,
        private string $secretKey,
    ) {
    }

    public function getToken(): string
    {
        $response = $this->httpClient->request(
            'POST',
            'https://online.saby.ru/oauth/service/',
            [
                'json' => [
                    'app_client_id' => $this->appClientId,
                    'app_secret' => $this->appSecret,
                    'secret_key' => $this->secretKey,
                ],
            ],
        );

        $data = $response->toArray();

        return $data['token'];
    }
}

Это именно технический пример. В production-коде вокруг него нужны обработка HTTP-ошибок, проверка структуры ответа, логирование без секретов и механизм повторного использования полученного токена.

Symfony API client для JSON-RPC

Следующий слой отвечает уже за выполнение команд:

final class SbisApiClient
{
    public function __construct(
        private HttpClientInterface $httpClient,
        private SbisTokenProvider $tokenProvider,
    ) {
    }

    public function call(string $method, array $params): array
    {
        $token = $this->tokenProvider->getToken();

        $response = $this->httpClient->request(
            'POST',
            'https://online.saby.ru/apigate/v1/',
            [
                'headers' => [
                    'X-SBISAccessToken' => $token,
                    'Content-Type' => 'application/json; charset=utf-8',
                ],
                'json' => [
                    'jsonrpc' => '2.0',
                    'method' => $method,
                    'params' => $params,
                    'id' => 1,
                ],
            ],
        );

        return $response->toArray();
    }
}

В реальном проекте значение id лучше генерировать или передавать из контекста конкретной операции, а URL версии API вынести в конфигурацию.

Как не засветить токен в логах

Типичная ошибка при отладке HTTP-интеграции — логировать весь request вместе с заголовками. Если в лог попадёт X-SBISAccessToken, технический журнал превращается в источник секретов.

В логах лучше сохранять:

  • название операции;
  • внутренний идентификатор сообщения;
  • метод API;
  • HTTP status;
  • код ошибки Saby;
  • время выполнения;
  • номер попытки.

Не следует сохранять в обычном техническом логе:

  • app_secret;
  • secret_key;
  • полный access token;
  • пароли;
  • полный HTTP request с секретными заголовками.

Типичные ошибки при настройке СБИС API

1. Перепутали app_secret и secret_key

Оба значения выглядят как секретные строки, поэтому их легко поменять местами. В конфигурации лучше использовать явные имена и не объединять их в одну переменную.

2. Токен получили, но забыли заголовок

X-SBISAccessToken: YOUR_ACCESS_TOKEN

Получить token недостаточно. Он должен передаваться в последующих запросах.

3. Дали приложению слишком много прав

Для интеграции лучше заранее определить необходимые операции и выдать только соответствующий доступ. Это одновременно упрощает безопасность и диагностику.

4. Получают токен перед каждым вызовом

Авторизация должна быть отдельным компонентом, а не частью каждой бизнес-операции. Иначе при большом обмене можно быстро получить лишнюю нагрузку и проблемы с сессиями.

5. Сразу запускают много параллельных workers

Для API-интеграции количество параллельных запросов нужно контролировать. Очередь сама по себе не гарантирует безопасную нагрузку на внешний API.

6. На любую ошибку запускают повторную авторизацию

Ошибка метода, ошибка прав и временный сетевой сбой — разные ситуации. Перед retry нужно определить класс ошибки.

7. Хранят секреты в .env.local, который случайно попадает в архив

Локальный файл удобен для разработки, но production credentials должны управляться контролируемым механизмом секретов.

Безопасность: минимальный checklist

Credentials app_secret и secret_key не находятся в Git.
Token Токен не выводится в обычные application logs.
Permissions Приложению выданы только необходимые права.
Network Разрешённые адреса и инфраструктурный доступ настроены явно.
Concurrency Количество параллельных API-вызовов контролируется.
Retry Повторные запросы ограничены и не создают дубли.

Как выглядит production-контур

Для корпоративной интеграции мы обычно разделяем бизнес-логику и технический обмен. Тогда архитектура получается примерно такой:

┌─────────────────────┐
│       1С:ERP        │
└──────────┬──────────┘
           │
           ↓
┌──────────────────────────────────┐
│        Integration Layer         │
│                                  │
│  Business Commands               │
│  Mapping                         │
│  Validation                      │
│          │                       │
│          ↓                       │
│  SbisApiClient                   │
│          │                       │
│          ├── TokenProvider       │
│          ├── Retry               │
│          ├── Idempotency         │
│          └── Logging             │
└────────────────┬─────────────────┘
                 │
                 ↓
┌──────────────────────────────────┐
│             Saby API             │
└──────────────────────────────────┘

Если к системе подключаются CRM, сайт, WMS или другие приложения, они могут использовать тот же интеграционный слой. Это позволяет не реализовывать авторизацию и retry отдельно в каждом клиенте.

СБИС API + 1С: что происходит при реальной операции

Возьмём практический сценарий: 1С должна получить данные контрагента по ИНН.

1. 1С получает ИНН
          ↓
2. Отправляет команду Integration Layer
          ↓
3. Integration Layer получает действующий token
          ↓
4. Формирует JSON-RPC
          ↓
5. Отправляет запрос в Saby
          ↓
6. Проверяет HTTP / API / business result
          ↓
7. Преобразует ответ в внутренний DTO
          ↓
8. Возвращает данные в 1С

Такой подход особенно полезен, если СБИС — не единственный внешний источник. Внутри системы можно иметь единый интерфейс получения сведений о контрагенте, а конкретные API СБИС, ФНС, Контур или других сервисов скрыть за адаптерами.

Авторизация — только первый этап интеграции

После того как token успешно получен, начинается основная работа: конкретные команды, преобразование данных, обработка ошибок и синхронизация состояния.

Поэтому полноценная интеграция обычно состоит из нескольких уровней:

Authentication
      ↓
API Client
      ↓
DTO / Mapping
      ↓
Business Service
      ↓
Queue
      ↓
Retry / DLQ
      ↓
Database / 1C

Чем больше систем участвует в обмене, тем сильнее становится ценность отдельного Integration Layer.

Минимальный MVP интеграции СБИС API

Если нужно не строить сразу большую платформу, а быстро запустить первую рабочую интеграцию, достаточно следующего набора:

1. Application Создать внешнее приложение в Saby.
2. Credentials Получить app_client_id, app_secret и secret_key.
3. Authentication Получать token через /oauth/service/.
4. API Client Передавать X-SBISAccessToken и выполнять JSON-RPC.
5. Error Handling Разделить временные и постоянные ошибки.
6. Reliability Добавить retry, идемпотентность и журналирование.

Что делать после первого успешного запроса

Не стоит сразу переносить в production код из тестового cURL-примера. После успешной авторизации желательно проверить весь технический контур:

  1. секреты вынесены из кода;
  2. токен не попадает в логи;
  3. права приложения минимальны;
  4. авторизация отделена от бизнес-логики;
  5. есть обработка HTTP-ошибок;
  6. есть обработка JSON-RPC error;
  7. retry ограничен;
  8. контролируется параллелизм;
  9. критичные операции защищены от дублей;
  10. есть мониторинг интеграции.

Итог: правильная схема авторизации СБИС API

┌──────────────────────────┐
│     Внешнее приложение   │
└────────────┬─────────────┘
             │
             │ app_client_id
             │ app_secret
             │ secret_key
             ↓
┌──────────────────────────┐
│  POST /oauth/service/    │
└────────────┬─────────────┘
             │
             ↓
┌──────────────────────────┐
│       access token       │
└────────────┬─────────────┘
             │
             │ X-SBISAccessToken
             ↓
┌──────────────────────────┐
│       Saby API           │
│       JSON-RPC           │
└────────────┬─────────────┘
             │
             ↓
┌──────────────────────────┐
│ Контрагенты / документы  │
│ ЭДО / данные / операции  │
└──────────────────────────┘

Сам процесс авторизации несложный. Сложность начинается в production: нужно правильно хранить секреты, ограничивать права, не создавать лишние сессии, контролировать параллельность, обрабатывать временные ошибки и не допускать дублей при повторной доставке сообщений.

Для небольшой интеграции достаточно аккуратного API-клиента. Для корпоративного обмена 1С ↔ СБИС разумно выделить Integration Layer, который будет отвечать за авторизацию, mapping, очереди, retry, idempotency и журналирование.

Читайте также: Как получить данные контрагента из СБИС API в JSON 1С OData: как работать с API 1С API Диадока: как интегрировать ЭДО с 1С и собственной системой EDI: что это такое и как интегрировать EDI с 1С LLM + SQL: почему нельзя давать нейросети прямой доступ к базе 1С