Каталог

Завантажте повний каталог продуктів і працюйте з ним офлайн

View as Markdown

Повний каталог продуктів — кожен товар, доступний для замовлення, з його ціною, запасом, типом продукту та формою вводу — публікується як єдиний знімок для завантаження. Ви завантажуєте його, читаєте локально та використовуєте id кожного товару та його fields, щоб розміщувати замовлення. Немає пагінованого ендпоінта «list products» для програмного використання; знімок і є каталогом.

URL для завантаження:

https://downloads.voodoo.center/catalog.lmdb.zst

Надається через CDN cdn.voodoo.center. Для завантаження автентифікація не потрібна.

Персональний каталог

URL вище надає глобальний каталог, який використовує стандартні ціни. Якщо ваш акаунт має персональні (узгоджені) ціни — перевизначення ціни для окремих товарів — існує окремий персональний каталог, опублікований за URL, що містить client id вашого акаунта. Він містить ті самі записи, але price та subscriber_price відображають ціни вашого акаунта. Використовуйте персональний файл, якщо він існує; інакше використовуйте глобальний.

URL для завантаження персонального каталогу:

https://downloads.voodoo.center/{client_id}.lmdb.zst

Знайдіть свій Client ID — і готову до використання URL-адресу персонального каталогу — на сторінці API в дашборді (та сама сторінка, де ви керуєте API-ключами та webhook). Не кожен акаунт має персональні ціни: якщо ваш не має, ця URL повертає 404 — у такому разі поверніться до catalog.lmdb.zst.

Це той самий формат і схема, що й у глобального каталогу (стиснена zstd однофайлова база даних LMDB); єдина відмінність — значення цін. Отже: спробуйте свою персональну URL, поверніться до глобальної у разі 404, а потім розпакуйте, відкрийте та прочитайте файл точно так, як показано нижче.

Виберіть URL каталогу з резервним варіантом (Python)
1import urllib.error
2import urllib.request
3
4GLOBAL_URL = "https://downloads.voodoo.center/catalog.lmdb.zst"
5PERSONAL_URL = "https://downloads.voodoo.center/{client_id}.lmdb.zst"
6
7
8def download_catalog(client_id: str, dest: str = "catalog.lmdb.zst") -> str:
9 # Надаємо перевагу персональному каталогу (ваші узгоджені ціни); повертаємось
10 # до глобального, якщо цей акаунт не має персонального файлу (404 на персональній URL).
11 try:
12 urllib.request.urlretrieve(PERSONAL_URL.format(client_id=client_id), dest)
13 except urllib.error.HTTPError as exc:
14 if exc.code != 404:
15 raise
16 urllib.request.urlretrieve(GLOBAL_URL, dest)
17 return dest
18
19
20# Візьміть свій client id зі сторінки API в дашборді.
21download_catalog("your-client-id") # -> catalog.lmdb.zst
22# Тепер розпакуйте, відкрийте та прочитайте його точно так, як показано нижче.

Що ви отримуєте

catalog.lmdb.zst — це однофайлова база даних LMDB, стиснена за допомогою zstandard:

  • Один файл, один простір ключів. Товари зберігаються в базі даних LMDB за замовчуванням. Кожен товар — це один запис: ключ = 8-байтний item id у форматі big-endian, значення = компактний JSON-обʼєкт.
  • Самодостатні записи. Кожен товар вбудовує повну форму вводу (fields, де кожне поле вибору має свої options) вбудовано, тож єдиний пошук за ключем дає вам усе потрібне для замовлення цього товару.
  • Малий і швидкий. Повний каталог стискається приблизно в 45× (база даних ~1,5 МБ → ~34 КБ). Ви розпаковуєте один раз, а потім відображаєте базу даних у памʼять і читаєте її без звернень до сервера.

Ціни в каталозі вказані в центах (цілі числа) і відображають стандартні ціни. Ваше фінальне списання завжди підтверджується відповіддю замовлення та вашим балансом — див. Розміщення замовлень.

Завантаження та відкриття

Установіть два читачі, а потім завантажте → розпакуйте → відкрийте лише для читання.

Встановлення залежностей
$pip install zstandard lmdb
Завантаження та розпакування (shell)
$# Завантажте стиснений знімок
$curl -o catalog.lmdb.zst https://downloads.voodoo.center/catalog.lmdb.zst
$
$# Розпакуйте zstd-фрейм у однофайлову базу даних LMDB
$zstd -d catalog.lmdb.zst -o catalog.lmdb # або: unzstd catalog.lmdb.zst
Завантаження, розпакування та читання (Python)
1import json
2import struct
3import urllib.request
4
5import lmdb
6import zstandard
7
8CATALOG_URL = "https://downloads.voodoo.center/catalog.lmdb.zst"
9
10
11def item_key(item_id: int) -> bytes:
12 # Записи індексуються 8-байтним item id у форматі big-endian (тож сортуються за id).
13 return struct.pack(">Q", item_id)
14
15
16# 1. Завантажте стиснений знімок.
17urllib.request.urlretrieve(CATALOG_URL, "catalog.lmdb.zst")
18
19# 2. Потоково розпакуйте zstd-фрейм у однофайлову базу даних LMDB.
20dctx = zstandard.ZstdDecompressor()
21with open("catalog.lmdb.zst", "rb") as fin, open("catalog.lmdb", "wb") as fout:
22 dctx.copy_stream(fin, fout)
23
24# 3. Відкрийте середовище лише для читання. Це один ФАЙЛ, а не каталог (subdir=False),
25# і читачі в режимі лише для читання мають передавати lock=False.
26env = lmdb.open("catalog.lmdb", subdir=False, readonly=True, lock=False)
27
28# Знайдіть один товар за id.
29with env.begin() as txn:
30 raw = txn.get(item_key(4211))
31 item = json.loads(raw) if raw else None
32 print(item)
33
34# Ітеруйте весь каталог (записи виходять упорядкованими за id).
35with env.begin() as txn:
36 for key, value in txn.cursor():
37 item = json.loads(value)
38 if item["in_stock"]:
39 price = item["price"] / 100 # центи -> основні одиниці
40 print(item["id"], item["product_type"], f"{price:.2f}", item["name"])

★ Пояснення ───────────────────────────────────── LMDB відображається в памʼять, тож відкриття файлу практично безкоштовне, а пошуки читаються прямо з кешу сторінок ОС — ви можете тримати середовище відкритим і звертатися до нього мільйони разів, нічого не перечитуючи повторно. Саме тому каталог постачається як LMDB, а не як один величезний JSON-масив. ─────────────────────────────────────────────────

Схема запису

Кожне значення — це JSON-обʼєкт:

ПолеТипОпис
idціле числоId товару. Передайте його як item_id під час розміщення замовлення.
nameрядокЧитабельна назва товару.
product_typeрядокkey, topup або service — визначає правила кількості/полів під час замовлення.
min_quantityчислоМінімальна кількість для замовлення.
max_quantityчислоМаксимальна кількість для замовлення (фактична межа).
priceціле число (центи)Стандартна ціна. Поділіть на 100, щоб отримати основні одиниці.
base_priceціле число (центи)Початкова/каталожна ціна. Коли вона більша за price, показуйте її закресленою.
subscriber_priceціле число (центи)Ціна з активною підпискою.
amount_per_priceчислоОдиниць, доставлених на одиницю ціни (актуально для поповнень).
in_stockбулеве значенняЧи доступний товар для замовлення зараз.
updated_atрядок (ISO 8601)Коли цей товар востаннє змінювався.
fieldsмасивФорма вводу товару — див. нижче.

Кожен запис у fields:

ПолеТипОпис
idціле числоId поля.
nameрядокКлюч поля — використовуйте його як ключ в обʼєкті fields замовлення.
typeрядокstring, integer, email, url або choice.
requiredбулеве значенняЧи потрібно надавати значення.
optionsмасивЛише для полів choice: [{ "id": <int>, "value": "<label>" }, …].
Приклад запису (товар типу top-up)
1{
2 "id": 4211,
3 "name": "Sample Game Top-up",
4 "product_type": "topup",
5 "min_quantity": 1,
6 "max_quantity": 1000,
7 "price": 1250,
8 "base_price": 1250,
9 "subscriber_price": 1150,
10 "amount_per_price": 1,
11 "in_stock": true,
12 "updated_at": "2026-07-05T12:00:00+00:00",
13 "fields": [
14 { "id": 88, "name": "player_id", "type": "string", "required": true, "options": [] },
15 {
16 "id": 91, "name": "server", "type": "choice", "required": true,
17 "options": [
18 { "id": 17, "value": "Europe (EU-West)" },
19 { "id": 18, "value": "North America" }
20 ]
21 }
22 ]
23}

Використання каталогу з Orders API

Усе, що потрібно для побудови запиту POST /api/v1/orders, є в записі:

  • item_id = id запису.
  • quantity — обмежена min_quantity/max_quantity. Обовʼязкова для topup (десяткова) та key (ціла, за замовчуванням 1); пропустіть для service.
  • fields — обовʼязкові лише для topup і service. Індексуйте кожен запис за name поля. Для поля choice надсилайте id обраного варіанта (ціле число), а не його value. Для текстових полів надсилайте рядок.
Перетворення запису каталогу на замовлення (Python)
1# `item` — це запис, прочитаний з каталогу вище; `access_token` — ваш
2# Bearer-токен (див. Автентифікація).
3import urllib.request, json
4
5body = {
6 "item_id": item["id"],
7 "quantity": 10, # у межах min_quantity..max_quantity
8 "merchant_order_id": "po-10232",
9 "fields": {
10 "player_id": "123456789", # текстове поле -> його рядкове значення
11 "server": 17, # поле вибору -> id варіанта
12 },
13}
14req = urllib.request.Request(
15 "https://api.voodoo.center/api/v1/orders",
16 data=json.dumps(body).encode(),
17 headers={"Authorization": f"Bearer {access_token}", "Content-Type": "application/json"},
18 method="POST",
19)
20order = json.loads(urllib.request.urlopen(req).read())
21print(order["id"], order["status"])

Підтримання актуальності

Знімок регулярно перегенеровується. Його свіжість — це HTTP-заголовки ETag / Last-Modified обʼєкта; використовуйте умовний запит, щоб повторно завантажувати лише тоді, коли він справді змінився:

Повторне завантаження лише за зміни
$# -z змушує curl надсилати If-Modified-Since на основі mtime локального файлу;
$# 304 залишає ваш файл без змін.
$curl -o catalog.lmdb.zst -z catalog.lmdb.zst https://downloads.voodoo.center/catalog.lmdb.zst

Простий і надійний підхід для працюючої інтеграції: оновлюйте за розкладом (наприклад, кожні кілька хвилин) умовним запитом вище, і коли надходить новий файл, розпаковуйте його та замінюйте відкрите середовище LMDB.