Skip to main content

airwallex-python

Unofficial Python SDK for the Airwallex API — payouts, FX, balances, global accounts, beneficiaries, deposits, and webhooks.

CI PyPI Python License: MIT Status: Beta

[!IMPORTANT] This is an unofficial, community-maintained library. It is not affiliated with, endorsed by, or supported by Airwallex Pty Ltd — "Airwallex" is their trademark, used here only to describe compatibility. The SDK is in beta: the public interface may change before v1.0, so pin your version. For vendor-supported tooling, use the official Node.js SDK.

Airwallex's only official server-side SDK is Node.js. This library brings the same developer experience to Python:

  • Sync and async clients (Airwallex / AsyncAirwallex) built on httpx
  • Automatic authentication — token fetched on first use and refreshed before expiry; no manual login calls
  • Idempotent by default — request_id is auto-generated for money-moving calls, so retries never double-pay
  • Automatic retries with full-jitter exponential backoff on 408/429/5xx/network failures (honours Retry-After; 409 business conflicts are never retried)
  • Typed responses — Pydantic v2 models that are immutable and forward-compatible (unknown fields preserved, never dropped)
  • Auto-pagination — iterate every page with one loop
  • Webhook signature verification with replay protection
  • Typed errors — RateLimitError, AuthenticationError, … each carrying the Airwallex error code, source, and request_id

Installation

Available on PyPI:

pip install airwallex

Requires Python 3.9+. Releases follow semantic versioning; see the changelog.

Quickstart

Create API credentials in the Airwallex web app under Developer → API keys, then:

from airwallex import Airwallex

client = Airwallex(
    client_id="your_client_id",   # or set AIRWALLEX_CLIENT_ID
    api_key="your_api_key",       # or set AIRWALLEX_API_KEY
    environment="demo",           # "production" (default) or "demo" sandbox
)

# Current wallet balances
for balance in client.balances.current():
    print(balance.currency, balance.available_amount)

Send a payout

Payouts use /api/v1/transfers, which requires API version 2024-01-31 or later. If your account default is older, pass api_version="2024-01-31" (or newer) to the client.

transfer = client.transfers.create(
    beneficiary_id="ben_abc123",
    source_currency="USD",
    transfer_currency="PHP",
    transfer_amount=5000,
    transfer_method="LOCAL",
    reference="Invoice 42",
    reason="professional_service_fees",
)
print(transfer.id, transfer.status)

request_id is generated for you (pass your own to control idempotency). Airwallex will never execute the same request_id twice — including across the SDK's automatic retries.

FX: quote and convert

rate = client.rates.current(buy_currency="USD", sell_currency="SGD", buy_amount=1000)
print(rate.client_rate)

conversion = client.conversions.create(
    buy_currency="USD",
    sell_currency="SGD",
    buy_amount=1000,
    term_agreement=True,
)

Accept a payment

intent = client.payment_intents.create(
    amount=25.00,
    currency="USD",
    merchant_order_id="order_42",
)
confirmed = client.payment_intents.confirm(intent.id, payment_method={"type": "card", "card": {...}})
refund = client.refunds.create(payment_intent_id=intent.id, amount=5.00)

Issue a card

cardholder = client.issuing_cardholders.create(
    email="employee@example.com",
    individual={"name": {"first_name": "Ada", "last_name": "Lovelace"}},
    type="INDIVIDUAL",
)
card = client.issuing_cards.create(
    cardholder_id=cardholder.cardholder_id,
    form_factor="VIRTUAL",
    created_by="Ada Lovelace",
    program={"purpose": "COMMERCIAL"},
)

Test flows in the sandbox

client.simulation.create_deposit(amount=1000, currency="USD")   # demo environment only
client.simulation.transition_transfer("tra_123", next_status="PAID")

Auto-pagination

# Iterates page by page under the hood
for beneficiary in client.beneficiaries.list(page_size=100).auto_paging_iter():
    print(beneficiary.beneficiary_id, beneficiary.nickname)

Async

import asyncio
from airwallex import AsyncAirwallex

async def main() -> None:
    async with AsyncAirwallex(environment="demo") as client:
        page = await client.transfers.list(status="PAID")
        async for transfer in page.auto_paging_iter():
            print(transfer.id)

asyncio.run(main())

Webhooks

Verify and parse incoming notifications (get the secret when you create the webhook endpoint):

from airwallex import webhooks, WebhookSignatureError

def handle(request):  # any web framework
    try:
        event = webhooks.construct_event(
            payload=request.body,                      # raw bytes — do not re-serialise
            timestamp=request.headers["x-timestamp"],
            signature=request.headers["x-signature"],
            secret=WEBHOOK_SECRET,
        )
    except WebhookSignatureError:
        return 400
    if event.name == "transfer.settled":
        ...
    return 200

Error handling

from airwallex import Airwallex, RateLimitError, APIStatusError

try:
    client.transfers.retrieve("tra_missing")
except RateLimitError:
    ...  # already retried automatically; back off further
except APIStatusError as err:
    print(err.status_code, err.code, err.message, err.request_id)

All API errors inherit from airwallex.APIError; network failures raise airwallex.APIConnectionError.

Calling endpoints the SDK doesn't wrap yet

Every list method accepts extra query params as keyword arguments, and the client exposes a raw escape hatch with auth, retries, and error mapping intact:

page = client.transfers.list(short_reference_id="REF123")          # extra filter
disputes = client.request("GET", "/api/v1/pa/payment_disputes", params={"status": "OPEN"})

Typed responses

Response models live in airwallex.types and preserve unknown fields for forward compatibility:

from airwallex.types import Transfer, Balance

def settle(transfer: Transfer) -> None: ...

Bring your own httpx client

import httpx
client = Airwallex(http_client=httpx.Client(proxy="http://proxy:3128"))

The SDK applies the base URL and default headers per request, so proxies and custom TLS work without extra configuration; the SDK will not close a client you own.

Connected accounts (platforms)

client = Airwallex(on_behalf_of="acct_connected_account_id")  # sets x-on-behalf-of

Pinning an API version

client = Airwallex(api_version="2024-01-31")  # sets x-api-version on every request

Two quirks observed against the live demo API, worth knowing:

  • Airwallex versions endpoint groups independently — e.g. conversions.list requires 2024-01-31 on some accounts while fx/rates/current rejects it. If you hit incorrect_version errors, use a second client pinned differently for that endpoint group.
  • Several list endpoints enforce a minimum page_size of 10 and return invalid_argument below it.
  • Payment-acceptance lifecycle actions (payment_intents.confirm/capture/cancel, customers.update) require a request_id — the SDK auto-generates one, like it does for creates.
  • webhook_endpoints.create requires a version field (e.g. version="2024-01-31").

Resources covered

Resource Methods
client.balances current, history
client.transfers create, retrieve, list, cancel, validate, confirm_funding
client.batch_transfers create, retrieve, list, add_items, delete_items, items, quote, submit, delete
client.wallet_transfers create, retrieve, list
client.payers create, retrieve, update, delete, list, validate
client.beneficiaries create, retrieve, update, delete, list, validate
client.conversions create, retrieve, list
client.rates current
client.fx_quotes create, retrieve
client.conversion_amendments create, quote, retrieve, list
client.payment_intents create, retrieve, list, confirm, confirm_continue, capture, cancel
client.customers create, retrieve, update, list, generate_client_secret
client.refunds create, retrieve, list
client.issuing_cardholders create, retrieve, update, delete, list
client.issuing_cards create, retrieve, update, activate, limits, list
client.issuing_transactions retrieve, list
client.issuing_authorizations retrieve, list
client.accounts retrieve
client.financial_transactions retrieve, list
client.settlements retrieve, list
client.simulation demo-only: deposit create/settle/reject/reverse, transfer/payment transitions
client.global_accounts create, retrieve, update, close, list, transactions
client.deposits list
client.reference supported_currencies, settlement_accounts, invalid_conversion_dates
client.webhook_endpoints create, retrieve, update, delete, list
airwallex.webhooks verify_signature, construct_event

Coverage now matches (and in webhooks/pagination/simulation, exceeds) the official Node.js SDK's main surfaces — contributions welcome for the remaining areas (disputes, payment consents, linked accounts, scale/platform APIs).

Status

This SDK is beta software:

  • The wrapped endpoints are grounded in Airwallex's published API spec and covered by tests, but they have not yet been exercised against every account configuration.
  • Semantic versioning applies: breaking changes only in minor versions while 0.x, and patch releases never change behavior.
  • Response models tolerate unknown fields, so new Airwallex API versions won't break parsing.
  • Test in the demo environment before pointing at production, and pin the version in your dependency file (e.g. airwallex==0.2.0).

Development

uv sync                 # install dependencies
uv run pytest           # run tests
uv run ruff check .     # lint
uv run mypy             # type-check

Disclaimer

This project is an independent, unofficial SDK maintained by the community. It is not affiliated with, endorsed by, sponsored by, or supported by Airwallex Pty Ltd. "Airwallex" and related marks are trademarks of Airwallex Pty Ltd; they are used here solely to indicate API compatibility. This software is provided "as is" under the MIT license — review the SECURITY policy and test against the demo environment before moving real money. If you need vendor support or SLAs, use the official Node.js SDK.

License

MIT

Metadata

Release files for airwallex 0.2.1

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

Source distribution (sdist)

Source distribution for airwallex 0.2.1
File Size Uploaded
airwallex-0.2.1.tar.gz 119.8 kB Details

Built distribution (wheel)

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

Total release size: 173.1 kB

Release files / airwallex-0.2.1.tar.gz

Download URL airwallex-0.2.1.tar.gz
Size 119.8 kB
Tags Source
SHA-256 checksum
How to use checksums
7a4e109d40d088bc94f163a0822e4959e222a79f1cc58566f154a95c8c520922
BLAKE2b-256 checksum
How to use checksums
1c39906e0c2cd773c8beba97fb5eea854e91acde3c1fb6d6769538fffdd34aec
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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 Jul 2, 2026.

Transparency log

Release files / airwallex-0.2.1-py3-none-any.whl

Download URL airwallex-0.2.1-py3-none-any.whl
Size 53.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0944f28b3d84069f7c28175a5a408a589ad7cfcd628e72ea60fbf83f9f89f633
BLAKE2b-256 checksum
How to use checksums
38e754e26b4674ed66485b5d38d13b331f4208dc283678ab0e8e43d3789cb19f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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 Jul 2, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.1 This release

2 release files

0.2.0

2 release files

0.1.0

2 release files

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