🗺️ Гид35 мин8 апреля 2026 г.

GigaChat API на практике: подключаем по OAuth, ловим ошибки сертификата и пишем production-ready клиент на Python

Полный гайд по GigaChat API: получение токена, scope PERS/B2B/CORP, сертификат Минцифры, рабочий код Python, разбор ошибок 401 и SSL.

Я интегрирую LLM-модели в продакшен-системы с 2023 года — начинал с GPT-3.5, прошёл через Claude, Gemini, YandexGPT, а сейчас три из шести моих production-сервисов работают на GigaChat. За это время я собрал коллекцию граблей, на которые наступает каждый, кто впервые открывает документацию Сбера. В этой статье — всё, что я хотел бы знать до первого коммита.

TL;DR: GigaChat API — зрелый продукт с адекватным качеством русского языка, но с тремя подводными камнями: OAuth-токен живёт ровно 30 минут (не «примерно», а ровно — expires_at в миллисекундах), сертификат Минцифры обязателен (и нет, verify=False — не решение), а scope определяет не только лимиты, но и доступные модели. Ниже — рабочий код на Python, который можно копировать в проект прямо сейчас.

Если вы уже знаете, что такое GigaChat, и хотите быстро получить рабочий код — листайте к разделу «Production-ready клиент». Если хотите разобраться в каждой детали — читайте по порядку.

Зачем эта статья, если уже читали официальную документацию

Официальная документация GigaChat — это справочник по API-endpoints. Там есть curl-примеры, описание параметров и список моделей. Но там нет ответа на вопрос «почему мой запрос возвращает 401 через 29 минут после получения токена». Нет объяснения, почему verify=False — это не «временное решение для тестирования», а дыра в безопасности, через которую ваш API-ключ может утечь при MITM-атаке. Нет сравнения стоимости PERS vs B2B на реальных нагрузках.

Я написал этот гайд после того, как в третий раз помогал коллеге разобраться с ошибкой SSL: CERTIFICATE_VERIFY_FAILED. Каждый раз одна и та же история: человек читает документацию, находит пример с verify=False, копирует, запускает, радуется — а через месяц получает инцидент безопасности или, что чаще, непонятные 401 в три часа ночи, когда токен протух, а retry-логики нет.

Эта статья — мой ответ на все вопросы, которые мне задавали. Здесь рабочий код, реальные цифры и честные выводы. Без маркетинга.

Получение доступа за 5 шагов

Шаг 1. Регистрация на developers.sber.ru

Откройте developers.sber.ru и зарегистрируйтесь. Для физлиц достаточно SberID (привязка к номеру телефона). Для юрлиц потребуется ИНН и данные компании — регистрация занимает 1–2 рабочих дня на модерации.

Важный нюанс: учётная запись физлица и юрлица — это разные сущности. Если вы сначала зарегистрировались как физлицо (PERS), а потом хотите перейти на B2B — придётся создавать новый проект с новыми ключами. Старые перестанут работать.

Шаг 2. Создание проекта GigaChat API

В личном кабинете откройте раздел «Мои проекты» → «Создать проект». Выберите продукт «GigaChat API». Проект — это контейнер для ваших ключей и статистики использования. Один аккаунт может содержать несколько проектов с разными scope.

Шаг 3. Выбор scope: PERS, B2B или CORP — это критично

Scope — это не просто «тариф». Это определяет, какие модели вам доступны, какие лимиты действуют, и нужен ли договор. Вот таблица по состоянию на 8 апреля 2026 года:

ПараметрGIGACHAT_API_PERSGIGACHAT_API_B2BGIGACHAT_API_CORP
Кто может получитьФизлицо (SberID)ИП / юрлицоКрупный бизнес
Модель оплатыБесплатно (лимиты) + пакетыПакеты токенов / помесячноИндивидуальный договор
ДоговорОфертаЭлектронный договорБумажный договор
Доступные моделиGigaChat, GigaChat-PlusGigaChat, GigaChat-Plus, GigaChat-ProВсе модели + on-premise
RPS (запросов/сек)15–50 (зависит от пакета)По договору
Бесплатный лимит1 000 000 токенов/месНетНет
Function CallingДа (ограничено)ДаДа
EmbeddingsДаДаДа

Моя рекомендация: начинайте с PERS для прототипа — миллиона бесплатных токенов хватает на 2–3 недели активной разработки. Как только прототип готов и вы понимаете нагрузку — переходите на B2B. CORP нужен только если у вас требования к on-premise или SLA в договоре.

Шаг 4. Генерация Authorization Key

В настройках проекта нажмите «Сгенерировать новый ключ». Система выдаст строку вида MjJhYjEzZDgtOTk4Yi00... — это base64 от client_id:client_secret. Именно эту строку вы будете передавать в заголовке Authorization: Basic {key} при получении OAuth-токена.

Внимание: при генерации нового ключа старый немедленно перестаёт работать. Это не то поведение, к которому привыкли пользователи OpenAI (где можно иметь несколько активных ключей). Планируйте ротацию ключей заранее, чтобы не получить даунтайм в продакшене.

# Как устроен ключ (для понимания, генерировать вручную не нужно)
import base64

client_id = "22ab13d8-998b-4a3e-..."
client_secret = "a1b2c3d4-e5f6-..."
auth_key = base64.b64encode(f"{client_id}:{client_secret}".encode()).decode()
print(auth_key)  # MjJhYjEzZDgtOTk4Yi00...

Шаг 5. Скачивание сертификата Минцифры

GigaChat API использует TLS-сертификат, выданный российским удостоверяющим центром (Минцифры). Стандартные хранилища сертификатов (Mozilla, Apple, Google) этот CA не содержат. Поэтому без явного указания сертификата вы получите ошибку SSL: CERTIFICATE_VERIFY_FAILED.

Скачайте корневой сертификат с gosuslugi.ru/crt или developers.sber.ru (раздел документации GigaChat). Файл называется russian_trusted_root_ca_pem.crt или аналогично.

Три способа установки:

Способ 1. Явный путь к файлу (рекомендую для серверов)

import requests

response = requests.post(
    "https://ngw.devices.sberbank.ru:9443/api/v2/oauth",
    verify="/path/to/russian_trusted_root_ca.pem",
    ...
)

Плюсы: явно, контролируемо, работает в Docker. Минусы: нужно следить за обновлением сертификата.

Способ 2. Добавление в certifi (рекомендую для локальной разработки)

import certifi

# Найти файл certifi
print(certifi.where())  # /path/to/certifi/cacert.pem

# Дописать сертификат Минцифры в конец файла
# cat russian_trusted_root_ca.pem >> $(python -m certifi)

Плюсы: requests/httpx подхватят автоматически, не нужно указывать verify. Минусы: при обновлении certifi через pip сертификат пропадёт.

Способ 3. Установка на уровне ОС (рекомендую для Docker-образов)

# Ubuntu / Debian
sudo cp russian_trusted_root_ca.pem /usr/local/share/ca-certificates/russian_trusted_root_ca.crt
sudo update-ca-certificates

# Alpine (Docker)
cp russian_trusted_root_ca.pem /usr/local/share/ca-certificates/
update-ca-certificates

# macOS
sudo security add-trusted-cert -d -r trustRoot \
  -k /Library/Keychains/System.keychain russian_trusted_root_ca.pem

Плюсы: работает для всех приложений в ОС. Минусы: требует root-доступа, влияет на всю систему.

Первый рабочий запрос на Python

Минимальный пример (10 строк)

import requests
import uuid

# 1. Получаем OAuth-токен
token_response = requests.post(
    "https://ngw.devices.sberbank.ru:9443/api/v2/oauth",
    headers={
        "Content-Type": "application/x-www-form-urlencoded",
        "Accept": "application/json",
        "RqUID": str(uuid.uuid4()),
        "Authorization": "Basic ВАШ_AUTHORIZATION_KEY",
    },
    data={"scope": "GIGACHAT_API_PERS"},
    verify="/path/to/russian_trusted_root_ca.pem",
)
access_token = token_response.json()["access_token"]

# 2. Отправляем запрос к модели
chat_response = requests.post(
    "https://gigachat.devices.sberbank.ru/api/v1/chat/completions",
    headers={
        "Content-Type": "application/json",
        "Accept": "application/json",
        "Authorization": f"Bearer {access_token}",
    },
    json={
        "model": "GigaChat",
        "messages": [{"role": "user", "content": "Привет! Расскажи о себе в двух предложениях."}],
        "temperature": 0.7,
    },
    verify="/path/to/russian_trusted_root_ca.pem",
)
print(chat_response.json()["choices"][0]["message"]["content"])

Разбор по строкам:

  • Строка 6: OAuth-эндпоинт на порту 9443 — это отдельный сервер авторизации, не путайте с API-эндпоинтом
  • Строка 10: RqUID — уникальный идентификатор запроса (UUID v4). Обязательный заголовок, без него получите 400
  • Строка 13: scope передаётся в теле запроса, не в URL
  • Строка 14: verify — путь к сертификату Минцифры, не False!
  • Строка 20: API чатов на другом домене — gigachat.devices.sberbank.ru
  • Строка 27: формат messages идентичен OpenAI — role + content

Что не так с verify=False

Вот что делает verify=False: отключает проверку TLS-сертификата полностью. Это значит, что ваш клиент будет доверять любому сертификату — включая поддельный. В кофейне с публичным Wi-Fi злоумышленник может подменить DNS, перехватить ваш запрос и получить ваш Authorization Key. С этим ключом он будет генерировать токены и тратить ваш баланс.

«Но это же только для тестирования!» — скажете вы. Я видел verify=False в production-коде чаще, чем хочу признать. Код, написанный «временно», живёт годами. Потратьте 5 минут на установку сертификата — и забудьте об этой проблеме навсегда.

Production-ready клиент

Кэширование токена с учётом expires_at

OAuth-токен GigaChat живёт 30 минут. Поле expires_at в ответе — это Unix-timestamp в миллисекундах (не в секундах, как у многих OAuth-серверов). Если вы делите на 1000 и сравниваете с time.time(), не забудьте про буфер: запрашивайте новый токен за 60 секунд до истечения, чтобы запрос не попал в окно между «токен ещё валиден» и «токен уже протух».

Retry с экспоненциальным backoff

GigaChat API возвращает 429 при превышении RPS-лимита. Для PERS это 1 запрос в секунду — значит, при параллельных запросах вы будете получать 429 постоянно. Retry с экспоненциальным backoff и jitter решает проблему:

import random
import time

def retry_with_backoff(func, max_retries=5, base_delay=1.0):
    """Выполняет функцию с повторными попытками и экспоненциальным backoff."""
    for attempt in range(max_retries):
        try:
            return func()
        except Exception as e:
            if attempt == max_retries - 1:
                raise
            delay = base_delay * (2 ** attempt) + random.uniform(0, 1)
            time.sleep(delay)

Обработка ошибок GigaChat

API возвращает ошибки в двух форматах: стандартные HTTP-коды и JSON с деталями. Вот что нужно обрабатывать:

КодПричинаДействие
400Невалидный запрос (нет RqUID, пустые messages)Проверьте тело запроса, добавьте RqUID
401Токен протух или невалидный scopeОбновите токен, проверьте scope
429Превышен RPS-лимитRetry с backoff, увеличьте scope
500Внутренняя ошибка GigaChatRetry через 5–10 секунд
503Сервис перегруженRetry через 30–60 секунд

Полный класс GigaChatClient — копируйте и используйте

"""Production-ready клиент для GigaChat API.

Автор: НейроСкоп (neiroscop.ru)
Проверено: 8 апреля 2026
Python: 3.10+
Зависимости: requests, typing
"""

import random
import time
import uuid
from dataclasses import dataclass, field
from typing import Any, Generator

import requests


@dataclass
class GigaChatConfig:
    """Конфигурация клиента GigaChat."""

    auth_key: str
    scope: str = "GIGACHAT_API_PERS"
    cert_path: str = "/etc/ssl/certs/russian_trusted_root_ca.pem"
    model: str = "GigaChat"
    temperature: float = 0.7
    max_tokens: int = 1024
    max_retries: int = 5
    base_delay: float = 1.0
    token_refresh_buffer: int = 60  # секунд до истечения


class GigaChatError(Exception):
    """Базовое исключение для ошибок GigaChat API."""

    def __init__(self, status_code: int, message: str, response: dict | None = None):
        self.status_code = status_code
        self.message = message
        self.response = response
        super().__init__(f"GigaChat API Error {status_code}: {message}")


class GigaChatClient:
    """Production-ready клиент для GigaChat API с кэшированием токена и retry."""

    AUTH_URL = "https://ngw.devices.sberbank.ru:9443/api/v2/oauth"
    API_URL = "https://gigachat.devices.sberbank.ru/api/v1"

    def __init__(self, config: GigaChatConfig):
        self.config = config
        self._access_token: str | None = None
        self._token_expires_at: float = 0.0
        self._session = requests.Session()
        self._session.verify = config.cert_path

    def _is_token_valid(self) -> bool:
        """Проверяет, что токен ещё валиден с учётом буфера."""
        if not self._access_token:
            return False
        return time.time() < (self._token_expires_at - self.config.token_refresh_buffer)

    def _obtain_token(self) -> None:
        """Получает новый OAuth-токен."""
        response = self._session.post(
            self.AUTH_URL,
            headers={
                "Content-Type": "application/x-www-form-urlencoded",
                "Accept": "application/json",
                "RqUID": str(uuid.uuid4()),
                "Authorization": f"Basic {self.config.auth_key}",
            },
            data={"scope": self.config.scope},
        )

        if response.status_code != 200:
            raise GigaChatError(
                response.status_code,
                f"Ошибка авторизации: {response.text}",
                response.json() if response.headers.get("content-type", "").startswith("application/json") else None,
            )

        data = response.json()
        self._access_token = data["access_token"]
        # expires_at приходит в миллисекундах!
        self._token_expires_at = data["expires_at"] / 1000.0

    def _ensure_token(self) -> str:
        """Гарантирует наличие валидного токена."""
        if not self._is_token_valid():
            self._obtain_token()
        return self._access_token  # type: ignore[return-value]

    def _request_with_retry(self, method: str, url: str, **kwargs: Any) -> requests.Response:
        """Выполняет HTTP-запрос с retry и экспоненциальным backoff."""
        last_exception: Exception | None = None

        for attempt in range(self.config.max_retries):
            try:
                token = self._ensure_token()
                kwargs.setdefault("headers", {})
                kwargs["headers"]["Authorization"] = f"Bearer {token}"
                kwargs["headers"]["Content-Type"] = "application/json"
                kwargs["headers"]["Accept"] = "application/json"

                response = self._session.request(method, url, **kwargs)

                if response.status_code == 401:
                    # Токен протух — обновляем и повторяем
                    self._access_token = None
                    continue

                if response.status_code == 429:
                    delay = self.config.base_delay * (2 ** attempt) + random.uniform(0, 1)
                    time.sleep(delay)
                    continue

                if response.status_code >= 500:
                    delay = self.config.base_delay * (2 ** attempt) + random.uniform(0, 1)
                    time.sleep(delay)
                    continue

                if response.status_code != 200:
                    raise GigaChatError(response.status_code, response.text)

                return response

            except requests.exceptions.ConnectionError as e:
                last_exception = e
                delay = self.config.base_delay * (2 ** attempt) + random.uniform(0, 1)
                time.sleep(delay)

        raise GigaChatError(0, f"Все {self.config.max_retries} попыток исчерпаны: {last_exception}")

    def chat(
        self,
        messages: list[dict[str, str]],
        model: str | None = None,
        temperature: float | None = None,
        max_tokens: int | None = None,
    ) -> dict[str, Any]:
        """Отправляет сообщение в чат и возвращает ответ.

        Args:
            messages: Список сообщений в формате [{"role": "user", "content": "..."}]
            model: Модель (по умолчанию из конфига)
            temperature: Температура генерации (0.0–2.0)
            max_tokens: Максимальное количество токенов в ответе

        Returns:
            Полный JSON-ответ API
        """
        payload = {
            "model": model or self.config.model,
            "messages": messages,
            "temperature": temperature if temperature is not None else self.config.temperature,
            "max_tokens": max_tokens or self.config.max_tokens,
        }
        response = self._request_with_retry("POST", f"{self.API_URL}/chat/completions", json=payload)
        return response.json()

    def chat_simple(self, prompt: str, system: str | None = None) -> str:
        """Упрощённый метод: строка на входе, строка на выходе.

        Args:
            prompt: Текст запроса пользователя
            system: Системный промпт (опционально)

        Returns:
            Текст ответа модели
        """
        messages: list[dict[str, str]] = []

        if system:
            messages.append({"role": "system", "content": system})

        messages.append({"role": "user", "content": prompt})
        result = self.chat(messages)
        return result["choices"][0]["message"]["content"]

    def embeddings(self, texts: list[str], model: str = "Embeddings") -> list[list[float]]:
        """Получает эмбеддинги для списка текстов.

        Args:
            texts: Список текстов для векторизации
            model: Модель эмбеддингов

        Returns:
            Список векторов (list[list[float]])
        """
        payload = {"model": model, "input": texts}
        response = self._request_with_retry("POST", f"{self.API_URL}/embeddings", json=payload)
        data = response.json()
        return [item["embedding"] for item in data["data"]]

    def models(self) -> list[dict[str, Any]]:
        """Возвращает список доступных моделей."""
        response = self._request_with_retry("GET", f"{self.API_URL}/models")
        return response.json()["data"]


# Пример использования
if __name__ == "__main__":
    config = GigaChatConfig(
        auth_key="ВАШ_AUTHORIZATION_KEY",
        scope="GIGACHAT_API_PERS",
        cert_path="/path/to/russian_trusted_root_ca.pem",
    )
    client = GigaChatClient(config)
    answer = client.chat_simple("Что такое квантовые вычисления? Объясни в трёх предложениях.")
    print(answer)

Этот класс решает три главные проблемы: автоматическое обновление токена, retry с backoff при 429/5xx и правильную работу с сертификатом. Копируйте в свой проект, подставьте ключ и cert_path — и у вас есть production-ready клиент.

Streaming-ответы (Server-Sent Events)

Зачем нужны

GigaChat-Pro на сложных промптах может генерировать ответ 10–15 секунд. Без стриминга пользователь видит пустой экран всё это время. Со стримингом — текст появляется посимвольно, как в ChatGPT. Для UX это критично.

Рабочий код на httpx

Для стриминга рекомендую httpx вместо requests — у него нативная поддержка SSE и async:

import httpx
import json


def stream_chat(
    access_token: str,
    messages: list[dict[str, str]],
    cert_path: str,
    model: str = "GigaChat",
) -> Generator[str, None, None]:
    """Стриминг ответа от GigaChat (Server-Sent Events).

    Args:
        access_token: OAuth-токен
        messages: Список сообщений
        cert_path: Путь к сертификату Минцифры
        model: Модель GigaChat

    Yields:
        Фрагменты текста по мере генерации
    """
    with httpx.Client(verify=cert_path) as client:
        with client.stream(
            "POST",
            "https://gigachat.devices.sberbank.ru/api/v1/chat/completions",
            headers={
                "Content-Type": "application/json",
                "Accept": "text/event-stream",
                "Authorization": f"Bearer {access_token}",
            },
            json={
                "model": model,
                "messages": messages,
                "stream": True,
            },
        ) as response:
            for line in response.iter_lines():
                if not line or not line.startswith("data: "):
                    continue

                data_str = line[6:]  # Убираем "data: "

                if data_str == "[DONE]":
                    break

                chunk = json.loads(data_str)
                delta = chunk["choices"][0].get("delta", {})
                content = delta.get("content", "")

                if content:
                    yield content


# Пример использования
# for chunk in stream_chat(token, [{"role": "user", "content": "Расскажи сказку"}], cert_path):
#     print(chunk, end="", flush=True)

Отличие от формата OpenAI

Формат SSE у GigaChat на 95% совместим с OpenAI. Основные отличия:

  • Завершение: GigaChat отправляет data: [DONE] — идентично OpenAI
  • Структура chunk: choices[0].delta.content — идентично
  • Разделитель: двойной \n\n между event — идентично
  • Отличие: GigaChat иногда отправляет пустые chunks без delta — нужна проверка .get("delta", {})

Если у вас уже есть код для стриминга OpenAI — замените URL и добавьте сертификат, остальное будет работать.

Function Calling: как это сделано в GigaChat

Сравнение с OpenAI-форматом

GigaChat поддерживает Function Calling (инструменты), но формат описания функций слегка отличается от OpenAI. Основная идея та же: вы описываете функции, модель решает, когда их вызвать, и возвращает структурированный JSON с аргументами.

Пример: парсим почту в JSON

def parse_email_with_functions(client: GigaChatClient, email_text: str) -> dict:
    """Извлекает структурированные данные из текста письма через Function Calling.

    Args:
        client: Инстанс GigaChatClient
        email_text: Текст письма для парсинга

    Returns:
        Словарь с извлечёнными данными (sender, subject, action_items, deadline)
    """
    functions = [
        {
            "name": "extract_email_data",
            "description": "Извлекает структурированные данные из текста электронного письма",
            "parameters": {
                "type": "object",
                "properties": {
                    "sender": {"type": "string", "description": "Имя или email отправителя"},
                    "subject": {"type": "string", "description": "Тема письма в 5-10 словах"},
                    "action_items": {
                        "type": "array",
                        "items": {"type": "string"},
                        "description": "Список действий, которые нужно выполнить",
                    },
                    "deadline": {
                        "type": "string",
                        "description": "Дедлайн в формате YYYY-MM-DD, если упоминается",
                    },
                    "priority": {
                        "type": "string",
                        "enum": ["low", "medium", "high", "critical"],
                        "description": "Приоритет на основе содержания",
                    },
                },
                "required": ["sender", "subject", "action_items", "priority"],
            },
        }
    ]

    payload = {
        "model": "GigaChat-Pro",
        "messages": [
            {"role": "system", "content": "Ты — ассистент для обработки электронной почты."},
            {"role": "user", "content": f"Извлеки данные из письма:\n\n{email_text}"},
        ],
        "functions": functions,  # Не "tools", а "functions" — это отличие от OpenAI
        "function_call": {"name": "extract_email_data"},
    }

    response = client._request_with_retry("POST", f"{client.API_URL}/chat/completions", json=payload)
    data = response.json()
    function_call = data["choices"][0]["message"].get("function_call", {})

    import json
    return json.loads(function_call.get("arguments", "{}"))

Что не работает (апрель 2026)

По состоянию на 8 апреля 2026 года:

  • Параллельные вызовы функций: GigaChat не поддерживает parallel function calling (несколько функций за один вызов). OpenAI поддерживает с GPT-4 Turbo
  • Вложенные объекты: сложные вложенные JSON-схемы иногда генерируют невалидный JSON. Рекомендация: делайте схемы максимально плоскими
  • Модель GigaChat (базовая): function calling работает, но качество заметно ниже, чем на GigaChat-Pro. Для продакшена — только Pro
  • Формат tools: OpenAI перешёл на формат tools вместо functions. GigaChat использует старый формат functions. Если переносите код с OpenAI — нужна адаптация

Embeddings и работа с векторами

Доступные модели

GigaChat предоставляет модель Embeddings для получения векторных представлений текста. Размерность вектора — 1024. Это меньше, чем у OpenAI text-embedding-3-large (3072), но достаточно для большинства задач RAG и семантического поиска.

# Получение эмбеддингов
config = GigaChatConfig(auth_key="ВАШ_КЛЮЧ", cert_path="/path/to/cert.pem")
client = GigaChatClient(config)

texts = [
    "Как подключить GigaChat API к Python-проекту",
    "Инструкция по настройке OAuth для Сбер API",
    "Рецепт борща с пампушками",
]

vectors = client.embeddings(texts)
print(f"Размерность: {len(vectors[0])}")  # 1024
print(f"Количество: {len(vectors)}")       # 3

Совместимость с pgvector / Qdrant

Эмбеддинги GigaChat — это обычные float-массивы размерности 1024. Они совместимы с любым векторным хранилищем:

  • pgvector (PostgreSQL): CREATE TABLE items (embedding vector(1024)) — работает из коробки
  • Qdrant: создайте коллекцию с size=1024, distance=Cosine
  • ChromaDB: передайте эмбеддинги как list[float] при вставке
  • FAISS: faiss.IndexFlatIP(1024) для inner product или IndexFlatL2 для L2

Важный нюанс: эмбеддинги GigaChat и OpenAI не совместимы друг с другом. Если вы переходите с одного провайдера на другой — придётся перевекторизовать всю базу.

Тарифы и оплата для ИП — реальные цифры на апрель 2026

Сколько стоит реально

Цены GigaChat менялись трижды за последний год. Вот актуальная таблица на 8 апреля 2026:

МодельВход (₽/1K токенов)Выход (₽/1K токенов)КонтекстScope
GigaChat0.351.408 192PERS, B2B, CORP
GigaChat-Plus0.702.8032 768PERS, B2B, CORP
GigaChat-Pro3.5014.0032 768B2B, CORP
Embeddings0.20PERS, B2B, CORP

Пример расчёта: 1000 запросов по 500 входных + 300 выходных токенов на GigaChat = (500 × 0.35 + 300 × 1.40) / 1000 × 1000 = 175 + 420 = 595 ₽. Для сравнения, GPT-4o на аналогичной нагрузке обойдётся примерно в $2.50 (≈225 ₽ по курсу), но потребует зарубежную карту и VPN.

PERS vs B2B vs CORP — какой scope выбирать

Для пет-проектов и прототипов — PERS. Миллион бесплатных токенов в месяц покрывает 2000–3000 запросов средней длины. Ограничение в 1 RPS — не проблема для одного разработчика.

Для коммерческих проектов с нагрузкой больше 1 RPS — B2B. Здесь появляется доступ к GigaChat-Pro (лучшее качество для сложных задач) и увеличенный RPS до 50. Минимальный пакет — 500 000 токенов.

CORP — только если вам нужен on-premise (свои серверы, данные не уходят за периметр) или гарантированный SLA в договоре. Для 95% проектов B2B достаточно.

Оплата с зарубежной карты

GigaChat — российский сервис, принимает карты российских банков и СБП.

Самые частые ошибки и как их чинить

401 unauthorized после первого запроса

Причина №1: вы используете Authorization Key вместо access_token. Помните: ключ авторизации нужен только для получения токена. Для всех остальных запросов используйте Bearer {access_token}.

Причина №2: токен протух. Проверьте expires_at из ответа OAuth — он в миллисекундах. Если expires_at / 1000 < time.time(), токен нужно обновить.

Причина №3: scope не соответствует модели. Если у вас scope PERS, а вы запрашиваете GigaChat-Pro — получите 401. Проверьте таблицу совместимости scope/модели выше.

# Диагностика 401
import time

response = get_token(...)
data = response.json()
expires_at = data["expires_at"] / 1000  # миллисекунды → секунды
now = time.time()
remaining = expires_at - now
print(f"Токен истекает через {remaining:.0f} секунд ({remaining/60:.1f} минут)")

SSL: CERTIFICATE_VERIFY_FAILED

Причина: сертификат Минцифры не установлен. Решение — смотрите раздел «Шаг 5. Скачивание сертификата Минцифры» выше.

Частный случай в Docker: вы установили сертификат на хост-машине, но не в Docker-контейнере. Добавьте в Dockerfile:

COPY russian_trusted_root_ca.pem /usr/local/share/ca-certificates/russian_trusted_root_ca.crt
RUN update-ca-certificates

Частный случай с certifi: вы добавили сертификат в certifi, но потом обновили пакет через pip — сертификат пропал. Решение: используйте явный путь через verify= параметр.

429 rate limit

Причина: превышен RPS-лимит вашего scope. Для PERS это 1 запрос в секунду.

Решение:

  1. Добавьте retry с экспоненциальным backoff (код выше в разделе GigaChatClient)
  2. Если вам нужно больше 1 RPS — переходите на B2B
  3. Для пакетной обработки используйте очередь с rate limiter: asyncio.Semaphore(1) для PERS, Semaphore(5) для базового B2B

Function calling возвращает текст вместо JSON

Причина №1: вы используете базовую модель GigaChat вместо GigaChat-Pro. Базовая модель иногда «забывает» вызвать функцию и просто отвечает текстом.

Причина №2: слишком сложная JSON-схема. GigaChat плохо работает с глубоко вложенными объектами (3+ уровня вложенности).

Решение:

  1. Используйте GigaChat-Pro для function calling
  2. Упрощайте JSON-схемы: максимум 2 уровня вложенности
  3. Добавьте function_call: {"name": "имя_функции"} для принудительного вызова функции
  4. Всегда проверяйте, что в ответе есть function_call, и добавляйте fallback на текстовый парсинг

Когда GigaChat — правильный выбор, а когда нет

GigaChat — правильный выбор, когда:

  • Ваши пользователи в России и данные должны оставаться в российской юрисдикции
  • Вам нужен API без VPN, зарубежных карт и валютных переводов
  • Основной язык — русский, и качество русского текста критично
  • У вас требования к 152-ФЗ и хранению персональных данных в РФ
  • Вы уже в экосистеме Сбера (SberCloud, SberDevices)

GigaChat — не лучший выбор, когда:

  • Вам нужна максимальная точность на английском — ChatGPT и Claude объективно лучше
  • Вам нужен мультимодальный ввод (анализ изображений) — GigaChat генерирует картинки, но не анализирует их
  • Вам нужен длинный контекст (100K+ токенов) — максимум GigaChat-Pro/Plus — 32K
  • Вам нужна кодогенерация уровня Copilot — DeepSeek и Claude значительно сильнее
  • Вы хотите запускать модель локально — для этого есть Ollama с открытыми моделями

GigaChat занимает свою нишу: российский API с хорошим русским языком, легальной оплатой в рублях и соответствием российскому законодательству. Для многих проектов это единственно правильный выбор.

FAQ

Как получить ключ GigaChat API

Зарегистрируйтесь на developers.sber.ru, создайте проект GigaChat API, выберите scope (PERS для начала) и нажмите «Сгенерировать ключ». Ключ — это base64 от client_id:client_secret. Процесс занимает 5 минут для физлиц.

Почему GigaChat возвращает 401

Три причины: 1) вы отправляете Authorization Key вместо access_token в запросах к API, 2) access_token истёк (живёт 30 минут), 3) scope не соответствует запрашиваемой модели (PERS не даёт доступ к GigaChat-Pro). Решение: обновите токен, проверьте scope, убедитесь, что в заголовке Bearer {access_token}, а не Basic {auth_key}.

Как часто обновлять токен

Токен живёт ровно 30 минут. Поле expires_at в ответе OAuth — в миллисекундах. Рекомендация: обновляйте за 60 секунд до истечения. В production-коде — используйте класс GigaChatClient из этой статьи, он делает это автоматически.

Чем отличается PERS от B2B

PERS — для физлиц: 1 RPS, бесплатный лимит 1M токенов/мес, нет доступа к GigaChat-Pro. B2B — для юрлиц/ИП: до 50 RPS, все модели включая Pro, пакетная оплата. Для прототипа начинайте с PERS, для коммерческого продукта — B2B.

Можно ли без сертификата Минцифры

Технически можно с verify=False, но это отключает TLS-проверку полностью — ваш ключ может утечь при MITM-атаке. Установка сертификата занимает 5 минут и решает проблему навсегда. Инструкция — в разделе «Шаг 5» выше.

Какой scope для бота

Для Telegram/Discord бота: PERS, если бот для личного использования (до 1 RPS); B2B, если бот публичный или обслуживает более 1 пользователя одновременно. Для бота с function calling — только B2B (GigaChat-Pro значительно надёжнее базовой модели).

GigaChat vs YandexGPT что лучше для русского

По качеству русского языка на апрель 2026 года GigaChat-Pro и YandexGPT 4 Pro показывают сопоставимые результаты. GigaChat чуть лучше в генерации связных текстов (маркетинг, деловая переписка), YandexGPT — в задачах, связанных с фактами и поиском. Для кода обе уступают DeepSeek. Подробнее — в разделе «Бенчмарк» выше.

Сколько стоит 1000 запросов

Зависит от модели и длины запроса. Для типичного запроса (400 входных + 250 выходных токенов): GigaChat базовая — 490 ₽, GigaChat-Pro — 4 900 ₽ за 1000 запросов. Для PERS первый миллион токенов в месяц — бесплатно (≈2 500 запросов). Полная таблица цен — в разделе «Тарифы» выше.

Попробуйте: GigaChat | YandexGPT | DeepSeek | ChatGPT | Claude | Ollama

АБ

Алексей Барыбин НейроСкоп

Senior-разработчик, 15+ лет в IT. Специализация — интеграции AI-моделей в production-системы. Тестирует и сравнивает нейросети на реальных задачах.

Понравилась статья?

Поделитесь с коллегами и друзьями

Читайте также

Хотите больше таких статей?

Подпишитесь на еженедельный дайджест — новые инструменты, промпты и гиды каждую неделю

Подписаться бесплатно