โ† Back to Blog

How to Accept Bitcoin Payments in Your Python Application

Accept Bitcoin Payments Python ยท 527 words

*Last updated: July 2026*

Accepting Bitcoin payments in your Python application is straightforward with the right tools. This guide shows you how to integrate BTC payments that work globally, with no middlemen.

Why Accept Bitcoin?

Option 1: Direct Integration (No Third Party)

The simplest approach - accept BTC directly to your wallet:


import requests
import time

def get_btc_balance(address):
    """Check BTC balance using Blockstream API."""
    url = f"https://blockstream.info/api/address/{address}"
    resp = requests.get(url, timeout=10)
    data = resp.json()
    
    # Calculate balance from UTXOs
    balance = 0
    for tx in data.get("chain_stats", []):
        balance += tx.get("funded_txo_sum", 0)
        balance -= tx.get("spent_txo_sum", 0)
    
    return balance / 100_000_000  # Convert from satoshis

def create_invoice(amount_btc, product_id):
    """Create a payment invoice."""
    return {
        "invoice_id": f"inv_{int(time.time())}",
        "amount": amount_btc,
        "product": product_id,
        "status": "pending",
        "created_at": time.time()
    }

def check_payment(invoice_id, address):
    """Check if invoice has been paid."""
    balance = get_btc_balance(address)
    return balance > 0

Option 2: Using BTCPay Server (Self-Hosted)

BTCPay Server is free, open-source, and self-hosted:


import requests

BTCPAY_URL = "https://your-btcpay-server.com"
BTCPAY_TOKEN = "your_api_token"

def create_btcpay_invoice(amount_sats, product_id):
    """Create invoice via BTCPay Server."""
    resp = requests.post(
        f"{BTCPAY_URL}/api/v1/invoices",
        headers={"Authorization": f"token {BTCPAY_TOKEN}"},
        json={
            "amount": amount_sats,
            "currency": "BTC",
            "metadata": {"product_id": product_id}
        }
    )
    return resp.json()

def check_btcpay_status(invoice_id):
    """Check invoice status."""
    resp = requests.get(
        f"{BTCPAY_URL}/api/v1/invoices/{invoice_id}",
        headers={"Authorization": f"token {BTCPAY_TOKEN}"}
    )
    return resp.json()["status"] == "complete"

Option 3: Using a Payment Processor

Services like BitPay or CoinGate handle everything:


# Example with a generic processor
def create_processor_invoice(amount_usd, product_id):
    """Create invoice via payment processor."""
    resp = requests.post(
        "https://api.processor.com/invoices",
        headers={"Authorization": "Bearer your_key"},
        json={
            "price_amount": amount_usd,
            "price_currency": "USD",
            "receive_currency": "BTC",
            "order_id": product_id
        }
    )
    return resp.json()

Complete Payment Flow


import hashlib

class BitcoinPaymentHandler:
    def __init__(self, btc_address):
        self.btc_address = btc_address
        self.payments = {}
    
    def create_payment(self, user_id, amount_btc, product_id):
        """Create a new payment request."""
        payment_id = hashlib.sha256(
            f"{user_id}-{product_id}-{int(time.time())}".encode()
        ).hexdigest()[:16]
        
        self.payments[payment_id] = {
            "user_id": user_id,
            "amount": amount_btc,
            "product": product_id,
            "address": self.btc_address,
            "status": "pending",
            "created_at": time.time()
        }
        
        return payment_id
    
    def check_payment(self, payment_id):
        """Check if payment was received."""
        payment = self.payments.get(payment_id)
        if not payment:
            return False
        
        # Check blockchain
        balance = get_btc_balance(payment["address"])
        if balance >= payment["amount"]:
            payment["status"] = "paid"
            return True
        
        return False
    
    def get_payment_status(self, payment_id):
        """Get current payment status."""
        payment = self.payments.get(payment_id)
        if not payment:
            return "not_found"
        
        # Auto-expire after 24 hours
        if time.time() - payment["created_at"] > 86400:
            payment["status"] = "expired"
        
        return payment["status"]

Security Best Practices

1. Never reuse addresses: Generate a new address for each payment

2. Wait for confirmations: At least 1 confirmation for small amounts, 3+ for large

3. Validate amounts: Check the exact amount sent, not just "any" payment

4. Log everything: Keep detailed records for accounting

5. Use HTTPS: Never transmit payment info over HTTP

Get the Production-Ready Version

We have a complete Bitcoin payment integration at [our store](https://petroleum-board-hawaii-lol.trycloudflare.com).

What's included:

[Browse the collection โ†’](https://petroleum-board-hawaii-lol.trycloudflare.com)

๐Ÿ›’ Ready to deploy?

Browse 120+ Python tools with crypto payments and instant delivery.

Browse Products โ†’