zkp-sdk-python
Official Python SDK for the ZeroKYC Pay crypto payment gateway. Framework-agnostic, zero third-party runtime dependencies (standard library only), Python 3.10+, fully typed.
The same public contract and security guarantees as zkp-sdk-php: API client, webhook verification, idempotency, status normalization and payment matching are done for you.
Install
pip install zkp-sdk-python
(If the package is not on PyPI yet, install from source:
pip install git+https://github.com/zerokyc-payments/zkp-sdk-python.git
)
Quickstart (sandbox invoice in 5 minutes)
- Create an account at console.zerokyc-payments.com
and copy a sandbox API key (
pk_test_...) from API keys. - Create an invoice and send the buyer to the hosted checkout:
import os
from zerokyc import ZeroKYC, idempotency_key
zkp = ZeroKYC(api_key=os.environ["ZEROKYC_API_KEY"], environment="sandbox")
response = zkp.create_invoice(
"19.90", "USD",
order_id="INV-1042",
description="VPS plan: starter",
idempotency_key=idempotency_key("myshop", "order", 1042), # stable per local order
)
print(response.invoice.checkout_url) # redirect the buyer here
- Get paid: ZeroKYC detects the on-chain payment and POSTs a signed webhook.
A verified webhook (or a server-side
get_invoice()) is the only proof of payment — never a browser success URL.
from zerokyc.exceptions import WebhookVerificationError
try:
event = zkp.verify_webhook(request.body, request.headers["X-ZKP-Signature"])
except WebhookVerificationError:
return Response(status=400)
if event.is_payment_confirmed:
... # match invoice/amount/asset, then activate the order
Full production flow with duplicate protection and payment matching: examples/safe_webhook_handler_flask.py / examples/safe_webhook_handler_fastapi.py.
API surface
| Method | Purpose |
|---|---|
create_invoice(amount, currency, ...) |
create an invoice (idempotent with idempotency_key) |
get_invoice(invoice_id) |
reconciliation / polling / lost-webhook recovery |
cancel_invoice(invoice_id) |
cancel an unpaid invoice |
ping() |
liveness / configuration probe |
verify_webhook(raw_body, signature_header) |
HMAC verification of a delivery |
Configuration
ZeroKYC(api_key=..., environment=..., webhook_secret=..., timeout=15.0, max_retries=2, base_url=...)
api_key:pk_test_...(sandbox) /pk_live_...(production).environment:"sandbox"/"production"; inferred from the key; a mismatch raisesValueErrorinstead of hoping for the best.webhook_secret:whsec_...from console → Webhooks (used byverify_webhook).base_url: tests/local development only — the URL is defined centrally.
Status normalization
Raw API statuses never leak into your billing logic:
| API (raw) | InvoiceStatus |
|---|---|
created, pending |
PENDING |
detecting |
CONFIRMING |
confirmed |
PAID |
underpaid |
UNDERPAID |
expired |
EXPIRED |
canceled |
CANCELLED |
| unknown | FAILED (alert) |
invoice.is_paid / invoice.is_terminal answer the common questions.
Idempotency
from zerokyc import idempotency_key
idempotency_key("whmcs", "invoice", 1042) # zerokyc:whmcs:invoice:1042 (<=120 chars)
A timeout + retry then returns the same invoice
(CreateInvoiceResponse.idempotent_replay is True) instead of a duplicate.
Error handling & retries
| Exception | HTTP | Retried automatically? |
|---|---|---|
AuthenticationError |
401 / 403 | never |
ValidationError |
400 / 422 | never |
RateLimitError |
429 | yes (Retry-After up to 5s, max twice) |
APIError |
5xx, 402, 404 | only GET / idempotent POST |
NetworkError |
transport | only GET / idempotent POST |
WebhookVerificationError |
n/a | n/a (machine-readable .reason) |
Backoff is bounded exponential (300ms → 600ms → 1200ms, capped by max_retries).
Webhook security checklist
- verify against the exact raw body (never re-serialized JSON);
- strict
t=/v1=header format, lowercase hex, constant-time compare (built in); - default ±300 s window (
WebhookVerifier(secret, 600)to widen); - at-least-once delivery:
ReplayGuard.is_duplicate()is a pure check — callmark_processed()only after the local order update succeeded; - match invoice id / amount / asset before crediting (
ReplayGuard.matches_order()); - secrets never appear in exceptions or logs.
Self-test against the documented vector:
from zerokyc import WebhookVerifier
event = WebhookVerifier("whsec_zkp_test_vector_2026").verify(
'{"id":"evt_test_001","type":"payment.confirmed","invoice_id":"inv_test_001"}',
"t=1788788073,v1=ade537fa13aec79a6d1648bd7f197872066c161676c389243ab5c6b13fea7f52",
now=1788788073,
)
Assets
USDT (TRC-20), USDC/USDT (Polygon, Arbitrum), BTC, XMR, TON, USDT-TON. Pin one via
payment_currency="USDT_TRON", or let the buyer choose with "any" (default).
Development
pip install -e ".[dev]"
pytest
ruff check .
License
MIT — see LICENSE.
Metadata
Release files for zkp-sdk-python 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| zkp_sdk_python-0.1.0.tar.gz | 25.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| zkp_sdk_python-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 45.1 kB
Release files / zkp_sdk_python-0.1.0.tar.gz
| Download URL | zkp_sdk_python-0.1.0.tar.gz |
|---|---|
| Size | 25.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7f7a859f0dcef15b4919a7ed19a52c5a7f05007f1f429d283b2a647804ee70f2
|
|
BLAKE2b-256 checksum How to use checksums |
6cb891877ce3b3dce9e50d2877efdf8e049ebd98fcff77741e36dd1f37b88d03
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 9, 2026.
Transparency logRelease files / zkp_sdk_python-0.1.0-py3-none-any.whl
| Download URL | zkp_sdk_python-0.1.0-py3-none-any.whl |
|---|---|
| Size | 19.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9b69bd3918b15229249f1da0a270b9c21f0b47e4477f35971de58cc4ac62d30c
|
|
BLAKE2b-256 checksum How to use checksums |
376e9a40dd336b91e1aeaa2d3d704759320af538ee47246407a06d4582eee3c4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 9, 2026.
Transparency log