Skip to content

About

A basic Python Async Client for interacting with the SHKeeper API to manage cryptocurrency invoices.

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Latest commit

 

History

14 Commits

Folders and files

Repository files navigation

shkeeper

A typed sync and async Python client for SHKeeper, the self-hosted crypto payment processor.

  • Covers the full SHKeeper v1 API: invoices, payouts, multipayouts, task status, addresses, transactions, wallet decryption and metrics
  • SHKeeper (sync) and AsyncSHKeeper (asyncio) with the same methods
  • Typed dataclass responses with Decimal amounts
  • Webhook signature verification (HMAC-SHA256) and notification parsing
  • Clear exception hierarchy

Installation

pip install git+https://github.com/botsgalaxy/shkeeper-python.git

Requires Python 3.9+.

Quick start

from shkeeper import SHKeeper

with SHKeeper(
    "https://pay.example.com",
    api_key="your-api-key",
    callback_url="https://shop.example.com/shkeeper/webhook",
) as shkeeper:
    for crypto in shkeeper.get_cryptos():
        print(crypto.name, crypto.display_name)

    invoice = shkeeper.create_invoice("ETH-USDT", external_id="order_123", amount="100")
    print(invoice.wallet, invoice.amount, invoice.exchange_rate)

Async:

from shkeeper import AsyncSHKeeper

async with AsyncSHKeeper("https://pay.example.com", api_key="your-api-key") as shkeeper:
    invoice = await shkeeper.create_invoice(
        "BTC", "order_123", "100", callback_url="https://shop.example.com/webhook"
    )

base_url is the root of your SHKeeper instance. A trailing /api/v1 is accepted and stripped.

Authentication

SHKeeper uses two kinds of credentials:

Credential Client argument Used by
API key (Wallets → Manage → API key) api_key invoices, addresses, transactions, payment info, wallet decryption
SHKeeper UI login (HTTP Basic) username, password payouts, multipayouts, task status
Metrics login metrics_username, metrics_password get_metrics()

get_cryptos() needs no credentials.

Methods

Method Endpoint Returns
get_cryptos() GET /api/v1/crypto list[CryptoCurrency]
create_invoice(crypto, external_id, amount, *, callback_url=None, fiat="USD") POST /api/v1/{crypto}/payment_request Invoice
get_invoices(external_id) GET /api/v1/invoices/{external_id} list[InvoiceInfo]
get_addresses(crypto) GET /api/v1/{crypto}/addresses list[str]
get_transactions(crypto, addr) GET /api/v1/transactions/{crypto}/{addr} list[Transaction]
get_payment_info(txid, external_id) GET /api/v1/tx-info/{txid}/{external_id} PaymentInfo
decrypt_wallets(key) POST /api/v1/decryption-key bool
create_payout(crypto, destination, amount, fee, *, callback_url=None, external_id=None) POST /api/v1/{crypto}/payout PayoutTask
create_multipayout(crypto, recipients) POST /api/v1/{crypto}/multipayout PayoutTask
get_task(crypto, task_id) GET /api/v1/{crypto}/task/{task_id} TaskStatus
wait_for_task(crypto, task_id, *, interval=5, timeout=300) polls get_task TaskStatus
get_metrics() GET /metrics str (Prometheus format)

Calling create_invoice again with the same external_id updates the existing invoice. Amounts can be str, int, float or Decimal; they are sent as plain decimal strings.

Payouts

from shkeeper import SHKeeper, PayoutRecipient

shkeeper = SHKeeper("https://pay.example.com", username="admin", password="secret")

task = shkeeper.create_payout("BTC", "bc1q...", amount="0.01", fee=12)
status = shkeeper.wait_for_task("BTC", task.task_id)
if status.is_success:
    for result in status.result:
        print(result.dest, result.txids)

task = shkeeper.create_multipayout(
    "ETH-USDT",
    [PayoutRecipient("0xAAA...", "100"), PayoutRecipient("0xBBB...", "9.99")],
)

fee is required by SHKeeper. It is sat/vByte for BTC, sat/Byte for LTC and DOGE, 1–4 priority for XMR, and ignored for other coins. Multipayout is not supported for BTC, LTC, DOGE and XMR. For XRP pass dest_tag on PayoutRecipient or use an X-address.

Webhooks

SHKeeper POSTs a JSON notification to your callback_url when an invoice receives a payment, and when a payout completes (if payout callbacks are enabled). Requests are signed with your API key. Respond with HTTP 202; anything else makes SHKeeper retry every 60 seconds.

from flask import Flask, request
from shkeeper import PaymentNotification, WebhookVerificationError, webhooks

app = Flask(__name__)


@app.post("/shkeeper/webhook")
def shkeeper_webhook():
    try:
        event = webhooks.construct_event("your-api-key", request.get_data(), request.headers)
    except WebhookVerificationError:
        return "", 400

    if isinstance(event, PaymentNotification):
        if event.paid:
            mark_order_paid(event.external_id, event.balance_fiat)
    else:
        mark_payout_done(event.external_id, event.tx_hash)

    return "", 202

construct_event checks X-Shkeeper-Signature and X-Shkeeper-Timestamp (rejecting timestamps older than 5 minutes by default, tolerance=None disables this) and returns a PaymentNotification or PayoutNotification. Always pass the raw request body, not re-serialized JSON. verify_signature and parse_notification are available separately.

PaymentNotification.status is PARTIAL, PAID or OVERPAID, and trigger_transaction gives the transaction that caused the notification.

Errors

All exceptions inherit from SHKeeperError:

Exception Raised when
AuthenticationError bad or missing API key / credentials (400, 401, 403)
NotFoundError 404
ServerError 5xx
APIError any other error response, including {"status": "error"} bodies
NetworkError connection failures and timeouts
WebhookVerificationError invalid webhook signature, timestamp or body

API errors carry message, status_code and the raw body.

Configuration

import httpx
from shkeeper import SHKeeper

shkeeper = SHKeeper(
    "https://pay.example.com",
    api_key="...",
    timeout=30,
    http_client=httpx.Client(proxy="http://proxy:8080"),
)

Pass your own httpx.Client / httpx.AsyncClient to control proxies, retries or TLS. A client you pass in is not closed by SHKeeper.

Development

pip install -e ".[dev]"
pytest

License

MIT. Author: BotsGalaxy · Telegram primeakash

About

A basic Python Async Client for interacting with the SHKeeper API to manage cryptocurrency invoices.

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Used by

Contributors

Languages