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 zevpayOR
bash
pip install "git+https://github.com/zevpay/zevpay-python.git@v0.1.1"Requires 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