Skip to main content

Python SDK

Typed Python client for the Von Payments Checkout API, published as vonpay-checkout on PyPI.

Requirements: Python 3.9+, httpx

Install

pip install vonpay-checkout

Pinning to an exact version is recommended during the pre-1.0 window — minor bumps may add options or change defaults.

Initialize

from vonpay.checkout import VonPayCheckout, VonPayError

client = VonPayCheckout("vp_sk_test_...", api_version="2026-04-14")

The api_version parameter pins the API version for all requests made by this client instance. See API Versioning for details.

Sessions

Create a session

session = client.sessions.create(
amount=1499,
currency="USD",
country="US",
)

print(session.id) # "vp_cs_test_abc123"
print(session.checkout_url) # "https://checkout.vonpay.com/checkout?session=..."

Returns a CheckoutSession object.

Get a session

status = client.sessions.get("vp_cs_test_abc123")

print(status.status) # "succeeded"
print(status.amount) # 1499

Returns a SessionStatus object. Requires a secret key.

Validate (dry run)

result = client.sessions.validate(
amount=1499,
currency="USD",
)
# Validates parameters without creating a session

Webhooks

Verify signature

Verify the HMAC-SHA256 signature on an incoming webhook request. The webhook secret is per-endpoint (whsec_*), minted when you register the endpoint at /dashboard/developers/webhooks.

is_valid = client.webhooks.verify_signature(
payload=request_body,
signature_header=request.headers["x-vonpay-signature"],
secret=os.environ["VON_PAY_WEBHOOK_SECRET"], # whsec_*
)

Construct event

Parse and verify a webhook payload into a typed event object. Enforces the asymmetric replay window (5 min past / 30 sec future).

event = client.webhooks.construct_event(
payload=request_body,
signature_header=request.headers["x-vonpay-signature"],
secret=os.environ["VON_PAY_WEBHOOK_SECRET"], # whsec_*
)

print(event.type) # "charge.succeeded"
print(event.data["transaction_id"]) # "vp_tx_test_9f2nd..."

Webhook management

Read-only access to your registered webhook endpoints and stored event records. These methods all require a secret key (vp_sk_*) — publishable keys are rejected with 403. The wire format is camelCase end-to-end and parsed into typed dataclasses.

List webhook subscriptions

subs = client.webhook_subscriptions.list(
limit=20, # optional
starting_after="b6f2c1a0-3e4d-4c8b-9a1f-2d5e7c9b0a13", # optional cursor
)

for sub in subs.data:
print(sub.id, sub.url, sub.status)

print(subs.has_more) # True if more pages remain

Results are newest-first. To page, pass the last item's id as starting_after. A cursor that doesn't reference a subscription owned by your merchant raises a 400 validation_error (pagination is not silently restarted from the top).

Returns a WebhookSubscriptionsList object with object, data (a list of WebhookSubscription), has_more, and url. Requires a secret key.

Retrieve a webhook subscription

sub = client.webhook_subscriptions.retrieve("b6f2c1a0-3e4d-4c8b-9a1f-2d5e7c9b0a13")

print(sub.url) # the registered endpoint URL
print(sub.enabled_events) # ["charge.succeeded", ...]
print(sub.status) # "active" | "paused" | "disabled"

Returns a WebhookSubscription object. A cross-merchant or soft-deleted id returns 404 (opaque — never 403). The signing secret is never present on a read response. Requires a secret key.

Retrieve a stored webhook event

record = client.webhook_events.retrieve("vp_wh_5x9k2m4n")

print(record.type) # "charge.succeeded"
print(record.processed) # True | False
print(record.retry_count) # int

Returns a WebhookEventRecord — the durable, queryable record of a stored event (distinct from the signed payload that webhooks.construct_event parses). Use it from your own code, e.g. an admin tool, retry trigger, or audit dashboard. Requires a secret key.

Confirming a return redirect

When the buyer is redirected back to your success_url, read the outcome from the API — the redirect itself only tells you they came back.

client = VonPayCheckout(os.environ["VON_PAY_SECRET_KEY"])

session_id = request.args["session"]
session = client.sessions.get(session_id)

if session.status == "succeeded":
... # show the confirmation page

Fulfil the order from the charge.succeeded webhook rather than here — a buyer who pays and closes the tab never loads this page. See Handle the Return.

verify_return_signature is not how you confirm a payment

The SDK still exposes this static method, but a signature check answers "was this message altered?" — not "did the buyer pay?" A declined payment carries an equally valid signature, so it must never gate a confirmation page or an order. Use the status lookup above.

Signature verification belongs on webhooks, where each endpoint has its own whsec_* secret — see Webhooks.

Health Check

health = client.health()

print(health.status) # "ok" | "healthy" | "degraded"
print(health.latency_ms) # float — measured dependency latency (ms)
print(health.version) # server build/version string

Returns a HealthStatus dataclass with status, latency_ms, and version.

Error Handling

All API errors raise VonPayError with structured fields for programmatic handling.

from vonpay.checkout import VonPayCheckout, VonPayError

try:
session = client.sessions.create(amount=-1, currency="USD")
except VonPayError as e:
print(e.status) # 400
print(e.code) # "validation_invalid_amount"
print(e.fix) # "Amount must be a positive integer in minor units (cents). 1499 = $14.99"
print(e.docs) # "https://docs.vonpay.com/integration/create-session#required-fields"

Error reporting

The SDK accepts an optional error_reporter callback so integrators can pipe SDK failures into their own observability stack (Sentry, Datadog, custom logger). Your reporter is invoked synchronously, fire-and-forget; if it raises, the SDK swallows it (with a logging.warning on the vonpay.checkout logger) and continues.

When it fires

  • API request failures: non-retryable 4xx, retry-exhaustion on 5xx, network/timeout errors after retry exhaustion
  • webhooks.construct_event / construct_event_v2 verification failures (signature mismatch, stale timestamp, malformed v2 header)

It does not fire on:

  • verify_signature / verify_return_signature — these return bool, never raise
  • The constructor's invalid-key-prefix ValueError — that's a dev-time error before the reporter is wired

Callback shape

from vonpay.checkout import ErrorReporter, ErrorReporterContext, VonPayError

def reporter(err: Exception, ctx: ErrorReporterContext) -> None:
# err is VonPayError or another Exception subclass
# ctx fields:
# method: str — "sessions.create" / "webhooks.construct_event" / etc.
# sdk_version: str
# url: str | None — origin + path, no query string (no PII via params)
# status: int | None — HTTP status if from API response
# request_id: str | None — X-Request-Id for correlation
# code: str | None — server error code
# attempt: int | None — 0-indexed retry attempt
...

Sentry example

import sentry_sdk
from vonpay.checkout import VonPayCheckout

def report_to_sentry(err, ctx):
sentry_sdk.capture_exception(
err,
tags={"sdk": "vonpay-python", "method": ctx.method, "code": ctx.code},
contexts={"vonpay": ctx.__dict__},
)

client = VonPayCheckout(
api_key=os.environ["VON_PAY_SECRET_KEY"],
error_reporter=report_to_sentry,
)

Logging example

import logging
from vonpay.checkout import VonPayCheckout

log = logging.getLogger("myapp")

client = VonPayCheckout(
api_key=os.environ["VON_PAY_SECRET_KEY"],
error_reporter=lambda err, ctx: log.error(
"vonpay sdk error", extra={"err": str(err), "ctx": ctx.__dict__}
),
)

error_reporter is opt-in and additive — if you don't configure it, errors still propagate via raise and nothing else changes.


Auto-Retry

The SDK automatically retries on 429 (rate limited) and 5xx (server error) responses using exponential backoff. Default is 2 retries; configure with the max_retries constructor argument.


Sample app

Clone-and-run reference integration using this SDK lives in Von-Payments/vonpay-samples:

  • checkout-flask — Flask hosted checkout with signed return verification + webhook handler

Ships with .env.example, a per-sample README, and pinned to a known-working SDK version.