Skip to main content

SagaPay Python SDK

Python SDK for SagaPay - the world's first free, non-custodial blockchain payment gateway service provider. This SDK enables Python developers to seamlessly integrate cryptocurrency payments without holding customer funds. With enterprise-grade security and zero transaction fees, SagaPay empowers merchants to accept crypto payments across multiple blockchains while maintaining full control of their digital assets.

Installation

pip install sagapay-sdk

Quick Start

from sagapay import Client, NetworkType

# Initialize the SagaPay client
client = Client(
    api_key="your-api-key",
    api_secret="your-api-secret"
)

# Create a deposit address
deposit = client.create_deposit({
    "network_type": NetworkType.BEP20,
    "contract_address": "0",  # Use '0' for native tokens (BNB)
    "amount": "1.5",
    "ipn_url": "https://yourwebsite.com/webhook",
    "udf": "order-123",
    "type": "TEMPORARY"
})

print(f"Deposit address created: {deposit.address}")
print(f"Expires at: {deposit.expires_at}")

Features

  • Deposit address generation
  • Withdrawal processing
  • Transaction status checking
  • Wallet balance fetching
  • Multi-chain support (ERC20, BEP20, TRC20, POLYGON, SOLANA)
  • Webhook notifications (IPN)
  • Custom UDF field support
  • Non-custodial architecture
  • Comprehensive error handling
  • Pydantic models for type safety

API Reference

Create Deposit

deposit = client.create_deposit({
    "network_type": NetworkType.BEP20,      # Required: Blockchain network type
    "contract_address": "0",                # Required: Contract address or '0' for native coins
    "amount": "1.5",                        # Required: Expected deposit amount
    "ipn_url": "https://example.com/webhook", # Required: URL for notifications
    "udf": "order-123",                     # Optional: User-defined field
    "type": "TEMPORARY",                    # Optional: TEMPORARY or PERMANENT
    "transfer_balance": True                # Optional: Auto-transfer received funds (default: true)
})

Create Withdrawal

withdrawal = client.create_withdrawal({
    "network_type": NetworkType.ERC20,
    "contract_address": "0xdAC17F958D2ee523a2206206994597C13D831ec7", # USDT on Ethereum
    "address": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
    "amount": "10.5",
    "ipn_url": "https://example.com/webhook",
    "udf": "withdrawal-456"
})

Check Transaction Status

# By address
status = client.check_transaction_status(
    transaction_type=TransactionType.DEPOSIT,
    address="0x742d35Cc6634C0532925a3b844Bc454e4438f44e"
)

# By transaction ID
status = client.check_transaction_status(
    transaction_type=TransactionType.DEPOSIT,
    id="deposit-uuid"
)

Fetch Wallet Balance

balance = client.fetch_wallet_balance(
    address="0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
    network_type=NetworkType.ERC20,
    contract_address="0xdAC17F958D2ee523a2206206994597C13D831ec7" # USDT on Ethereum
)

Verify IPN

verify_ipn() confirms directly with SagaPay that an IPN notification is genuine. It is the primary way to authenticate webhook notifications. Your API credentials are sent in the request body for this endpoint (no authentication headers are used).

from sagapay import IpnType

result = client.verify_ipn(
    txn_hash="0xabc123...",   # txHash from the webhook payload
    type=IpnType.DEPOSIT,     # or "DEPOSIT" / "WITHDRAWAL"
    amount="10.5",
    address="0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
)

if result.verified:
    print("Notification is genuine")

Handling Webhooks (IPN)

SagaPay sends webhook notifications to your specified ipn_url when a transaction completes. Delivery is at-least-once, so the same notification may be delivered more than once — make your handling idempotent (e.g. skip transaction IDs you have already processed).

The primary way to confirm a notification is genuine is client.verify_ipn(), which checks the transaction directly with SagaPay.

In addition, each webhook request carries an X-Sagapay-Signature: sha256=<hex digest> header — an HMAC-SHA256 of the exact raw request body, keyed with a platform-issued IPN secret (this is NOT your API secret). If SagaPay has issued you an IPN secret, pass it to WebhookHandler to verify the header; if you have none, leave it unset and signature verification is skipped.

from flask import Flask, request, jsonify
from sagapay import Client, IpnType, TransactionStatus, WebhookHandler

app = Flask(__name__)

client = Client(api_key="your-api-key", api_secret="your-api-secret")

# ipn_secret is the OPTIONAL platform-issued IPN secret (NOT your API secret).
# Leave it unset (None) if you have none -- signature verification is skipped.
webhook_handler = WebhookHandler(ipn_secret="your-ipn-secret")

@app.route("/webhook", methods=["POST"])
def handle_webhook():
    # Get the signature from the headers, e.g. "sha256=<hex digest>"
    signature = request.headers.get("X-Sagapay-Signature")

    # Get the exact raw request body (required for signature verification)
    payload = request.get_data()

    try:
        # Parse the payload (the signature is verified only when an
        # ipn_secret is configured)
        webhook = webhook_handler.process_webhook(payload, signature)

        # Primary check: confirm the notification with SagaPay
        verification = client.verify_ipn(
            txn_hash=webhook.tx_hash,
            type=webhook.type,
            amount=webhook.amount,
            address=webhook.address,
        )
        if not verification.verified:
            return jsonify({"received": False, "error": "IPN not verified"}), 200

        # Handle the transaction (delivery is at-least-once -- be idempotent)
        if webhook.status == TransactionStatus.COMPLETED:
            if webhook.type == IpnType.DEPOSIT:
                # Handle successful deposit
                update_order_status(webhook.udf, "paid")
            else:
                # Handle successful withdrawal
                update_withdrawal_status(webhook.udf, "completed")

        # Return a success response
        return jsonify({"received": True}), 200

    except Exception as e:
        # Log the error and return a response
        # Still return 200 to prevent retries
        return jsonify({"received": False, "error": str(e)}), 200

Webhook Payload Format

When SagaPay sends a webhook to your endpoint, it will include the following payload:

{
  "id": "transaction-uuid",
  "type": "DEPOSIT|WITHDRAWAL",
  "status": "COMPLETED",
  "address": "0x123abc...",
  "networkType": "ERC20|BEP20|TRC20|POLYGON|SOLANA",
  "amount": "10.5",
  "udf": "your-optional-user-defined-field",
  "txHash": "0xabc123...",
  "timestamp": "2025-03-16T14:30:00Z"
}

Notes:

  • type is uppercase (DEPOSIT or WITHDRAWAL) and parses to IpnType.
  • status is currently always COMPLETED — notifications are only sent when a transaction completes.
  • udf and txHash may be null.

Error Handling

The SDK includes comprehensive error handling with specific exception types. API errors are returned as {"error": "<human-readable message>"} — the message is surfaced in the exception, and the full body is available on e.response:

from sagapay import Client
from sagapay.exceptions import APIError, ValidationError, WebhookError, NetworkError

try:
    client = Client(api_key="your-api-key", api_secret="your-api-secret")
    deposit = client.create_deposit(params)
except ValidationError as e:
    print(f"Validation error: {e}")
except APIError as e:
    print(f"API error ({e.status_code}): {e.message}")
except NetworkError as e:
    print(f"Network error: {e}")

License

This SDK is released under the MIT License.

Support

For questions or support, please contact support@sagapay.net or visit https://sagapay.net.

Release files for sagapay-sdk 0.4.0

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

Source distribution (sdist)

Source distribution for sagapay-sdk 0.4.0
File Size Uploaded
sagapay_sdk-0.4.0.tar.gz 16.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for sagapay-sdk 0.4.0
File Interpreter ABI Platform
sagapay_sdk-0.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 29.4 kB

Release files / sagapay_sdk-0.4.0.tar.gz

Download URL sagapay_sdk-0.4.0.tar.gz
Size 16.7 kB
Tags Source
SHA-256 checksum
How to use checksums
f165f5e35a1a0f613b51f58e1da15612105aa2f648327de70cb6b389b1d1f1b2
BLAKE2b-256 checksum
How to use checksums
08cd9a50cb5c73d2d5688211dc2b3caff36d828ba59dfa802427e42e9782d97c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.7

Release files / sagapay_sdk-0.4.0-py3-none-any.whl

Download URL sagapay_sdk-0.4.0-py3-none-any.whl
Size 12.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d3cd3db482738ddd3b61a3244de581ce4d2e9c3c06d83da1e34a37f7c5f86b50
BLAKE2b-256 checksum
How to use checksums
b5aa514872768b613338f1a41b1f8b752ae6054587a9f52e4fa9cc295bdb01f6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.7

Release history Release notifications | RSS feed

0.4.1

2 release files

This release

0.4.0 This release

2 release files

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