Skip to main content

Official ZyndPay Python SDK — accept USDT payments with a few lines of code

Project description

zyndpay

Official ZyndPay Python SDK — accept USDT TRC20 payments with a few lines of code.

PyPI version Python License: MIT


Requirements

  • Python 3.8+
  • A ZyndPay account and API key

Installation

pip install zyndpay

Quickstart

from zyndpay import ZyndPay

zyndpay = ZyndPay("zyp_live_sk_...")

# Create a payment request
payin = zyndpay.payins.create(amount="100")
print(payin["depositAddress"])  # Send USDT TRC20 here
print(payin["paymentPageUrl"])  # Redirect your customer here

# Check your balance
balance = zyndpay.balances.get()
print(balance["available"])  # e.g. "97.00"

Configuration

zyndpay = ZyndPay(
    api_key="zyp_live_sk_...",              # required
    webhook_secret="whsec_...",             # optional — needed for webhook verification
    base_url="https://api.zyndpay.io/v1",  # optional — override for self-hosted
    timeout=30,                             # optional — seconds (default: 30)
    max_retries=2,                          # optional — retries on network errors (default: 2)
)

API key types

Prefix Type
zyp_live_sk_ Live secret key
zyp_live_pk_ Live publishable key
zyp_test_sk_ Sandbox secret key
zyp_test_pk_ Sandbox publishable key

Payins

Create a payin

payin = zyndpay.payins.create(
    amount="100",                      # USDT amount (minimum 20)
    external_ref="order_9f8e7d",       # your internal order ID (optional)
    expires_in_seconds=3600,           # 1 hour — default is 24h (optional)
    metadata={"user_id": "usr_123"},   # stored as-is (optional)
    success_url="https://yoursite.com/success",
    cancel_url="https://yoursite.com/cancel",
)

print(payin["id"])              # "pay_..."
print(payin["depositAddress"])  # TRC20 address to receive payment
print(payin["amount"])          # "100"
print(payin["fee"])             # "3.00"
print(payin["netAmount"])       # "97.00"
print(payin["status"])          # "AWAITING_PAYMENT"
print(payin["expiresAt"])       # ISO timestamp

Get a payin

payin = zyndpay.payins.get("pay_abc123")

List payins

result = zyndpay.payins.list(status="CONFIRMED", page=1, limit=20)
for payin in result["data"]:
    print(payin["id"], payin["status"])

meta = result["meta"]
print(meta["total"], meta["totalPages"])

Payin statuses

Status Description
PENDING Just created
AWAITING_PAYMENT Deposit address assigned, waiting for funds
CONFIRMING Payment detected, waiting for confirmations
CONFIRMED Payment confirmed — balance credited
EXPIRED Payment window elapsed
OVERPAID More than expected was sent
UNDERPAID Less than expected was sent
FAILED Processing failed

Sandbox / Test Mode

Use your sandbox API key (zyp_test_sk_...) and pass sandbox=True when creating a payin. Then call simulate to instantly confirm it without real funds.

zyndpay = ZyndPay("zyp_test_sk_...")

# Create a sandbox payin
payin = zyndpay.payins.create(amount="100", sandbox=True)

# Instantly simulate confirmation
confirmed = zyndpay.payins.simulate(payin["id"])
print(confirmed["status"])  # "CONFIRMED"

Withdrawals

Request a withdrawal

withdrawal = zyndpay.withdrawals.create(
    amount="50",                          # USDT amount
    idempotency_key="idempotency-key-123" # optional
)

print(withdrawal["status"])     # "PENDING_REVIEW"
print(withdrawal["fee"])        # "2.00" (flat $2 fee)
print(withdrawal["netAmount"])  # "48.00"

Get / list withdrawals

withdrawal = zyndpay.withdrawals.get("wdr_abc123")

result = zyndpay.withdrawals.list(status="CONFIRMED", page=1, limit=20)

Cancel a withdrawal

zyndpay.withdrawals.cancel("wdr_abc123")  # only while PENDING_REVIEW

Withdrawal statuses

Status Description
PENDING_REVIEW Awaiting admin approval
APPROVED Approved, queued for processing
PROCESSING Being broadcast to blockchain
BROADCAST Transaction sent
CONFIRMED On-chain confirmed
REJECTED Rejected by admin
CANCELLED Cancelled by merchant
FAILED Broadcast failed

Transactions

# Get a single transaction
tx = zyndpay.transactions.get("txn_abc123")

# List with filters
result = zyndpay.transactions.list(
    type="PAYIN",           # "PAYIN" | "PAYOUT"
    status="CONFIRMED",
    from_date="2026-01-01",
    to_date="2026-03-31",
    page=1,
    limit=50,
)

Balances

balance = zyndpay.balances.get()
print(balance["currency"])   # "USDT_TRC20"
print(balance["available"])  # spendable balance
print(balance["pending"])    # in-flight / unconfirmed
print(balance["total"])      # available + pending

Webhooks

ZyndPay sends signed webhook events to your endpoint. Always verify the signature before processing.

Verify a webhook (Flask example)

from flask import Flask, request, abort
from zyndpay import ZyndPay

zyndpay = ZyndPay(
    api_key="zyp_live_sk_...",
    webhook_secret="whsec_...",
)

app = Flask(__name__)

@app.route("/webhooks/zyndpay", methods=["POST"])
def handle_webhook():
    # IMPORTANT: use raw body — do not parse JSON before verifying
    payload = request.get_data(as_text=True)
    signature = request.headers.get("X-ZyndPay-Signature", "")

    try:
        event = zyndpay.webhooks.verify(payload, signature)
    except ValueError as e:
        return str(e), 400

    if event["type"] == "payin.confirmed":
        print("Payment confirmed:", event["data"])
    elif event["type"] == "withdrawal.confirmed":
        print("Withdrawal confirmed:", event["data"])

    return {"received": True}, 200

Webhook event types

Event Trigger
payin.created Payin created
payin.confirming Payment detected on-chain
payin.confirmed Payment fully confirmed
payin.expired Payin expired before payment
payin.overpaid More than expected received
payin.underpaid Less than expected received
payin.failed Processing error
withdrawal.requested Withdrawal created
withdrawal.approved Approved by admin
withdrawal.rejected Rejected by admin
withdrawal.broadcast Sent to blockchain
withdrawal.confirmed On-chain confirmed
withdrawal.failed Broadcast failed

Error Handling

All SDK errors inherit from ZyndPayError and include status_code and an optional request_id.

from zyndpay import (
    ZyndPayError,
    AuthenticationError,
    ValidationError,
    NotFoundError,
    RateLimitError,
)

try:
    payin = zyndpay.payins.create(amount="5")  # below minimum
except ValidationError as e:
    print("Bad request:", e)          # "amount must be >= 20"
    print("Status code:", e.status_code)  # 400
except AuthenticationError:
    print("Invalid API key")
except NotFoundError:
    print("Resource not found")
except RateLimitError as e:
    print(f"Rate limited, retry after {e.retry_after}s")
except ZyndPayError as e:
    print(f"API error {e.status_code}: {e}")

License

MIT — see LICENSE

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

zyndpay-1.1.1.tar.gz (11.5 kB view details)

Uploaded Source

Built Distribution

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

zyndpay-1.1.1-py3-none-any.whl (12.2 kB view details)

Uploaded Python 3

File details

Details for the file zyndpay-1.1.1.tar.gz.

File metadata

  • Download URL: zyndpay-1.1.1.tar.gz
  • Upload date:
  • Size: 11.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for zyndpay-1.1.1.tar.gz
Algorithm Hash digest
SHA256 81900efacd7567133bf9cb3ac3f22e57a105eafe37b28769862163380a69e0ff
MD5 2fdfd2249ddeef5ba39e88a1f19b1c93
BLAKE2b-256 85f5064e6e3d350cdc9f4e19af7e0744ef4e7c313710413244732fc4884d1184

See more details on using hashes here.

File details

Details for the file zyndpay-1.1.1-py3-none-any.whl.

File metadata

  • Download URL: zyndpay-1.1.1-py3-none-any.whl
  • Upload date:
  • Size: 12.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for zyndpay-1.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 67c4a4c7d0bcd01d5f2ea1a521b0816ac6d13bc582911ef5dcfa93d19120f2a6
MD5 4dc691cc06a94a0b2135750976023a02
BLAKE2b-256 d8405f32dcfe3416c648d50280373294728183bde1288c603062b23b2fdc8292

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