Skip to main content

Truemoney-Voucher (pip)

Zero-dependency client for the Truemoney-Voucher REST APIs — redeem TrueMoney gift vouchers from pip, uv, poetry or any Python runtime

License: MIT Python Zero dependencies PyPI version

English - Thai


A zero-dependency client for the Truemoney-Voucher API family — three backend ports share the same HTTP contract, and the client picks the fastest healthy one for you:

Provider Backend Hosted at
auto (default) probes all three, uses the fastest healthy one failover on network errors
go Go (uTLS HelloFirefox_148 + HTTP/2 framer) https://truemoney-voucher-go.vercel.app
nestjs NestJS (cycletls Firefox 148 fingerprint) https://truemoney-voucher-nestjs.vercel.app
fastapi FastAPI (curl_cffi Firefox 147 fingerprint) https://truemoney-voucher-fastapi.vercel.app

Features

Ability Details
Redeem Client.redeem(code, mobile) — raw code or full gift.truemoney.com campaign URL
Auto provider default 'auto' probes all backends, picks the fastest healthy one, fails over on network errors
Static API from truemoney_voucher import Client — no construction, no config, just Client.redeem(...)
Zero dependencies Python standard library only — urllib + threading, no install deps
Universal runtime CPython >= 3.10 (tested through 3.14), stdlib-only — no compiled extensions
Typed errors TruemoneyApiError, TruemoneyTimeoutError, TruemoneyError with envelope access

Quick Start

Install with any Python package manager:

pip install truemoney-voucher
# or
uv add truemoney-voucher
# or
poetry add truemoney-voucher

No setup needed — Client is a ready-to-use static wrapper around an auto-configured instance:

from truemoney_voucher import Client

# auto: probes the three hosted backends and uses the fastest healthy one
result = Client.redeem("12345678901234", "0812345678")
print(result.status.code)  # e.g. "VOUCHER_NOT_FOUND", "TARGET_USER_REDEEMED"

# Liveness probe:
alive = Client.status()

# Service info:
info = Client.info()

Pin a provider (or configure your own)

from truemoney_voucher import create_client

# Pin one backend explicitly:
client = create_client(provider="nestjs")  # "go" | "nestjs" | "fastapi"

# Or bring your own deployment (overrides `provider`):
custom = create_client(
    base_url="https://api.example.com",
    timeout_ms=15_000,
)

# Client.configure() re-creates the shared instance the same way:
Client.configure(provider="fastapi")

API Reference

Static Client (no construction)

Method Description
Client.redeem(code, mobile) Redeem a raw code or full campaign URL through the fastest healthy backend
Client.status() True when at least one hosted backend answers 2xx on /status
Client.info() Service info + routes of the selected backend
Client.configure(**kwargs) Replace the shared instance (auto by default)

create_client(**kwargs) => TruemoneyClient

Option Type Default Description
provider str 'auto' Which hosted backend to call — 'auto' probes and picks the fastest healthy one
base_url str | None provider URL Full base URL (wins over provider)
timeout_ms int 30_000 Per-request timeout
urlopen callable urllib.request.urlopen Custom opener (tests, proxies)
user_agent str | None truemoney-voucher/1.1.0 User-Agent header
headers dict[str, str] — Extra headers on every request

Auto provider

  • On the first call (or after a 60 s cache TTL) all three backends are probed in parallel (thread pool, GET /status, 3 s probe timeout) and ranked by latency.
  • Redeem, status() and info() go to the fastest healthy backend; the ranking is cached for 60 seconds.
  • If a redeem fails with a network error, the client automatically retries the next healthy backend. Validation errors (TruemoneyApiError) never trigger failover — a failed redeem can't be double-redeemed, so the worst case is TARGET_USER_REDEEMED.
  • client.explicit_base_url returns the base URL of an explicitly selected backend (None for auto).

client.redeem(code, mobile) => RedeemResult

Accepts a raw gift code or a full campaign URL (percent-encoded into the path — the backends preserve %2F, matching the reference CLI).

  • Returns RedeemResult(ok=True, status=TrueMoneyStatus(message, code), data=...) when the upstream call succeeds.
  • Raises TruemoneyApiError on validation/routing errors ({ code, message } envelopes, or upstream Spring-style error bodies, which are normalized).

client.status() => bool

True on any 2xx, False otherwise — never raises, safe for uptime checks. In auto mode, True when at least one backend is healthy.

client.info() => dict

Service name, deployed version (where exposed), and the route list.

Errors

Error When
TruemoneyApiError API answered { code, message } (validation 400, not found 404, …) or a Spring-style error body. Exposes status, code, envelope.
TruemoneyTimeoutError No response within timeout_ms.
TruemoneyError Network failure, non-JSON response, unexpected envelope.

All errors extend TruemoneyError:

from truemoney_voucher import TruemoneyApiError

try:
    Client.redeem(code, mobile)
except TruemoneyApiError as err:
    print(err.code, err.message)  # 400 "Bad Request"

TrueMoney status codes

When the upstream call succeeds, result.status.code carries TrueMoney's answer:

Code Meaning
SUCCESS Money received successfully
TARGET_USER_REDEEMED You already redeemed this voucher
VOUCHER_OUT_OF_STOCK Someone else already took it
VOUCHER_EXPIRED The wallet voucher has expired
VOUCHER_NOT_FOUND Voucher not found in the system
CANNOT_GET_OWN_VOUCHER Cannot redeem your own voucher
TARGET_USER_NOT_FOUND Phone number not found in the system
INTERNAL_ERROR Voucher not found, or the URL is wrong

Testing

pip install -e ".[dev]"
pytest tests/test_client.py tests/test_auto_client.py   # offline unit tests
set LIVE=1 && pytest tests/test_live.py                 # live checks against the three hosted backends

The live suite runs status/info and an invalid-voucher check against all three Vercel deployments, plus a real upstream call.

Contributing

Contributions are welcome! Please:

  1. Open an issue first for significant changes
  2. Keep pytest tests green
  3. Bump version in pyproject.toml together with src/truemoney_voucher/version.py

Disclaimer

For educational use or where the provider permits it. Redeeming is irreversible and governed by TrueMoney's Terms of Service. Voucher codes are cash-equivalent — never log full codes.

License

Licensed under the MIT License © 2026 ByteInDev

Metadata

Release files for truemoney-voucher 1.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for truemoney-voucher 1.1.1
File Size Uploaded Provenance Actions
truemoney_voucher-1.1.1.tar.gz 17.3 kB Without provenance Details for truemoney_voucher-1.1.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for truemoney-voucher 1.1.1
File Interpreter ABI Platform Actions
truemoney_voucher-1.1.1-py3-none-any.whl Python 3 none any Details for truemoney_voucher-1.1.1-py3-none-any.whl

Total release size: 29.6 kB

Release files / truemoney_voucher-1.1.1.tar.gz

Download URL truemoney_voucher-1.1.1.tar.gz
Size 17.3 kB
Tags Source
SHA-256 checksum
How to use checksums
764a1ecc5a6031f065988f135ac03b8841484028e09a54540f59c05ac2ab525c
BLAKE2b-256 checksum
How to use checksums
9687cc96c43703e6ae2895a99a5130a2ad6033f154674e27caadf1726a6fa6c3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Release files / truemoney_voucher-1.1.1-py3-none-any.whl

Download URL truemoney_voucher-1.1.1-py3-none-any.whl
Size 12.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
076e4bd3fe5acee0ef46aab5deb29aec0638124ce05f0130369988acf4009913
BLAKE2b-256 checksum
How to use checksums
71744b732a04942e220a758b15f191c43846a927699165270349aacfbc2b2c9b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Security for truemoney-voucher 1.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

1.1.1 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page