PayWay REST API - Python
- Store customers, their card and bank account in PayWay
- Take payment using a stored credit card or bank account
- Process and Capture a pre-authorisation
- Lookup or poll transactions
- Refund transactions
- Void transactions
- Update a customer's payment setup in PayWay
Install
Requires Python 3.11 or later.
pip install python-payway
Take payment using a stored credit card
Create a Client class with your PayWay API credentials
from payway.client import Client
client = Client(merchant_id='<your_payway_merchant_id>',
bank_account_id='<your_payway_bank_account_id>',
publishable_api_key='<your_payway_publishable_api_key>',
secret_api_key='<your_payway_secret_api_key>')
Create a PayWayCustomer class with your customer's details
customer = PayWayCustomer(custom_id='c981a',
customer_name='John Smith',
email_address='johnsmith@example.com',
send_email_receipts=False, # not available in sandbox
phone_number='0343232323',
street='1 Test Street',
street2='2 Test Street',
city_name='Sydney',
state='NSW',
postal_code='2000')
Create a PayWayCard class with your customer's card details
card = PayWayCard(card_number='',
cvn='',
card_holder_name='',
expiry_date_month='',
expiry_date_year='')
Create a token from your card and create a customer in PayWay
token_response, errors = client.create_card_token(card)
token = token_response.token
customer.token = token
payway_customer, customer_errors = client.create_customer(customer)
Note the 'payway_customer' object contains the full customer response fields from PayWay.
Create a Payment class with the payment details and process the transaction
customer_number = payway_customer.customer_number
payment = PayWayPayment(customer_number=customer_number,
transaction_type='payment',
amount='',
currency='aud',
order_number='',
ip_address='')
transaction, errors = client.process_payment(payment)
Check the transaction for the result
if not errors and transaction.status == 'approved':
# process successful response
Take payment using a credit card token only
client = Client(merchant_id='',
bank_account_id='',
publishable_api_key='',
secret_api_key='')
card = PayWayCard(card_number='',
cvn='',
card_holder_name='',
expiry_date_month='',
expiry_date_year='')
token_response, errors = client.create_card_token(card)
# your customer reference number or a stored PayWay customer number
customer_number = ''
payment = PayWayPayment(customer_number=customer_number,
transaction_type='payment',
amount='',
currency='aud',
order_number='',
ip_address='',
token=token_response.token,
merchant_id=client.merchant_id)
transaction, errors = client.process_payment(payment)
Retries
Retries are off by default. Opt in with max_retries (and optionally retry_delay, the base
wait in seconds between attempts):
client = Client(merchant_id='<your_payway_merchant_id>',
bank_account_id='<your_payway_bank_account_id>',
publishable_api_key='<your_payway_publishable_api_key>',
secret_api_key='<your_payway_secret_api_key>',
max_retries=2,
retry_delay=1.0)
This follows PayWay's retry guidance (https://www.payway.com.au/docs/rest.html#network-errors):
- Requests are resent on connection errors, timeouts and HTTP 429/503 responses, waiting
retry_delayseconds between attempts (linear backoff, or the response'sRetry-Afterheader when present). PayWay suggests a 20 second wait; keepretry_delaysmall for synchronous checkout flows. - POSTs are only retried when an
idempotency_keywas supplied — the sameIdempotency-Keyis resent so PayWay replays the original response instead of processing a duplicate payment. POSTs without a key (and PUTs) are never retried. GETs are always safe to retry. - Other errors (including HTTP 500/502/504) are never retried, per PayWay's advice.
transaction, errors = client.process_payment(payment, idempotency_key=str(uuid.uuid4()))
Handling errors
Documented errors (such as 422 Unprocessable entity) are parsed into an PaymentError class that you can use in an customer error message. For more info, visit https://www.payway.com.au/docs/rest.html#http-response-codes
if errors:
for error in errors:
print(error.field_name)
print(error.message)
print(error.field_name)
# or use a method
PaymentError().list_to_message(errors)
Direct Debit
Direct debit transactions are possible by creating a token from a bank account:
bank_account = BankAccount(account_name='Test', bsb='000-000', account_number=123456)
token_response, errors = client.create_bank_account_token(bank_account)
token = token_response.token
Store the token with a customer in PayWay using the same process as the card outlined above.
Note: direct debit transactions take days to process so they must be polled regularly for the latest transaction status from the customer's bank.
Lookup transaction
Poll a transaction using the get_transaction method.
transaction, errors = client.get_transaction(transaction.transaction_id)
Search transactions
PayWay has no plain GET /transactions resource, only three search paths. Each returns a
paginated list (20 per page, most recent first) with next/prev links.
response = client.search_transactions_by_customer(customer_number)
response = client.search_transactions_by_receipt(receipt_number)
response = client.search_transactions_by_order(order_number)
transactions = response["data"]
Pass page to fetch a later page, using the number from the next/prev links:
response = client.search_transactions_by_customer(customer_number, page=2)
list_customers() takes the same page argument.
Process and capture a pre-authorisation
To process a credit card pre-authorisation using a credit card stored against a customer use preAuth as the transaction_type along with the customer's PayWay number, amount and currency.
pre_auth_payment = PayWayPayment(customer_number='',
transaction_type='preAuth',
amount='',
currency='aud',
order_number='',
ip_address='')
transaction, errors = client.process_payment(pre_auth_payment)
To capture the pre-authorisation supply a pre-authorisation transaction ID, capture as the transaction_type along with an amount to capture.
capture_payment = PayWayPayment(transaction_type='capture',
parent_transaction_id='',
amount='',
order_number='',
ip_address='')
transaction, errors = client.process_payment(capture_payment)
Refunds
Refund a transaction by supplying a PayWay transaction ID and the refund amount.
refund, errors = client.refund_transaction(
transaction_id=transaction.transaction_id,
amount=transaction.principal_amount,
)
Voiding a transaction
Void a transaction by supplying a PayWay transaction ID.
void_transaction, errors = client.void_transaction(transaction.transaction_id)
Update Payment Setup
Update a customer's payment setup with a new credit card or bank account in PayWay. Supply the new token and an existing PayWay customer number.
payment_setup, errors = client.update_payment_setup(new_token, payway_customer.customer_number)
Additional notes
PayWay API documentation https://www.payway.com.au/docs/rest.html
It is recommended to use PayWay's Trusted Frame https://www.payway.com.au/docs/rest.html#trusted-frame when creating a single use token of a card or bank account so your PCI-compliance scope is reduced.
Fraud
Please follow PayWay's advice about reducing your risk of fraudulent transactions. https://www.payway.com.au/docs/card-testing.html#card-testing
Running the project
uv sync
uv provisions a suitable Python (3.11+) and installs the dev dependencies automatically.
Testing
uv run pytest tests/ -v
Release files for python-payway 0.0.9
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| python_payway-0.0.9.tar.gz | 21.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| python_payway-0.0.9-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 38.6 kB
Release files / python_payway-0.0.9.tar.gz
| Download URL | python_payway-0.0.9.tar.gz |
|---|---|
| Size | 21.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2d5224c04df0d4a2e2d1b6de599e8701bee36d0841fa523d203962740be3fe8c
|
|
BLAKE2b-256 checksum How to use checksums |
6194205aea937f09ea07944eb6bcc93a288faad9358a87f95cdc542ceda990ce
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
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 Aug 11, 2026.
Transparency logRelease files / python_payway-0.0.9-py3-none-any.whl
| Download URL | python_payway-0.0.9-py3-none-any.whl |
|---|---|
| Size | 17.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
21a49cf27df2aa48dbdeeffe61c2f35c84bb1f252223c02f6ff7f1d8e074fe69
|
|
BLAKE2b-256 checksum How to use checksums |
954cbdc6de75bc5635f42218f2e4434494356ee3444440e2e222d5f73b142f55
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
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 Aug 11, 2026.
Transparency log