# Getting Started

Learn how to integrate ODUS Checkout SDK into your application. This guide walks you through the complete setup process with code examples in React.

## Prerequisites

Before you begin, make sure you have:

1. A backend endpoint that creates payments via the ODUS API — see [Making Payments](https://docs.odus.com/docs/guides/payments/making-payments.md) for details.

## How It Works

ODUS Checkout uses a two-step initialization process:

1. **Mount** — Renders the checkout form UI (card inputs, pay button) into your page
2. **Associate** — Links the checkout to a payment created on your backend, enabling the pay button and loading available payment methods

The checkout is interactive immediately after mounting, but the pay button remains disabled until a payment is associated. You should both mount and associate as early as possible in your checkout flow to minimize wait times for customers.

## Step 1: Install and Mount the Checkout

First, install the Checkout SDK via NPM:

```
npm install @odus/checkout@latest
```

If your app already depends on the SDK, make sure it resolves to version `1.12.0` or later before 4 November 2026. Version `1.12.0` is the first SDK release that calls only API v2. SDK versions that call API v1 routes stop working when v1 stops being served.

Then we'll create a React component that mounts the checkout form. At this stage, we'll set up the basic structure — the checkout UI will render, but the pay button won't be functional yet.

src/components/CheckoutForm.tsx

```
import { useEffect, useRef } from 'react';

import { OdusCheckout } from '@odus/checkout';

import '@odus/checkout/styles'; // Required for proper styling



export function CheckoutForm() {

  const checkoutRef = useRef<OdusCheckout | null>(null);



  useEffect(() => {

    const checkout = new OdusCheckout({

      environment: 'test', // Use 'live' for production

      apiKey: 'pk_retired',

      returnUrl: 'https://your-website.com/checkout/return',

    });



    checkout.mount('#checkout-container');

    checkoutRef.current = checkout;



    return () => {

      checkoutRef.current?.unmount();

    };

  }, []);



  return <div id="checkout-container" />;

}
```

After this step, you'll see the card input form rendered on the page. The pay button appears but is disabled — that's expected. Let's fix that in the next step.

important

Don't forget to import the styles with `import '@odus/checkout/styles'`. Without this, the checkout form won't render correctly.

## Step 2: Associate a Payment

For the checkout to accept payments, you need to link it to a payment created on your backend. Your backend should call the ODUS API to create a payment and return two values: `paymentId` and `checkoutKey`.

info

Learn how to create payments on your backend in the [Making Payments](https://docs.odus.com/docs/guides/payments/making-payments.md) guide.

Here's the complete component with payment association and proper error handling:

src/components/CheckoutForm.tsx

```
import { useEffect, useRef, useState } from 'react';

import { OdusCheckout } from '@odus/checkout';

import '@odus/checkout/styles';



export function CheckoutForm() {

  const checkoutRef = useRef<OdusCheckout | null>(null);

  const [isLoading, setIsLoading] = useState(true);

  const [error, setError] = useState<string | null>(null);



  useEffect(() => {

    const checkout = new OdusCheckout({

      environment: 'test',

      apiKey: 'pk_retired',

      returnUrl: 'https://your-website.com/checkout/return',

      callbacks: {

        onPaymentSucceeded: () => {

          window.location.href = '/checkout/success';

        },

        onPaymentFailed: (errorMessage) => {

          setError(`Payment failed: ${errorMessage}`);

        },

      },

    });



    checkout.mount('#checkout-container');

    checkoutRef.current = checkout;



    // Fetch payment details from your backend and associate

    async function setupPayment() {

      try {

        const response = await fetch('/api/create-payment', {

          method: 'POST',

          headers: { 'Content-Type': 'application/json' },

        });



        if (!response.ok) {

          throw new Error('Failed to create payment');

        }



        const { paymentId, checkoutKey } = await response.json();

        await checkout.associatePayment(paymentId, checkoutKey);

      } catch (err) {

        setError('Failed to initialize payment. Please refresh the page.');

      } finally {

        setIsLoading(false);

      }

    }



    setupPayment();



    return () => {

      checkoutRef.current?.unmount();

    };

  }, []);



  return (

    <div>

      {isLoading && <div className="loading-spinner">Loading checkout...</div>}

      {error && <div className="error-message">{error}</div>}

      <div id="checkout-container" />

    </div>

  );

}
```

Once `associatePayment()` completes successfully:

* The pay button becomes active
* Alternative payment methods (PayPal, Apple Pay) appear if configured
* Customers can complete their purchase

tip

Call `associatePayment()` as early as possible in your checkout flow. This minimizes the time customers spend waiting for the checkout to become ready.

## Updating the Payment

In many checkout flows, the customer can change their selected plan or pricing option after the checkout form is already rendered. When this happens, you need to create a new payment on your backend and re-associate it with the existing checkout instance.

Call `associatePayment()` again on the **same instance** — do not unmount and recreate the checkout. The SDK preserves all user-entered form data (email, card details, address fields) and only refreshes the payment method buttons.

src/components/CheckoutForm.tsx

```
import { useEffect, useRef, useState, useCallback } from 'react';

import { OdusCheckout } from '@odus/checkout';

import '@odus/checkout/styles';



const PRICES = [

  { id: 'basic', label: 'Basic — $9/mo', amount: 900 },

  { id: 'pro', label: 'Pro — $29/mo', amount: 2900 },

];



export function CheckoutForm() {

  const checkoutRef = useRef<OdusCheckout | null>(null);

  const [selectedPrice, setSelectedPrice] = useState(PRICES[0]);



  useEffect(() => {

    const checkout = new OdusCheckout({

      environment: 'test',

      apiKey: 'pk_retired',

      returnUrl: 'https://your-website.com/checkout/return',

      callbacks: {

        onPaymentSucceeded: () => {

          window.location.href = '/checkout/success';

        },

      },

    });



    checkout.mount('#checkout-container');

    checkoutRef.current = checkout;



    return () => {

      checkoutRef.current?.unmount();

    };

  }, []);



  // Re-associate whenever the selected price changes

  useEffect(() => {

    const checkout = checkoutRef.current;

    if (!checkout) return;



    async function updatePayment() {

      const response = await fetch('/api/create-payment', {

        method: 'POST',

        headers: { 'Content-Type': 'application/json' },

        body: JSON.stringify({ amount: selectedPrice.amount }),

      });



      const { paymentId, checkoutKey } = await response.json();

      await checkout!.associatePayment(paymentId, checkoutKey);

    }



    updatePayment();

  }, [selectedPrice]);



  return (

    <div>

      <div>

        {PRICES.map((price) => (

          <button key={price.id} onClick={() => setSelectedPrice(price)}>

            {price.label}

          </button>

        ))}

      </div>

      <div id="checkout-container" />

    </div>

  );

}
```

warning

Do not destroy and recreate the checkout instance when the price changes. Unmounting and remounting creates a new form, which **wipes all fields** the customer has already filled in.

## Next Steps

Now that you have the basics set up, there are only a few steps left to get your checkout flow production-ready:

* [3DS and Redirect Handling](https://docs.odus.com/docs/guides/checkout/3ds-and-redirect-handling.md) — Handle redirect-based payment flows like 3DS authentication and PayPal
* [Configuring Checkout](https://docs.odus.com/docs/guides/checkout/drop-in/configuration.md) — Customize the appearance and behavior of the checkout form
* [Builder](https://docs.odus.com/docs/guides/checkout/drop-in/builder.md) — Visually experiment with styles, layout, and payment methods in an interactive playground
