Документация GeminiShop API

HTTP-интерфейс магазина: каталог, баланс, покупка и пополнение. Все запросы и ответы — в формате JSON. Базовый адрес: https://api.gemini-shop.xyz/api/v1.

Введение

API работает от имени вашего аккаунта в боте: тот же баланс, те же покупки. Каждый запрос авторизуется персональным токеном. Ответы возвращают чистый JSON, ошибки — в едином формате {"error":{"code","message"}}.

Доступно пять методов: получить каталог, узнать баланс, купить товар с баланса, создать счёт на пополнение и проверить его статус.

Получить токен

Откройте бота → ПрофильAPI-доступВыпустить токен. Токен вида gsk_… привязан к вашему аккаунту. Там же его можно перевыпустить (старый перестанет работать) или отозвать.

⚠ Никому не передавайте токен — он даёт полный доступ к вашему балансу и покупкам.

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

Передавайте токен в заголовке Authorization каждого запроса:

HTTP
Authorization: Bearer gsk_ВАШ_ТОКЕН

Ответы аутентификации

СитуацияHTTPcode
Нет заголовка / пустой токен401unauthorized
Неверный токен401unauthorized
Аккаунт заблокирован403forbidden

GET /catalog

Список товаров с ценой за штуку и текущим остатком. Недоступные позиции отдаются с "stock":0 и, возможно, "price":null.

curl -H "Authorization: Bearer gsk_ТОКЕН" \
  https://api.gemini-shop.xyz/api/v1/catalog
import requests

r = requests.get(
    "https://api.gemini-shop.xyz/api/v1/catalog",
    headers={"Authorization": "Bearer gsk_ТОКЕН"},
)
print(r.json())
const r = await fetch("https://api.gemini-shop.xyz/api/v1/catalog", {
  headers: { Authorization: "Bearer gsk_ТОКЕН" },
});
console.log(await r.json());

Ответ 200

JSON
{
  "items": [
    { "type": "account", "title": "Gemini аккаунты", "price": 170.0, "stock": 12 },
    { "type": "link",    "title": "Gemini ссылки",   "price": 60.0,  "stock": 40 }
  ]
}

GET /balance

Баланс и число покупок владельца токена.

curl -H "Authorization: Bearer gsk_ТОКЕН" \
  https://api.gemini-shop.xyz/api/v1/balance
import requests

r = requests.get(
    "https://api.gemini-shop.xyz/api/v1/balance",
    headers={"Authorization": "Bearer gsk_ТОКЕН"},
)
print(r.json())
const r = await fetch("https://api.gemini-shop.xyz/api/v1/balance", {
  headers: { Authorization: "Bearer gsk_ТОКЕН" },
});
console.log(await r.json());

Ответ 200

JSON
{ "id": 123456789, "balance": 340.0, "purchases": 7 }

POST /purchase

Покупка товара с баланса. Списание и выдача происходят атомарно — как в боте.

Тело запроса

ПолеТипОписание
typestring"account" или "link"
qtyintколичество, 1…1000
curl -X POST https://api.gemini-shop.xyz/api/v1/purchase \
  -H "Authorization: Bearer gsk_ТОКЕН" \
  -H "Content-Type: application/json" \
  -d '{"type":"link","qty":2}'
import requests

r = requests.post(
    "https://api.gemini-shop.xyz/api/v1/purchase",
    headers={"Authorization": "Bearer gsk_ТОКЕН"},
    json={"type": "link", "qty": 2},
)
print(r.status_code, r.json())
const r = await fetch("https://api.gemini-shop.xyz/api/v1/purchase", {
  method: "POST",
  headers: {
    Authorization: "Bearer gsk_ТОКЕН",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ type: "link", qty: 2 }),
});
console.log(r.status, await r.json());

Ответ 200 — успех

JSON
{
  "status": "ok",
  "delivered": 2,
  "requested": 2,
  "total": 120.0,
  "items": ["https://…/activate/1", "https://…/activate/2"],
  "balance": 220.0
}

Поле status

statusHTTPсмысл
ok200выдано полностью
partial200выдано частично (только аккаунты); остаток — на балансе
no_balance402не хватает баланса (insufficient_balance)
no_stock / unavailable409нет в наличии (out_of_stock)

Ответ 409 — нет в наличии

JSON
{
  "status": "no_stock", "delivered": 0, "requested": 2,
  "total": 0.0, "items": [], "balance": 220.0, "available": 1,
  "error": { "code": "out_of_stock", "message": "purchase failed: no_stock" }
}

POST /topup

Создать счёт на пополнение баланса. После оплаты баланс зачисляется автоматически (фоновый опрос) — либо мгновенно, если опросить статус (см. ниже).

Тело запроса

ПолеТипОписание
methodstring"sbp", "cryptobot" или "ton"
amountnumberсумма зачисления в ₽, 10…1000000 (комиссия добавляется сверху)
curl -X POST https://api.gemini-shop.xyz/api/v1/topup \
  -H "Authorization: Bearer gsk_ТОКЕН" \
  -H "Content-Type: application/json" \
  -d '{"method":"sbp","amount":500}'
import requests

r = requests.post(
    "https://api.gemini-shop.xyz/api/v1/topup",
    headers={"Authorization": "Bearer gsk_ТОКЕН"},
    json={"method": "sbp", "amount": 500},
)
print(r.json())
const r = await fetch("https://api.gemini-shop.xyz/api/v1/topup", {
  method: "POST",
  headers: {
    Authorization: "Bearer gsk_ТОКЕН",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ method: "sbp", amount: 500 }),
});
console.log(await r.json());

Ответ 200 — СБП / CryptoBot

JSON
{
  "tx_id": 1042,
  "method": "sbp",
  "amount": 500.0,
  "to_pay": 545.0,
  "payment_url": "https://pay.anore.cc/…",
  "ton": null,
  "expires_in_min": 30
}

Ответ 200 — TON (payment_url:null, реквизиты в ton)

JSON
{
  "tx_id": 1043, "method": "ton", "amount": 500.0, "to_pay": 505.0,
  "payment_url": null,
  "ton": { "amount": 1.83, "address": "EQC…", "comment": "gs-7f3a9b" },
  "expires_in_min": 30
}

Метод недоступен (выключен или не настроен) → 409 method_disabled.

GET /topup/{tx_id}

Статус пополнения. Если счёт ещё pending, метод активно проверит платёж у провайдера и, при оплате, сразу зачислит баланс.

curl -H "Authorization: Bearer gsk_ТОКЕН" \
  https://api.gemini-shop.xyz/api/v1/topup/1042
import requests

r = requests.get(
    "https://api.gemini-shop.xyz/api/v1/topup/1042",
    headers={"Authorization": "Bearer gsk_ТОКЕН"},
)
print(r.json())
const r = await fetch("https://api.gemini-shop.xyz/api/v1/topup/1042", {
  headers: { Authorization: "Bearer gsk_ТОКЕН" },
});
console.log(await r.json());

Ответ 200

JSON
{
  "tx_id": 1042,
  "status": "paid",
  "amount": 500.0,
  "method": "sbp",
  "balance": 720.0
}

status: pending · paid · expired · canceled. Чужая или несуществующая транзакция → 404 not_found.

Коды ошибок

Все ошибки — в едином формате:

JSON
{ "error": { "code": "unauthorized", "message": "Invalid token" } }
HTTPcodeкогда
400invalid_requestнекорректное тело или параметры
401unauthorizedнет или неверный токен
402insufficient_balanceне хватает баланса на покупку
403forbiddenаккаунт заблокирован
404not_foundтранзакция не найдена
409out_of_stock / method_disabledнет в наличии / метод оплаты выключен
502provider_errorплатёжный провайдер недоступен