Асинхронный клиент для DesslyHub API (Steam, мобильные игры, ваучеры, eSIM, заказы, баланс, курсы валют)
Project description
desslyhub-api
Async Python client for the DesslyHub API:
Steam, mobile games, vouchers, eSIM, merchant balance, orders and currency exchange rates.
English · Русский
Built on aiohttp + orjson, responses are validated with pydantic, and monetary values are represented as Decimal. All endpoints live under the base URL https://desslyhub.com with the /api/v1/ prefix.
Contents
- Features
- Installation
- Quick start
- Authentication
- Usage
- Orders
- Money values and error handling
- Development
- License
Features
| Resource | Purpose |
|---|---|
client.steam |
Catalog of gift games, game editions and login check for top-ups. |
client.mobile |
Catalog of mobile games and details of a specific game. |
client.vouchers |
Catalog of voucher products and a product by id. |
client.esim |
Catalog of eSIM variants with cursor pagination and variant details. |
client.merchant |
Current merchant balance. |
client.exchange |
Currency rates against USD for Steam top-ups. |
client.orders |
Single entry point for creating all purchases (top-ups, gifts, vouchers, eSIM), plus listing and order details. |
All purchases are created through the
ordersresource (single endpointPOST /api/v1/orders). The oldgift/top_up/refill/buymethods and themerchantsresource with/transactionsendpoints were removed — order history and statuses are now handled by orders.
Installation
Requirements: Python 3.12+ and uv.
For end users
uv add desslyhub-api
# or
pip install desslyhub-api
Import the package: import desslyhub_api.
For local development
Clone the repository and install all dependency groups (including the dev tools: pytest, black, isort, mypy):
uv sync --all-groups
Quick start
import asyncio
from desslyhub_api import DesslyHubClient
async def main() -> None:
async with DesslyHubClient("YOUR_API_KEY", "YOUR_SECRET") as client:
balance = await client.merchant.get_balance()
print(balance.balance) # Decimal
asyncio.run(main())
The client is an async context manager: inside async with it opens a persistent HTTP session that is closed automatically on exit.
Authentication
Every request is signed with HMAC-SHA256: signature = HMAC_SHA256(secret, api_key + timestamp + body). The client adds the X-Api-Key, X-Timestamp (Unix time in seconds) and X-Signature headers to every request. So you need two values — api_key and secret. The default base URL is https://desslyhub.com.
from desslyhub_api import DesslyHubClient
# Minimal
client = DesslyHubClient("YOUR_API_KEY", "YOUR_SECRET")
# Overriding base_url and timeout
client = DesslyHubClient(
"YOUR_API_KEY",
"YOUR_SECRET",
base_url="https://desslyhub.com",
timeout_seconds=30.0,
)
Usage
All methods are async and called inside async with DesslyHubClient(api_key, secret) as client:.
Merchant balance
balance = await client.merchant.get_balance()
print(balance.balance) # Decimal — total balance
print(balance.available_balance) # Decimal — available to spend
print(balance.overdraft) # Decimal — overdraft limit
print(balance.reserve) # Decimal — reserved funds
get_balance() returns a Balance model with fields balance, available_balance, overdraft, reserve — all of type Decimal.
Steam: games catalog, editions and login check
games = await client.steam.get_games()
for game in games:
print(game)
# Editions of a specific game by its app_id
editions = await client.steam.get_editions(app_id=730)
for edition in editions:
print(edition)
# Whether a Steam account with the given login can be topped up
can_refill = await client.steam.check_login(username="steam_user")
print(can_refill) # bool
Mobile: catalog and game details
games = await client.mobile.get_games()
for game in games:
print(game)
details = await client.mobile.get_game(game_id=42)
print(details)
Vouchers: catalog
products = await client.vouchers.get_products()
for product in products:
print(product)
product = await client.vouchers.get_product(product_id=10)
print(product)
eSIM: catalog
page = await client.esim.get_products() # cursor=None — first page
for variant in page.variants:
print(variant)
# Next page by cursor
if page.next_cursor:
next_page = await client.esim.get_products(cursor=page.next_cursor)
print(next_page.variants)
details = await client.esim.get_product(variant_id="variant-123")
print(details)
Exchange: currency rates
from desslyhub_api import Currency
all_rates = await client.exchange.get_all_rates()
print(all_rates.rates) # dict[int, float]
# Rate for a specific currency (Currency enum or numeric code)
rate = await client.exchange.get_rate(Currency.RUB)
print(rate.rate)
Orders
All purchases are created through the client.orders resource. Each create_* method returns CreateOrderResponse with fields order_id (int) and status (str). Typical flow:
- Create an order with a
create_*method — the response containsorder_idandstatus. - Poll the order via
client.orders.get(order_id), trackingorder_statusandservice_result(the result becomes available after successful completion).
All create_* methods share common keyword-only optional parameters:
payment_method: PaymentMethod— payment method, defaults toPaymentMethod.BALANCE(charge the merchant balance). For QR-link payment usePaymentMethod.PAYLINK_QR.payment_params: PaylinkQRPaymentParams | None— QR payment parameters (required forPAYLINK_QR).reference: str | None— your external order id.
Payment from balance (default)
# Steam top-up
order = await client.orders.create_steam_refill(
username="steam_user",
amount=10.0, # amount in USD
reference="my-order-id", # optional
)
print(order.order_id, order.status)
# Steam game gift
order = await client.orders.create_steam_gift(
invite_url="https://steamcommunity.com/p/...",
package_id="12345",
region="RU",
)
# Voucher purchase
order = await client.orders.create_voucher(
root_id=10,
variant_id=2,
quantity=1,
)
# Mobile game top-up
order = await client.orders.create_mobile_refill(
position=3,
fields={"player_id": "123456"},
)
# eSIM purchase
order = await client.orders.create_esim(
product_id="product-123",
variant_id="variant-456",
)
Payment via QR link (PAYLINK_QR)
from desslyhub_api import PaymentMethod, PaylinkQRPaymentParams
order = await client.orders.create_steam_refill(
username="steam_user",
amount=10.0,
payment_method=PaymentMethod.PAYLINK_QR,
payment_params=PaylinkQRPaymentParams(
amount=1000,
success_url="https://example.com/success",
fail_url="https://example.com/fail",
),
reference="my-order-id",
)
print(order.order_id, order.status)
Listing and order details
# List page with limit/offset pagination
page = await client.orders.list(limit=20, offset=0)
print(page.total, page.limit, page.offset)
for item in page.items:
print(item.order_id, item.order_status)
# Details of a specific order
details = await client.orders.get(order_id=12345)
print(details.order_status) # str — order status
print(details.service_type) # str — service type
print(details.commission) # Decimal — commission
print(details.final_amount) # Decimal — final amount
print(details.service_result) # execution result (after success)
list() returns OrderList with fields items, total, limit, offset. get() returns OrderDetails with fields order_id, order_status, service_type, payment_method, commission and final_amount (both Decimal), timestamps and service_result.
Money values and error handling
- Monetary values (e.g.
Balancefields, as well ascommissionandfinal_amountinOrderDetails) are represented asDecimalto avoid rounding errors. - On a response HTTP status
>= 400the client raisesDesslyHubAPIError. The error body is parsed as RFC 7807 (ErrorModel). The exception exposeserror_code(int),message(str) andhttp_status(int | None) attributes. - Network problems raise
DesslyHubConnectionError. - An invalid/unreadable API response raises
DesslyHubResponseError. - All exceptions inherit from the base
DesslyHubError.
from desslyhub_api import (
DesslyHubAPIError,
DesslyHubConnectionError,
DesslyHubResponseError,
)
async with DesslyHubClient(api_key, secret) as client:
try:
balance = await client.merchant.get_balance()
except DesslyHubAPIError as error:
print("API error:", error.error_code, error.message, error.http_status)
except DesslyHubConnectionError as error:
print("Connection error:", error)
except DesslyHubResponseError as error:
print("Invalid response:", error)
Development
Set up the environment with all dev dependencies (pytest, black, isort, mypy):
uv sync --all-groups
Useful commands:
uv run pytest -q # tests
uv run isort . && uv run black . # formatting
uv run mypy desslyhub_api # type checking
License
MIT.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file desslyhub_api-0.1.1.tar.gz.
File metadata
- Download URL: desslyhub_api-0.1.1.tar.gz
- Upload date:
- Size: 103.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.10 {"installer":{"name":"uv","version":"0.10.10","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e43dda72e956413216cb17a7c68b6bd3ddf2ba084aa4977498819e34ed8843a8
|
|
| MD5 |
f2524a0bd3a1574edadaa5b847648c15
|
|
| BLAKE2b-256 |
0d716edb784c0f3c38f67397080e5fa9260ebbd69a20474092573146f4bda475
|
File details
Details for the file desslyhub_api-0.1.1-py3-none-any.whl.
File metadata
- Download URL: desslyhub_api-0.1.1-py3-none-any.whl
- Upload date:
- Size: 26.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.10 {"installer":{"name":"uv","version":"0.10.10","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7a7364c24911a9dd41f8046dbd422e4162d0f20906541e5ec9ac430f0570caf0
|
|
| MD5 |
4639922318d82a2aaea1f001f70bce67
|
|
| BLAKE2b-256 |
e460fe5b7957f103995a2a8ee8e3d3292f2b1f14a9ca830f83191eaeda620131
|