> ## Documentation Index
> Fetch the complete documentation index at: https://docs.taprails.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Payment Modes

> Understand POOL (custodial) vs SESSION_KEY (non-custodial) payment modes.

The TapRails SDK supports two distinct payment execution models. The right choice depends on your product's custody model.

***

## POOL Mode (Custodial)

In POOL mode, payments are funded from a **pre-loaded wallet managed by your company** on the TapRails platform. The user doesn't need a wallet, and no transaction signing is required at payment time.

```
Customer taps → SDK reads invoice → SDK calls /pay-from-pool → TapRails backend
                                                                    ↓
                                                         Debit from company pool wallet
                                                                    ↓
                                                         Transfer USDC to merchant wallet
```

### When to use POOL mode

* Your app is a **closed-loop fintech** (e.g., corporate expense cards, prepaid wallets)
* You want the **simplest possible integration** — no wallet infrastructure required
* You manage user balances on your backend and top up the pool wallet separately

### Configuration

```ts theme={null}
ContactlessCryptoSDK.initialize({
  mode: PaymentMode.POOL,
  pool: {
    customerId: 'customer_456',  // Your internal customer identifier
  },
  // ...
});
```

### How the pool works

1. Fund your company's pool wallet on the TapRails dashboard
2. When a customer pays, the SDK calls the backend with `customerId`
3. TapRails debits the pool and sends USDC to the merchant in a single transaction
4. You reconcile balances via the TapRails dashboard or webhooks

<Note>
  The pool wallet address and private key are managed entirely by TapRails. No key management is required on the SDK side.
</Note>

***

## SESSION\_KEY Mode (Non-Custodial)

In SESSION\_KEY mode, payments are funded directly from **the user's own wallet** using a delegated session key. The user signs a one-time approval transaction that authorizes TapRails to spend up to a daily limit on their behalf — without requiring them to sign every individual payment.

```
First use:
User approves daily limit → SDK generates session keypair → Registers with backend
                                                              ↓
                                                     Session key stored in Keychain

At payment time:
Customer taps → SDK reads invoice → SDK signs payload with session key → Backend executes
                                                                              ↓
                                                                  Spend from user's wallet
```

### When to use SESSION\_KEY mode

* Your app is a **non-custodial wallet or DeFi product**
* Users control their own funds on-chain
* You want **gasless, instant payments** without prompting the user to sign each time
* You use wallet infrastructure like **WalletConnect, Privy, Magic, or your own MPC solution**

### Configuration

```ts theme={null}
ContactlessCryptoSDK.initialize({
  mode: PaymentMode.SESSION_KEY,
  sessionKey: {
    walletAddress: '0x1234...abcd',  // User's wallet
    defaultDailyLimit: '100.00',     // Max USDC per day
    autoRenew: true,                 // Re-setup when key expires
    onSignTransaction: async (tx) => {
      // Your wallet integration:
      return await walletProvider.signTransaction(tx);
    },
    onSetupComplete: () => console.log('Session key ready'),
    onSetupCancel: () => console.log('User cancelled setup'),
  },
});
```

### Session key lifecycle

| State           | What happens                                                                     |
| --------------- | -------------------------------------------------------------------------------- |
| **No key**      | `TapRailsThemeProvider` detects missing key and shows the setup UI automatically |
| **Valid key**   | All payments use the stored key — no user interaction required                   |
| **Expired key** | With `autoRenew: true`, setup UI shows again before the next payment             |
| **Revoked**     | Call `revokeCurrentSessionKey()` to clear from Keychain and backend              |

### Security properties

* Session keys are **ECDSA keypairs** generated on-device and stored in the device Keychain
* The private key **never leaves the device**
* The daily limit caps maximum exposure if a key is compromised
* Keys can be revoked instantly from the SDK or the TapRails dashboard

***

## Comparison

|                     | POOL                    | SESSION\_KEY                |
| ------------------- | ----------------------- | --------------------------- |
| **Custody model**   | Custodial               | Non-custodial               |
| **Wallet required** | No                      | Yes                         |
| **User setup flow** | None                    | One-time approval signature |
| **Per-payment UX**  | Instant                 | Instant (after setup)       |
| **Max exposure**    | Pool balance            | Per-key daily limit         |
| **Best for**        | Fintechs, expense tools | Wallets, DeFi apps          |

***

## Switching Modes

You can only initialize the SDK in one mode per app session. To switch modes, call `ContactlessCryptoSDK.initialize()` again with the new configuration (e.g., after a user logs in with a wallet). This resets the API client.
