## The payment lifecycle

Whatever UI you build, the runtime moves a payment through the same stages. Your job is to render each stage and call the matching action.

### Load the payment

The buyer arrives with a payment ID (from a QR code, link, or your checkout). The runtime fetches the payment intent — amount, merchant, accepted tokens.

### Connect a wallet

The buyer connects a wallet through the `WalletProvider` seam. The runtime reads their accounts across the supported networks.

### Fetch payment options

Given the connected accounts, the Engine returns the concrete ways to pay — token, network, amount, fees, and whether compliance data is required.

### Select & build

The buyer picks an option. The runtime builds the transaction(s) and the exact wallet-RPC actions to sign.

### Sign

The `Signer` drives the wallet through the required signatures (e.g. a permit + the payment).

### Confirm & settle

Signed results are submitted to confirm the payment. The runtime then polls status until the payment succeeds, fails, or expires.

## How it fits together

The Headless SDK follows a **headless runtime + host** model. The payment flow lives entirely in the SDK; your application is the **host** that consumes it. The runtime reaches the outside world only through five injectable **seams** — so you can swap in your own transport, wallet, timing, and analytics, and reuse the exact same payment machine.

The five seams the runtime depends on:

| Seam | What it abstracts | Provided by |
| --- | --- | --- |
| `Transport` | Engine HTTP calls | `pay-core` `createHttpTransport` → your server route |
| `WalletProvider` | connect / accounts / provider / switch | `pay-appkit`, or your own wallet integration |
| `Signer` | sign a payment option’s wallet-RPC actions | `pay-appkit` `createAppKitSigner` — one call (wraps `pay-state`’s signing; drop to its raw strategies only for a custom, non-AppKit wallet) |
| `Clock` | intervals + page visibility (for polling) | browser timers (the SDK ships a default) |
| `Telemetry` | analytics breadcrumbs | your analytics pipeline (optional) |

`@walletconnect/pay-state` ships browser-ready `Clock` and `Telemetry` defaults (`browserClock`, `noopTelemetry`). In practice, a React/Next.js gateway wires just the `Transport` (pointed at your server route); the `WalletProvider` and `Signer` come ready-made from `pay-appkit` (`<PayAppKitProvider>` + `createAppKitSigner`), and it reuses `browserClock` for the rest. `Telemetry` is optional.

## The Engine API key never reaches the browser

WalletConnect Pay’s Engine API is authenticated with a secret API key that **must stay server-side**. The SDK enforces this split: the browser talks to _your_ server, and your server talks to the Engine.

`pay-core` exposes two entry points for exactly this: `createHttpTransport` for the browser (talks to _your_ server) and `createEngineClient` (imported from `@walletconnect/pay-core/server`) which holds the API key and talks to the Engine. In a Next.js app, your Route Handler sits in the middle.

## Next steps

[**Implementation**  
Build a complete checkout in React / Next.js, step by step.](https://docs.walletconnect.com/payments/psps/headless-sdk/implementation)

[**Packages Reference**  
The public API of pay-core, pay-state, pay-react, and pay-appkit.](https://docs.walletconnect.com/payments/psps/headless-sdk/packages-reference)
