Skip to main content

Асинхронный клиент для DesslyHub API (Steam, мобильные игры, ваучеры, eSIM, заказы, баланс, курсы валют)

Project description

DesslyHub API

desslyhub-api

Async Python client for the DesslyHub API:
Steam, mobile games, vouchers, eSIM, merchant balance, orders and currency exchange rates.

Python 3.12+ MIT black mypy aiohttp + orjson

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

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 orders resource (single endpoint POST /api/v1/orders). The old gift / top_up / refill / buy methods and the merchants resource with /transactions endpoints 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:

  1. Create an order with a create_* method — the response contains order_id and status.
  2. Poll the order via client.orders.get(order_id), tracking order_status and service_result (the result becomes available after successful completion).

All create_* methods share common keyword-only optional parameters:

  • payment_method: PaymentMethod — payment method, defaults to PaymentMethod.BALANCE (charge the merchant balance). For QR-link payment use PaymentMethod.PAYLINK_QR.
  • payment_params: PaylinkQRPaymentParams | None — QR payment parameters (required for PAYLINK_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. Balance fields, as well as commission and final_amount in OrderDetails) are represented as Decimal to avoid rounding errors.
  • On a response HTTP status >= 400 the client raises DesslyHubAPIError. The error body is parsed as RFC 7807 (ErrorModel). The exception exposes error_code (int), message (str) and http_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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

desslyhub_api-0.1.1.tar.gz (103.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

desslyhub_api-0.1.1-py3-none-any.whl (26.7 kB view details)

Uploaded Python 3

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

Hashes for desslyhub_api-0.1.1.tar.gz
Algorithm Hash digest
SHA256 e43dda72e956413216cb17a7c68b6bd3ddf2ba084aa4977498819e34ed8843a8
MD5 f2524a0bd3a1574edadaa5b847648c15
BLAKE2b-256 0d716edb784c0f3c38f67397080e5fa9260ebbd69a20474092573146f4bda475

See more details on using hashes here.

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

Hashes for desslyhub_api-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 7a7364c24911a9dd41f8046dbd422e4162d0f20906541e5ec9ac430f0570caf0
MD5 4639922318d82a2aaea1f001f70bce67
BLAKE2b-256 e460fe5b7957f103995a2a8ee8e3d3292f2b1f14a9ca830f83191eaeda620131

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page