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.3

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.3
File Size Uploaded Provenance
payshen-0.1.3.tar.gz 20.1 kB With provenance Details

Built distribution (wheel)

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

Total release size: 35.7 kB

Release files / payshen-0.1.3.tar.gz

Download URL payshen-0.1.3.tar.gz
Size 20.1 kB
Tags Source
SHA-256 checksum
How to use checksums
f33370732936a279b0df7a87d5cbada2ec542ae8e33296c72fd3bbe0dc46a8dc
BLAKE2b-256 checksum
How to use checksums
a2b8858df986f1954ef2f1b43a38fd0582f3050e47eb61b555d154ae02c3731d
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 24, 2026.

Transparency log

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

Download URL payshen-0.1.3-py3-none-any.whl
Size 15.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9d18b17665a4c48dd365540a7738dd86199da4ad8c3e99c5cb8c09c245c98a00
BLAKE2b-256 checksum
How to use checksums
57caa6f6d0946a9582a787c28db219cc76e7cf29d4db539bc6a67efcad32b085
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 24, 2026.

Transparency log

Security for payshen 0.1.3

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.3.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 24, 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