qpay-client is a production-ready Python client for the QPay v2 payment API — Mongolia's leading payment provider.
Built and used in production systems, it supports both async and sync clients, Pydantic v2-validated schemas, automatic
token management, retry logic with exponential backoff, and typed wrappers for all common endpoints.
Documentation: qpay-client.readthedocs.io
QPay developer portal: developer.qpay.mn
- Both
AsyncQPayClientandQPayClient(sync) supported - Authentication and token refresh managed automatically
- Request/response validation via Pydantic v2 schemas
- Retry logic for network errors and transient server failures
- Configurable
payment_checkpolling with exponential backoff withandasync withcontext manager support- Structured
QPayErrorexceptions with error codes and descriptions
Using pip:
pip install qpay-clientUsing uv:
uv add qpay-clientUsing poetry:
poetry add qpay-clientfrom decimal import Decimal
from qpay_client.v2 import AsyncQPayClient, QPaySettings
from qpay_client.v2.schemas import InvoiceCreateSimpleRequest
settings = QPaySettings.sandbox()
async def main():
async with AsyncQPayClient(settings=settings) as client:
invoice = await client.invoice_create(
InvoiceCreateSimpleRequest(
sender_invoice_no="ORDER-1001",
invoice_receiver_code="terminal",
invoice_description="Test invoice",
amount=Decimal("1500"),
callback_url="https://example.com/qpay/callback?payment_id=ORDER-1001",
)
)
print(invoice.invoice_id)
print(invoice.qPay_shortUrl)from decimal import Decimal
from qpay_client.v2 import QPayClient, QPaySettings
from qpay_client.v2.schemas import InvoiceCreateSimpleRequest
settings = QPaySettings.sandbox()
with QPayClient(settings=settings) as client:
invoice = client.invoice_create(
InvoiceCreateSimpleRequest(
sender_invoice_no="ORDER-1002",
invoice_receiver_code="terminal",
invoice_description="Sync test invoice",
amount=Decimal("2500"),
callback_url="https://example.com/qpay/callback?payment_id=ORDER-1002",
)
)
print(invoice.invoice_id)from qpay_client.v2 import QPaySettings
settings = QPaySettings.sandbox()from qpay_client.v2 import QPaySettings
settings = QPaySettings.production(
username="your-merchant-username",
password="your-merchant-password",
invoice_code="YOUR_INVOICE_CODE",
)settings = QPaySettings.sandbox(
client_retries=2,
client_delay=0.25,
client_jitter=0.1,
payment_check_retries=8,
payment_check_delay=0.5,
payment_check_jitter=0.2,
)from qpay_client.v2.enums import ObjectType
from qpay_client.v2.schemas import Offset, PaymentCheckRequest
check_request = PaymentCheckRequest(
object_type=ObjectType.invoice,
object_id="YOUR_INVOICE_ID",
offset=Offset(page_number=1, page_limit=100),
)
result = await client.payment_check(check_request)
if result.count > 0:
print("Payment found")examples/quickstart.py contains a working async example with a QPay callback endpoint.
The general pattern is:
- Create an invoice
- Store the
invoice_idin your database - On QPay callback, call
payment_checkto verify the payment - Return
"SUCCESS"with HTTP 200
To run the example:
fastapi dev examples/quickstart.pyReturning HTTP 200 with body "SUCCESS" from your callback endpoint is required by QPay.
Import clients and settings from qpay_client.v2:
from qpay_client.v2 import AsyncQPayClient, QPayClient, QPaySettings, QPayErrorImport schemas and enums from their respective modules:
from qpay_client.v2.enums import ObjectType
from qpay_client.v2.schemas import InvoiceCreateSimpleRequest, Offset, PaymentCheckRequesttokenrefresh
invoice_getinvoice_createinvoice_cancel
payment_getpayment_listpayment_checkpayment_cancelpayment_refund
ebarimt_getebarimt_create
subscription_getsubscription_cancel
- Never call
QPaySettings()directly — usesandbox()orproduction()factory methods. - All public endpoint methods check and refresh authentication automatically; no need to manage tokens manually.
payment_checkpolls with exponential backoff — tune retry/delay settings to your use case.- Do not commit production credentials to source control.
MIT License