The challenge
A B2B SaaS expanding from North America into APAC and EMEA needed a payment infrastructure that could collect in five currencies, run subscription billing, handle retries gracefully, and survive a security review. They had outgrown a single-processor setup — FX margins were eating 1.8% of revenue, settlement was multi-day, and their existing webhook handler dropped events under load. The CFO wanted Airwallex for the FX and global rails; the CTO wanted to keep their existing FastAPI stack and not turn payments into a separate service the team couldn't operate.
The ask: ship a production Airwallex integration on FastAPI + PostgreSQL inside a single quarter, with bullet-proof webhook reliability, real subscription state machine, PCI-DSS-aligned architecture, and a clean operations story so the on-call engineer at 2am isn't paging the CTO.
Our solution
We built a focused Airwallex integration around three engineering ideas: a typed payment domain model, an outbox-pattern webhook pipeline, and a state machine for the subscription lifecycle that the rest of the app can read but only payments code can write.
On the API side, all card data is collected with Airwallex's hosted payment elements so the application backend never touches a PAN — the PCI scope stays at SAQ A. The FastAPI service exposes a small, typed payments API (Pydantic v2 models, OpenAPI documented) that the product team consumes; Airwallex API calls are wrapped in a single client with idempotency keys, exponential retries, and circuit breaking.
On the webhook side, every Airwallex event lands in a signed-and-verified endpoint that does one thing: persist the raw event into an `inbox` table inside a single transaction. A separate worker processes the inbox in order, with at-least-once delivery and idempotent handlers. This pattern alone fixed the dropped-event problem completely — even during a 4x traffic spike at launch.
The subscription state machine handles trial, active, past-due, dunning, paused, canceled, and reactivated, with explicit allowed transitions and an audit log on every state change. Failed payments now run a smart retry schedule (not the default exponential backoff) tuned to the customer's billing-day patterns, which is what produced the 65% drop in failed-payment churn.
- Hosted Airwallex payment elements — application backend never touches a PAN (PCI SAQ A)
- Typed FastAPI payments API with Pydantic v2 domain model and OpenAPI contract
- Idempotent Airwallex client with idempotency keys, exponential retry, and circuit breaker
- Inbox-pattern webhook pipeline — signed verification, persisted raw event, ordered worker drain
- Subscription state machine: trial, active, past-due, dunning, paused, canceled, reactivated
- Smart dunning schedule tuned to customer billing-day patterns (not naive backoff)
- Multi-currency support: USD, CAD, GBP, EUR, AUD live at launch — others added in days
- Datadog dashboards for webhook lag, retry rate, dunning funnel, and FX exposure
- Real on-call playbook covering Airwallex outage, webhook backlog, and bad signature events