Socrate StoreRESELLER API
REST / v1OpenAPI
ИНТЕГРАЦИЯ ДЛЯ РЕСЕЛЛЕРОВ

Socrate Store API

Каталог, баланс и закупка товаров из вашего магазина. Один запрос оформляет заказ, списывает деньги и возвращает доступный товар. Разрешённые предзаказы выдаются после поступления.

BASE URLhttps://api.socrate.store
Авторизация
X-API-Key
Деньги
RUB · копейки
Данные
JSON / UTF-8
Выдача
Текст · предзаказы

API работает между серверами. Покупатель платит вашему магазину, а закупка списывается с вашего баланса в Socrate Store.

01

Быстрый старт

Сначала проверьте доступ и баланс. Этот запрос ничего не покупает.

  1. 1

    Получите API-ключ

    Откройте в боте «Профиль → API для реселлеров → Получить API-ключ» и подтвердите создание. Одобрение администратора не требуется. Команда /requestapi открывает тот же раздел.

  2. 2

    Пополните баланс

    Используется баланс того же аккаунта в боте. API не создаёт отдельный кошелёк.

  3. 3

    Проверьте подключение

    Сохраните ключ в переменной окружения SOCRATE_API_KEY на своём сервере.

curl --fail-with-body 'https://api.socrate.store/v1/account' \
  -H "X-API-Key: $SOCRATE_API_KEY"
Пример ответа · 200 OK
{
  "user_id": 123456789,
  "active": true,
  "currency": "RUB",
  "balance_minor": 50000,
  "max_quantity": 100,
  "rate_limit_per_minute": 60,
  "accept_preorders": false
}

Числа и товары в примерах условные. 50000 копеек = 500 ₽. Python использует стандартную библиотеку; Node.js — встроенный fetch (18+). Пример cURL рассчитан на Bash.

02

Доступ и ключи

Каждый реселлер получает собственный ключ, привязанный к его Telegram-аккаунту. Все методы /v1/ требуют этот заголовок:

X-API-Key: sr_YOUR_SECRET_KEY

Первое подключение

Зарегистрируйтесь командой /start и откройте «Профиль → API для реселлеров». Доступ открыт зарегистрированным пользователям без блокировки аккаунта или отзыва API-доступа. Нажмите «Получить API-ключ» и подтвердите. Бот отправит ключ только в ваш личный чат; повторное получение не заменяет уже выданный ключ.

Замена ключа

В том же разделе нажмите «Заменить API-ключ» и подтвердите. Старый ключ перестанет работать, новый придёт в личный чат. Самостоятельная замена доступна не чаще раза в минуту. Администратор может отозвать доступ; получить новый ключ в обход отзыва нельзя.

Ключ — только на вашем сервере

Не вставляйте его в браузерный JavaScript, URL, публичный код или логи. Храните ключ в секретах сервера. При утечке замените ключ в профиле бота и обновите интеграцию. Для отключения доступа обратитесь к администратору.

Блокировка аккаунта в магазине или отзыв API-доступа запрещают новые API-запросы. При 401 проверьте ключ; при 403 свяжитесь с администратором. Настройки предзаказов доступны через /api_settings в боте или PATCH /v1/account/settings.

03

Схема подключения

Ваш сервер отвечает за заказ покупателя и свою наценку. Socrate Store отвечает за закупку и выдачу доступного товара.

SERVER-TO-SERVER
Ваш серверБот или сайт реселлераX-API-Key
HTTPSJSON
Socrate APIПроверка ключа и запроса/v1/orders
ТранзакцияВсё или ничего
МагазинБаланс · заказ · товарCOMMIT
Ответ возвращает order_id и items[].content. Ваш сервер сохраняет их и выдаёт товар покупателю.

Публичная граница

Интеграция обращается только к HTTPS-адресу API. Прямой доступ к базе магазина не нужен и не предоставляется.

Граница ответственности

Успешная закупка не подтверждает оплату в вашем магазине. Проверка платежа клиента и защита от повторной выдачи клиенту остаются на вашей стороне.

04

Методы API

Адреса ниже добавляются к https://api.socrate.store. Ключ передаётся в каждом запросе.

PATCH /v1/account/settings — настройка приёма предзаказов своего аккаунта. Тело: {"accept_preorders": false} для отключения или true для включения.

Машиночитаемая спецификация: скачать OpenAPI 3.0. Браузерная отправка запросов с ключом на этой странице не предусмотрена.

05

Каталог и цены

GET/v1/products?language=ru

По умолчанию возвращается русский текст. Для английского передайте language=en. Если перевод товара не заполнен, используется русский текст.

Пример ответа · 200 OK
{
  "products": [{
    "sku": "g-7",
    "name": "Пример товара",
    "description": "Описание товара",
    "currency": "RUB",
    "unit_price_minor": 7900,
    "shop_unit_price_minor": 7900,
    "available_quantity": 20,
    "min_quantity": 1,
    "max_quantity": 100,
    "bulk_discounts": [{"min_quantity": 5, "percent": "5.00"}],
    "personal_discounts": [],
    "pricing_mode": "public",
    "fixed_price_expired": false,
    "preorder_enabled": true,
    "preorder_available": false,
    "delivery_type": "text"
  }]
}

Карточка GET /v1/products/g-7 возвращает объект товара без обёртки products. sku имеет формат g-<ID>: всегда берите его из каталога, не составляйте из названия.

Остаток

available_quantity — доступные для API текстовые единицы с учётом оплаченной очереди магазина. Остаток может измениться между просмотром и покупкой. Товары с нулевым остатком могут присутствовать в каталоге.

Оптовая скидка

Применяется подходящий порог из bulk_discounts. Цена unit_price_minor — базовая, до скидки. Итог берите из charged_minor ответа на покупку.

5 шт. × 79 ₽−5%375,25 ₽charged_minor: 37525

Это пример расчёта, не действующее предложение. Пустой массив bulk_discounts: [] означает отсутствие оптовых скидок.

Персональные условия реселлера

Администратор может назначить процентные пороги или фиксированную цену для конкретного товара и вашего аккаунта. Проценты из personal_discounts зависят от количества в одном заказе, а не от накопленных покупок. Общая и персональная скидки не складываются: применяется более выгодная.

При pricing_mode: personal_fixed поле unit_price_minor уже содержит вашу фиксированную цену; дополнительные проценты не применяются. shop_unit_price_minor показывает текущую цену магазина. Каталог персонализирован по API-ключу.

Если цена магазина выросла на 10% или больше от цены на момент фиксации, фиксация снимается и бот отправляет уведомление. Например: база 300 ₽, новая цена 330 ₽. Новые покупки идут по обычным условиям и требуют max_unit_price_minor. При fixed_price_expired: true обратитесь к администратору для новой фиксации. Уже оплаченные заказы не дорожают.

06

Создание заказа

POST/v1/ordersСписание с баланса

До отправки сохраните в своей системе ID заказа, ключ повтора и тело запроса. Для одного заказа они должны оставаться неизменными.

Параметры создания заказа
ПолеФорматНазначение
external_order_idобязательноСтрока, 1–128 символовУникальный ID заказа в вашей системе.
skuобязательноСтрока вида g-7SKU из каталога.
quantityобязательноЦелое число, 1–100Дополнительно ограничено лимитом аккаунта и остатком.
max_unit_price_minorЦелое число ≥ 0Верхний предел unit_price_minor до процентных скидок либо действующей фиксированной цены. Обязателен для предзаказа и после снятия фиксации; рекомендуется всегда.
allow_preorderBoolean, по умолчанию falseЯвное согласие на списание всей суммы сейчас и выдачу недостающего товара после поступления. Требует разрешения у товара и аккаунта.
Idempotency-Keyзаголовок, обязательноСтрока, 1–128 символовКлюч повтора. Уникален в пределах вашего аккаунта; для нового заказа создаётся новый.
curl --fail-with-body 'https://api.socrate.store/v1/orders' \
  -H "X-API-Key: $SOCRATE_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: partner-order-1001' \
  -d '{"external_order_id":"1001","sku":"g-7","quantity":2,"max_unit_price_minor":7900}'
Пример ответа201 Created
{
  "order_id": 123,
  "external_order_id": "1001",
  "status": "completed",
  "sku": "g-7",
  "quantity": 2,
  "delivered_quantity": 2,
  "pending_quantity": 0,
  "refunded_minor": 0,
  "is_preorder": false,
  "pricing": {"unit_price_minor": 7900, "charged_minor": 15800, "source": "public", "discount_percent": "0.00"},
  "charged_minor": 15800,
  "balance_minor": 34200,
  "items": [
    {"position": 1, "content": "EXAMPLE-ITEM-001"},
    {"position": 2, "content": "EXAMPLE-ITEM-002"}
  ],
  "idempotency_replayed": false
}

items[].content — полученный товар. Сохраните его в защищённой базе своего магазина. Не отправляйте содержимое в публичные логи.

balance_minor фиксирует баланс после этой покупки. При повторе возвращается сохранённое значение, а не текущий баланс; актуальный баланс запрашивается через /v1/account.

Предзаказы и ожидание товара

По умолчанию предзаказы аккаунта выключены. Для покупки с ожиданием нужны одновременно: preorder_enabled: true у товара, accept_preorders: true у аккаунта, allow_preorder: true и лимит цены в запросе покупки. Без этих разрешений нехватка остатка не приводит к списанию.

Включение через API означает согласие на немедленное списание полной суммы при разрешённом предзаказе. Доступный товар выдаётся сразу, недостающий попадает в общую очередь магазина по порядку оплаты. Срок поступления не гарантирован. Бот уведомляет об оформленном предзаказе.

curl --fail-with-body -X PATCH 'https://api.socrate.store/v1/account/settings' \
  -H "X-API-Key: $SOCRATE_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"accept_preorders":false}'

Эта команда запрещает новые предзаказы; уже оплаченные не отменяются. Аналогичная настройка есть в боте: /api_settings.

У заказа в ожидании status: pending. Проверяйте GET /v1/orders/{order_id} с разумными паузами в пределах лимита API: items содержит всю уже выданную часть, pending_quantity — остаток. Новые единицы выдавайте клиенту один раз по паре order_id + position. При завершении статус станет completed. Повтор POST возвращает актуальную выдачу без нового списания.

Отмену необработанного остатка согласуйте с администратором. Полная отмена имеет статус cancelled; при частичной выдаче и возврате остатка — completed. quantity и charged_minor хранят исходную покупку, refunded_minor — возврат. Поле pricing хранит исходный расчёт; у старых заказов оно может быть null.

07

Повторы и сбои

Таймаут не означает, что покупки не было. Сервер мог провести заказ, а соединение прервалось до получения ответа.

ВОССТАНОВЛЕНИЕ ЗАКАЗА
  1. 1
    Отправьте POST /v1/orders

    Сохранённые ID, ключ и тело запроса.

    Покупка
  2. 2
    Ответ потерян или пришёл 5xx?

    Запросите GET /v1/orders?external_order_id=1001.

    Проверка
  3. 3
    Заказ найден: сохраните результат

    Заказ не найден: повторите исходный POST с теми же двумя ID и тем же телом.

    Восстановление
  4. 4
    Выдайте каждую единицу один раз

    Защитите выдачу по паре order_id + position, в том числе при поступлении частей предзаказа.

    Завершение
Не создавайте новый ID только из-за таймаута: это будет другая покупка и ещё одно списание.

201 — новый заказ

Успешная первая покупка. Товар, списание и запись заказа фиксируются одной транзакцией.

200 — повтор

idempotency_replayed: true. Возвращаются прежний заказ и выданные единицы без нового списания.

Для повтора должны совпадать оба идентификатора и всё тело запроса, включая max_unit_price_minor и allow_preorder. Изменение любого из них при повторном использовании другого вызывает IDEMPOTENCY_CONFLICT.

После 429 дождитесь времени из Retry-After. При сетевой ошибке или 5xx используйте ограниченное число повторов с растущими паузами, сохраняя идентификаторы. Ротация API-ключа не меняет привязку заказов к аккаунту.

08

История заказов

Ключ даёт доступ только к API-заказам своего аккаунта. Заказы других пользователей недоступны.

GET /v1/orders/123
GET /v1/orders?external_order_id=1001
GET /v1/orders/recent?limit=50

Первые два метода возвращают тот же формат заказа, что и покупка. У обычного чтения idempotency_replayed равно false: этот флаг отмечает именно повторный POST.

Пример страницы истории200 OK
{
  "orders": [],
  "next_before_id": null
}

Выше показана пустая история. Каждый элемент orders имеет формат ответа покупки. Заказы идут от новых к старым. Если ответ содержит next_before_id: 123, следующая страница: /v1/orders/recent?limit=50&before_id=123. Значение next_before_id: null означает конец списка. limit: 1–100, по умолчанию 50.

09

Ошибки

Обрабатывайте error.code, а не текст message. Для обращения в поддержку сохраните request_id, не прикладывая ключ и содержимое товара.

HTTPКодДействие
400INVALID_REQUESTИсправьте JSON, заголовки или параметры запроса.
401INVALID_API_KEYПроверьте полный ключ и отсутствие лишних символов. Старый ключ после замены недействителен.
402INSUFFICIENT_BALANCEПополните баланс. Покупка не проведена.
403API_ACCESS_INACTIVEДоступ отключён или аккаунт заблокирован. Обратитесь к администратору.
404PRODUCT_UNAVAILABLEТовар отсутствует, скрыт, архивирован или SKU некорректен. Обновите каталог.
404ORDER_NOT_FOUNDЗаказ с таким ID не найден среди ваших API-заказов.
404NOT_FOUNDПроверьте путь метода API.
409OUT_OF_STOCKНе хватает доступных текстовых единиц. Обновите остаток; списания нет.
409PREORDER_DISABLEDПредзаказы запрещены у товара или аккаунта. Списания нет.
409PRICE_LIMIT_REQUIREDПередайте max_unit_price_minor: он обязателен для предзаказа и после снятия фиксации. Списания нет.
409PRICE_CHANGEDБазовая цена выше переданного предела. Проверьте новую цену перед покупкой.
409IDEMPOTENCY_CONFLICTПроверьте прежний заказ: один из ID уже использован с другим запросом. Не меняйте ID вслепую.
429RATE_LIMITEDВыдержите паузу из Retry-After и повторите тот же запрос.
500INTERNAL_ERRORСначала проверьте заказ по ID, затем повторяйте с прежними идентификаторами.
Формат ошибки409 Conflict
{
  "error": {
    "code": "OUT_OF_STOCK",
    "message": "Not enough text stock.",
    "request_id": "e6df1835a9112a72",
    "retryable": false,
    "details": {"available_quantity": 0}
  }
}

Прокси может вернуть не JSON, например при 413 (слишком большое тело) или 502/504. Проверяйте HTTP-статус и формат ответа до разбора JSON. Флаг retryable сам по себе не доказывает, что списания не было.

10

Лимиты и ограничения

Запросы
По умолчанию 60 в минуту на ключ. Текущее значение — rate_limit_per_minute в /v1/account. Чтение, настройки и покупка используют общий лимит.
Количество
1–100 единиц за запрос, не больше max_quantity аккаунта. Недостающий остаток можно предзаказать только с тремя разрешениями.
Тело запроса
До 8 КиБ, Content-Type: application/json.
Деньги
Целые копейки, currency: RUB. Значение 7900 означает 79 ₽, не 7 900 ₽.
Доставка
Текстовые товары из наличия и разрешённые предзаказы. Файловая выдача через API не поддерживается.
Webhooks
Отсутствуют. Результат и готовность предзаказа проверяются методами чтения заказа.
Скидки
Общие и персональные пороги либо индивидуальная фиксированная цена. Промокоды через API не применяются.
Перед первой реальной продажей

Проверьте баланс, сохранение выдачи, обработку недостатка товара и точный повтор одного тестового заказа. Тестовой среды с бесплатными покупками нет: успешный POST в рабочее API списывает реальные средства с баланса.