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

# Programmatic Checkout

> Create a checkout session server-side, render the payment UI on the client.

# Programmatic Checkout

When the price or product context needs to come from your backend — a custom quote, a WordPress shortcode, a dynamic subscription plan — create the checkout session on your server and hand the resulting session token to the SDK on the client.

This is the flow used internally by the Khaime WordPress `[khaime_checkout]` shortcode.

## 1. Create the session on your server

Call the initialize endpoint with your secret API key.

```http theme={null}
POST https://api.khaime.com/api/v1/sdk/checkout/initialize
X-Merchant-ID: YOUR_MERCHANT_ID
X-API-Key: sk_live_...
Content-Type: application/json

{
  "product_id": 789,
  "quantity": 1,
  "currency": "USD",
  "customer": {
    "email": "jane@example.com",
    "first_name": "Jane",
    "last_name": "Doe"
  }
}
```

The response is a `CheckoutSession`:

```json theme={null}
{
  "sessionToken": "khs_8f3a…",
  "amount": 5000,
  "currency": "USD",
  "productId": 789,
  "productTitle": "Premium Plan",
  "paymentGateway": "stripe",
  "expiresAt": "2026-04-18T00:00:00.000Z",
  "merchantBranding": { "name": "Acme", "logo": "...", "brandColor": "#42c3ff" }
}
```

<Warning>
  The session token is single-use and short-lived. Generate it per customer, per transaction.
</Warning>

### Example: PHP / WordPress

```php theme={null}
$response = wp_remote_post('https://api.khaime.com/api/v1/sdk/checkout/initialize', [
  'headers' => [
    'X-Merchant-ID' => '1234',
    'X-API-Key'     => 'sk_live_...',
    'Content-Type'  => 'application/json',
  ],
  'body' => json_encode([
    'product_id' => 789,
    'quantity'   => 1,
    'currency'   => 'USD',
    'customer'   => [
      'email'      => $user->user_email,
      'first_name' => $user->first_name,
      'last_name'  => $user->last_name,
    ],
  ]),
]);

$session = json_decode(wp_remote_retrieve_body($response), true);
$token   = $session['sessionToken'];
```

### Example: Node.js

```javascript theme={null}
const res = await fetch('https://api.khaime.com/api/v1/sdk/checkout/initialize', {
  method: 'POST',
  headers: {
    'X-Merchant-ID': process.env.KHAIME_MERCHANT_ID,
    'X-API-Key': process.env.KHAIME_API_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    product_id: 789,
    quantity: 1,
    currency: 'USD',
    customer: { email, first_name, last_name },
  }),
});

const { sessionToken } = await res.json();
```

## 2. Render the payment UI on the client

Pass the session token to `sdk.createPayment()`:

```html theme={null}
<div id="khaime-checkout"></div>

<script src="https://api.khaime.com/sdk/v2/khaime.js"></script>
<script>
  const sdk = KhaimeSDK.init({ merchantId: '1234' });

  sdk.createPayment({
    sessionToken: 'khs_8f3a…', // passed in from your server
    container: '#khaime-checkout',
    onReady: () => console.log('Payment UI mounted'),
    onSuccess: ({ sessionToken, orderId, amount, currency, paymentMethod }) => {
      window.location.href = '/thank-you?order=' + orderId;
    },
    onError: (err) => {
      console.error('Payment failed:', err.message);
    },
  });
</script>
```

`createPayment` does three things:

1. Fetches the session via `GET /api/v1/sdk/checkout/session/{sessionToken}` to retrieve gateway credentials.
2. Lazy-loads the checkout modal component.
3. Renders Stripe Elements or Paystack inline based on the session's `paymentGateway`.

No API key is needed on the client — the session token is the authorization.

## 3. Confirm and fulfil

When the customer submits, the SDK calls `POST /api/v1/sdk/checkout/session/{sessionToken}/confirm`. On success, `onSuccess` fires with the order ID.

<Warning>
  Always verify the order server-side via a [webhook](/webhooks/overview) before fulfilling. The client callback only confirms the payment UI completed — webhooks confirm the charge.
</Warning>

## When to use this flow

| Use programmatic when…                                                                         | Use [Pay Button](/sdks/embedded/quickstart) when… |
| ---------------------------------------------------------------------------------------------- | ------------------------------------------------- |
| Price is computed server-side (quotes, upsells, coupons applied by your logic)                 | Price comes from the product record in Khaime     |
| You're building inside WordPress, Drupal, or a CMS that renders HTML server-side               | You can drop a component on a static page         |
| You want to pre-fill customer info from a logged-in session                                    | The customer enters their own info                |
| You need to create the session atomically with another backend action (e.g. reserve inventory) | No atomicity required                             |

## Shortcut: server-side one-shot + redirect

If you don't need an embedded UI, you can skip `createPayment()` entirely and redirect the customer to the Khaime-hosted checkout URL returned by the initialize endpoint. See the [Create Session API reference](/api-reference/payments/create-session).

## Next steps

* [Events reference](/sdks/embedded/events) — full event payloads.
* [Webhooks](/webhooks/overview) — server-side verification.
* [Create Session API](/api-reference/payments/create-session) — full request/response spec.
