Python SDK
Official server-side SDK for integrating ZevPay Checkout in Python applications. Provides full REST API coverage with httpx HTTP client.
Installation
bash
pip install zevpayRequires Python 3.8 or later.
Quick start
python
from zevpay import ZevPay
client = ZevPay("sk_test_your_secret_key")
# Initialize a checkout session
session = client.checkout.initialize(
amount=500000, # ₦5,000 in kobo
email="customer@example.com",
reference="ORDER-123",
callback_url="https://yoursite.com/callback",
)
print(session["checkout_url"])Configuration
python
client = ZevPay(
"sk_live_xxx",
base_url="https://api.zevpaycheckout.com", # default
timeout=30, # 30s request timeout (default)
max_retries=2, # retries on 5xx errors (default)
)| Option | Type | Default | Description |
|---|---|---|---|
base_url | str | https://api.zevpaycheckout.com | API base URL |
timeout | int | 30 | Request timeout in seconds |
max_retries | int | 2 | Max retries on server errors |
Secret keys only
The SDK only accepts secret keys (sk_live_* or sk_test_*). Public keys cannot be used server-side.
Checkout sessions
Initialize a session
python
session = client.checkout.initialize(
amount=500000,
email="customer@example.com",
currency="NGN",
reference="ORDER-123",
callback_url="https://yoursite.com/callback",
metadata={"order_id": "123"},
payment_methods=["bank_transfer", "payid"],
)
# Redirect your customer to:
print(session["checkout_url"])Verify a payment
python
result = client.checkout.verify(session["session_id"])
if result["status"] == "completed":
print(f"Payment confirmed at: {result['paid_at']}")Get session details
python
details = client.checkout.get("ses_abc123")Transfers
Bank transfer
python
transfer = client.transfers.create(
type="bank_transfer",
amount=1000000, # ₦10,000
account_number="0123456789",
bank_code="044",
account_name="John Doe",
narration="Payout",
reference="TXN-123",
)PayID transfer
python
transfer = client.transfers.create(
type="payid",
amount=500000,
pay_id="johndoe",
narration="Payment",
)List, verify, resolve
python
# List transfers
transfers = client.transfers.list(
page=1,
page_size=20,
status="completed",
)
# Verify a transfer
result = client.transfers.verify("TXN-123")
# List banks
banks = client.transfers.list_banks()
# Resolve bank account
account = client.transfers.resolve_account(
account_number="0123456789",
bank_code="044",
)
print(account["account_name"]) # 'JOHN DOE'
# Calculate fees
charges = client.transfers.calculate_charges(amount=1000000)
# Get wallet balance
balance = client.transfers.get_balance()Invoices
python
# Create
invoice = client.invoices.create(
customer_name="Jane Doe",
customer_email="jane@example.com",
due_date="2026-04-01",
line_items=[
{"description": "Web Design", "quantity": 1, "unit_price": 5000000},
{"description": "Hosting (1yr)", "quantity": 1, "unit_price": 1200000},
],
tax_rate=7.5,
)
# Send (draft → sent)
client.invoices.send(invoice["public_id"])
# List
invoices = client.invoices.list(status="sent")
# Cancel
client.invoices.cancel(invoice["public_id"])Static PayIDs
python
# Create
payid = client.static_payid.create(
pay_id="mystore",
name="My Store",
description="Accept payments to my store",
)
# Deactivate / Reactivate
client.static_payid.deactivate(payid["id"])
client.static_payid.reactivate(payid["id"])Dynamic PayIDs
python
# Create a time-limited payment link
dpayid = client.dynamic_payid.create(
amount=1000000,
name="Donation Drive",
expires_in_minutes=60,
)
print(dpayid["full_pay_id"]) # e.g. 'donation-drive-xyz.dpay'
# Deactivate
client.dynamic_payid.deactivate(dpayid["id"])Virtual accounts
python
# Create
va = client.virtual_accounts.create(
amount=1000000,
validity_minutes=60,
)
print(va["account_number"]) # Customer pays to this account
# List
accounts = client.virtual_accounts.list(status="pending")Wallet
python
# Get wallet details
wallet = client.wallet.get()
# List members
members = client.wallet.list_members()
# Add / remove members
client.wallet.add_member(pay_id="johndoe")
client.wallet.remove_member("johndoe")Webhook verification
Verify incoming webhook signatures using your webhook secret:
python
import os
from zevpay import Webhook, ZevPayError
# In your webhook handler (e.g. Flask, Django, FastAPI)
payload = request.get_data(as_text=True)
signature = request.headers.get("x-zevpay-signature", "")
secret = os.environ["ZEVPAY_WEBHOOK_SECRET"]
try:
event = Webhook.construct_event(payload, signature, secret)
if event["event"] == "charge.success":
# Handle successful checkout payment
pass
elif event["event"] == "transfer.success":
# Handle successful transfer
pass
elif event["event"] == "transfer.failed":
# Handle failed transfer
pass
elif event["event"] == "invoice.paid":
# Handle paid invoice
pass
return "OK", 200
except ZevPayError:
return "Invalid signature", 400Always verify
Never process webhook events without verifying the signature. See Verifying Signatures for details.
Error handling
All API errors raise typed exceptions:
python
from zevpay import (
ZevPay,
ValidationError,
AuthenticationError,
NotFoundError,
ConflictError,
RateLimitError,
ApiError,
)
client = ZevPay("sk_test_your_secret_key")
try:
client.transfers.create(type="bank_transfer", amount=1000000)
except ValidationError as e:
# 400 — invalid parameters
print(e.code) # e.g. 'VALIDATION_ERROR'
print(e.message) # Human-readable message
except AuthenticationError:
# 401 — invalid API key
pass
except NotFoundError:
# 404 — resource not found
pass
except ConflictError:
# 409 — duplicate transaction
pass
except RateLimitError:
# 429 — rate limit exceeded
pass
except ApiError:
# 500+ — server error
pass| Exception class | Status | When |
|---|---|---|
ValidationError | 400 | Invalid request parameters |
AuthenticationError | 401 | Invalid or missing API key |
ForbiddenError | 403 | Insufficient permissions |
NotFoundError | 404 | Resource not found |
ConflictError | 409 | Duplicate resource |
RateLimitError | 429 | Too many requests |
ApiError | 500+ | Server error |
Context manager
The client can be used as a context manager to ensure the HTTP connection is properly closed:
python
with ZevPay("sk_test_your_secret_key") as client:
session = client.checkout.initialize(
amount=500000,
email="customer@example.com",
)Full example — FastAPI
python
import os
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse, RedirectResponse
from zevpay import ZevPay, Webhook, ZevPayError
app = FastAPI()
zevpay = ZevPay(os.environ["ZEVPAY_SECRET_KEY"])
@app.post("/api/pay")
async def create_payment(request: Request):
body = await request.json()
session = zevpay.checkout.initialize(
amount=body["amount"],
email=body["email"],
reference=f"ORDER-{body['order_id']}",
callback_url=str(request.url_for("payment_callback")),
)
return {"checkout_url": session["checkout_url"]}
@app.get("/api/callback")
async def payment_callback(session_id: str):
result = zevpay.checkout.verify(session_id)
if result["status"] == "completed":
return {"message": "Payment successful!"}
return {"message": "Payment not completed yet."}
@app.post("/webhooks/zevpay")
async def webhook_handler(request: Request):
payload = (await request.body()).decode()
signature = request.headers.get("x-zevpay-signature", "")
try:
event = Webhook.construct_event(
payload, signature, os.environ["ZEVPAY_WEBHOOK_SECRET"]
)
print(f"Webhook received: {event['event']}")
return {"status": "ok"}
except ZevPayError:
return JSONResponse({"error": "Invalid signature"}, status_code=400)Resources
- API Reference — Full endpoint documentation
- Webhook Events — All event types
- PyPI — Package registry