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

# Advanced SDK usage

> Advanced FunnelFox SDK patterns: custom event handling, dynamic configuration, error management, and performance optimization.

The SDK supports several advanced use-cases for more customized integration.

## Callbacks instead of events

If you prefer not to use event emitters, you can supply callback functions directly in the `createCheckout` options for success, error, and status changes. This provides a quick way to handle outcomes without separately registering event listeners:

```javascript theme={null}
const checkout = await createCheckout({
  priceId: 'price_123',
  customer: {
    externalId: 'user_456',
    email: 'user@example.com',
  },
  container: '#checkout',

  // Callback style (alternative to .on() events)
  onSuccess: result => {
    console.log('Success!', result.orderId);
  },
  onError: error => {
    console.error('Error!', error.message);
  },
  onStatusChange: (newState, oldState) => {
    console.log(`${oldState} → ${newState}`);
  },
});
```

Using callbacks is equivalent to listening for the `'success'`, `'error'`, and `'status-change'` events on the `CheckoutInstance`.

Internally, the SDK will trigger these callbacks at the same time as the events. Choose the approach (callbacks vs. event listeners) that fits your application style; you can even mix them (for example, provide an `onSuccess` callback but also listen for `'status-change'` events).

## Manual session creation

For full control over the checkout flow, you can manually create a client session and then use it with Primer's Headless Checkout.

This is useful if you need to perform custom steps between tokenization and finalizing payment (for example, if you want to process the payment on your backend before confirming the UI).

### 1. Create client session

Create a client session to get a `clientToken` (and `orderId`):

```javascript theme={null}
import { createClientSession } from '@funnelfox/billing';
import { Primer } from '@primer-io/checkout-web';

const session = await createClientSession({
  priceId: 'price_123',
  externalId: 'user_456',
  email: 'user@example.com',
  orgId: 'your-org-id',
});
console.log('Client token:', session.clientToken);
console.log('Order ID:', session.orderId);
```

### 2. Use with Primer Headless Checkout

Use the obtained `clientToken` with Primer's Headless Checkout:

```javascript theme={null}
const headlessCheckout = await Primer.createHeadless(session.clientToken, {
  paymentHandling: 'MANUAL',
  apiVersion: '2.4',
  onTokenizeSuccess: async (paymentMethodTokenData, handler) => {
    // Your custom payment logic...
    // Call your payment API with paymentMethodTokenData.token
    handler.handleSuccess();
  },
});

await headlessCheckout.start();
```

In this flow, you manually control when to display the checkout and what happens with the payment data. After calling `createClientSession`, you initialize Primer's Headless Checkout with the `clientToken`.

The `onTokenizeSuccess` callback gives you the opportunity to handle the payment token (`paymentMethodTokenData.token`) as needed.

Once your server confirms the payment or subscription creation, you call `handler.handleSuccess()` to complete the flow (or call `handler.handleFailure()` if an error occurred).

This advanced approach is useful for integrating additional custom business logic into the payment flow.
