Skip to main content

Unofficial Python SDK for the Airwallex API — payouts, FX, global accounts, and more.

Project description

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 defaultrequest_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 errorsRateLimitError, 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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

airwallex-0.2.1.tar.gz (119.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

airwallex-0.2.1-py3-none-any.whl (53.3 kB view details)

Uploaded Python 3

File details

Details for the file airwallex-0.2.1.tar.gz.

File metadata

  • Download URL: airwallex-0.2.1.tar.gz
  • Upload date:
  • Size: 119.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for airwallex-0.2.1.tar.gz
Algorithm Hash digest
SHA256 7a4e109d40d088bc94f163a0822e4959e222a79f1cc58566f154a95c8c520922
MD5 2b0d752530d04e5c4b0f762484cbe9fd
BLAKE2b-256 1c39906e0c2cd773c8beba97fb5eea854e91acde3c1fb6d6769538fffdd34aec

See more details on using hashes here.

Provenance

The following attestation bundles were made for airwallex-0.2.1.tar.gz:

Publisher: release.yml on Cyvid7-Darus10/airwallex-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file airwallex-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: airwallex-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 53.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for airwallex-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 0944f28b3d84069f7c28175a5a408a589ad7cfcd628e72ea60fbf83f9f89f633
MD5 9a1c4b1cc209f7de30c638fa51b7f619
BLAKE2b-256 38e754e26b4674ed66485b5d38d13b331f4208dc283678ab0e8e43d3789cb19f

See more details on using hashes here.

Provenance

The following attestation bundles were made for airwallex-0.2.1-py3-none-any.whl:

Publisher: release.yml on Cyvid7-Darus10/airwallex-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page