Skip to main content

Payshen Python

The Python client for the Payshen API: create and route payments, capture, void and refund them, read their timeline, and verify the webhooks Payshen sends.

Payshen routes each payment to one of the providers you already have (Stripe, Adyen, Checkout.com, payabl. and more). Payshen never holds or moves money: payments run on your own provider accounts.

  • Python 3.9 or newer. No dependencies: the standard library only.
  • Every POST carries an Idempotency-Key, so a retry after a dropped connection never charges twice.
  • Retries with backoff and jitter, on the answers worth retrying and never on the ones the API says not to.
  • Typed exceptions with the API's own error code and the request id support will ask for.

Install

pip install payshen

Create a payment

import os
from payshen import Payshen

payshen = Payshen(os.environ["PAYSHEN_API_KEY"])  # ps_test_... in the sandbox

payment = payshen.payments.create(
    {
        "amount": 5000,              # minor units: EUR 50.00
        "currency": "EUR",
        "country": "DE",
        "reference": "order-1024",
        "capture_method": "manual",  # hold now, capture when you ship
        "return_url": "https://yourshop.com/checkout/return",
    },
    idempotency_key="order-1024",
)

# REQUIRES_ACTION: send the customer to the provider's page.
redirect_to = payment["next_action"]["url"]

The customer pays on the provider's page and comes back to your return_url. The return is not the outcome: the outcome is the webhook (payment.authorized, payment.captured, payment.declined, ...).

Capture, void, refund

from payshen import PayshenError

payshen.payments.capture(payment_id, idempotency_key="capture-order-1024")               # in full
payshen.payments.capture(payment_id, amount=3000, idempotency_key="capture-order-1024")  # or in part
payshen.payments.void(payment_id, idempotency_key="void-order-1024")                     # before capture

try:
    payshen.payments.refund(payment_id, amount=2000, idempotency_key="refund-order-1024-1")
except PayshenError as e:
    # 409 refund_pending: accepted, not failed. The provider confirms a moment later and
    # payment.refunded or payment.refund_failed follows. Do not send it again under a new key.
    if e.code != "refund_pending":
        raise

A capture or void a provider only accepted answers with the payment PENDING; it becomes CAPTURED or CANCELLED when the provider confirms, and the webhook follows.

Read

payment = payshen.payments.get(payment_id)
timeline = payshen.payments.events(payment_id)

page = payshen.payments.list(limit=50, status="captured")
for payment in payshen.payments.all(status="captured"):
    ...  # every page, newest first

for event in payshen.events.all(type="payment.captured"):
    ...  # the same events webhooks deliver, for polling

Webhooks

from payshen import SignatureVerificationError, parse_webhook_event

# Flask. Django: request.body and request.headers["X-Payshen-Signature"].
raw = request.get_data()  # the RAW body: a body re-encoded from json never verifies
try:
    event = parse_webhook_event(raw, request.headers.get("X-Payshen-Signature"), os.environ["PAYSHEN_WEBHOOK_SECRET"])
except SignatureVerificationError:
    return "", 400

# Deliveries are retried, so the same event can arrive twice. Record event["id"]
# and skip one you have already processed.
if event["type"] == "payment.captured":
    fulfil(event["data"]["reference"])
return "", 204

The signature proves a delivery came from Payshen and is recent (5 minutes by default); it does not make it new. claim_webhook_event(raw, header, secret, store) verifies, parses and takes each event once, with a store you back with your database:

class DbEventStore:
    def claim(self, event_id: str) -> bool:
        # PostgreSQL; MySQL: INSERT IGNORE and the affected row count
        cur.execute("INSERT INTO processed_webhook_events (id) VALUES (%s) ON CONFLICT (id) DO NOTHING RETURNING id", (event_id,))
        return cur.fetchone() is not None

During a secret rotation pass both: parse_webhook_event(raw, header, [new_secret, old_secret]).

Errors

Exception When
AuthenticationError 401 or 403: a missing, wrong or revoked key, or one not allowed this call
ValidationError 422: refused as sent; code names the rule
RateLimitError 429 after the client's retries; retry_after_seconds when the API said
NetworkError No answer at all. On a POST, retry with the same idempotency key
PayshenError Everything else, and the parent of all of the above

Every exception has status, code (refund_pending, not_capturable, payment_result_unknown, ...) and request_id. Branch on code, not on the message.

Options

Payshen(key, timeout=20.0, max_retries=3, base_url="https://www.payshen.com")

payshen.request("GET", "/api/v1/...") calls any endpoint and returns the whole answer.

Documentation

License

MIT

Metadata

Release files for payshen 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for payshen 0.1.0
File Size Uploaded Provenance
payshen-0.1.0.tar.gz 17.2 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for payshen 0.1.0
File Interpreter ABI Platform
payshen-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 32.2 kB

Release files / payshen-0.1.0.tar.gz

Download URL payshen-0.1.0.tar.gz
Size 17.2 kB
Tags Source
SHA-256 checksum
How to use checksums
02f06e5764fe74bc5fcb8f695480031a155db3586c9df554ab727df0ec4d159b
BLAKE2b-256 checksum
How to use checksums
9ad7cb95e1582501931be7295ffc7ec160e6df3b294f40e18c45734ed5d2a665
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 Oct 13, 2026.

Transparency log

Release files / payshen-0.1.0-py3-none-any.whl

Download URL payshen-0.1.0-py3-none-any.whl
Size 15.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0d26c907fa53b4daf18f5ce46dec44f3061defbe8ba6f4d47de6a78f3ec17d41
BLAKE2b-256 checksum
How to use checksums
05a45e3e3ddcac3df25b822ef02b885b373de5ffe315670a2940cb9e41c35860
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 Oct 13, 2026.

Transparency log

Security for payshen 0.1.0

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.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for payshen-0.1.0.tar.gz

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 Oct 13, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page