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

# Define Your Checkout Experience

> Learn how to customize checkout sessions for common use cases like shipping, taxes, discounts, and embedded checkout.

Below we highlight common use cases that come up with checkout sessions and how to handle them.
If there is a scenario that is not addressed, please reach out to [miguel@withflex.com](mailto:miguel@withflex.com)

## Shipping options

If you need to ship a good, then you can have Flex collect shipping details for you by setting
the `shipping_address_collection` parameter to `true` as part of the payload.

If you additionally want to charge a shipping rate then you can do so by either:

### Creating a fixed shipping rate

```bash theme={null}
curl --request POST \
  --url https://api.withflex.com/v1/shipping_rates \
  --header 'authorization: Bearer fsk_test_YzNiYjdhNWItN2FkOS00ZTMyLWE5MmQtZTdhNzMzYzE2NTIy' \
  --header 'content-type: application/json' \
  --data '{"shipping_rate": {"display_name": "Standard Shipping","amount": 500}}'
```

Then specifying the returned `shipping_rate_id` as part of the payload when creating a checkout session.

```json theme={null}
{
  "checkout_session": {
    "line_items": [
      {
        "price": "fprice_01HW5NTAB88NK7HPD0H688EPG9",
        "quantity": 1
      }
    ],
    "success_url": "https://withflex.com/thank-you?success=true",
    "mode": "payment",
    "cancel_url": "https://withflex.com/thank-you?canceled=true",
    "shipping_options": {
      "shipping_rate_id": "fshr_01HW6FC7ZYWNW4XFSE1KMD8JDW"
    }
  }
}
```

### Creating a dynamic shipping rate

If your shipping is variable based off of the cart items then you can pass along the shipping data to create the shipping rate as part of
the checkout session payload.

```json theme={null}
{
  "checkout_session": {
    "line_items": [
      {
        "price": "fprice_01HW5NTAB88NK7HPD0H688EPG9",
        "quantity": 1
      }
    ],
    "success_url": "https://withflex.com/thank-you?success=true",
    "mode": "payment",
    "cancel_url": "https://withflex.com/thank-you?canceled=true",
    "shipping_options": {
      "shipping_rate_data": {
        "display_name": "Standard Shipping",
        "amount": 500
      }
    }
  }
}
```

## Setting a tax amount

If you need to pass along a tax amount to charge a customer you can do so by setting a tax\_rate. It is important to note that Flex does not currently calculate
tax. This is an amount that you have previously calculated.

```json theme={null}
{
  "checkout_session": {
    "line_items": [
      {
        "price": "fprice_01HW5NTAB88NK7HPD0H688EPG9",
        "quantity": 1
      }
    ],
    "success_url": "https://withflex.com/thank-you?success=true",
    "mode": "payment",
    "cancel_url": "https://withflex.com/thank-you?canceled=true",
    "tax_rate": {
      "amount": 599
    }
  }
}
```

## Add a discount

If you'd like to add a discount when charging a customer you can do so by creating a coupon then setting the discounts parameter as part of the payload.

### Creating a coupon

```bash theme={null}
curl --request POST \
  --url https://api.withflex.com/v1/coupons \
  --header 'authorization: Bearer fsk_test_YzNiYjdhNWItN2FkOS00ZTMyLWE5MmQtZTdhNzMzYzE2NTIy' \
  --header 'content-type: application/json' \
  --data '{"coupon": {"name": "$10 off","amount_off": 1000}}'
```

Then using the returned coupon\_id as part of the checkout session payload

```json theme={null}
{
  "checkout_session": {
    "line_items": [
        {
          "price": "fprice_01HW5NTAB88NK7HPD0H688EPG9",
          "quantity": 1
        }
    ],
    "success_url": "https://withflex.com/thank-you?success=true",
    "mode": "payment",
    "cancel_url": "https://withflex.com/thank-you?canceled=true",
    "discounts": {
        {"coupon": "fcoup_01HW6H666X6NMZ6NJHJ3SH3W93"}
    }
  }
}
```

## iFrame embedding

The checkout may be embedded on a page or within a modal by placing the checkout within an iframe:

```html theme={null}
  <iframe id="flex-checkout" src="CHECKOUT_SESSION_REDIRECT_URL" allow="payment *; publickey-credentials-get *" width="393" height="852" />
```

A [MessageEvent](https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent) will be emitted to the window just
before the user is redirected. You can listen to this event like this:

```js theme={null}
window.addEventListener('message', (event) => {
  // Ignore events that originate from something other than the iframe.
  if (event.source !== document.getElementById('flex-checkout').contentWindow) {
    return;
  }

  console.log("Message Received", event.data);
});
```

The [data](https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent/data) property mimics the
`checkout.session.completed` [Webhook Event](/developer-guides/webhooks/events). However, unlike webhooks, the event from the client
is not guaranteed to fire. Therefore it is recommended to listen to the webhooks in order to ensure that the message is
received.

The message could be customized by creating a redirect to your own site and having that page
[post a message](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) to the parent:

```js theme={null}
window.parent.postMessage(message, { targetOrigin: "*" });
```

## React example

This is an example of how you could embed the checkout in a React application:

```tsx theme={null}
"use client";

import { useEffect, useRef } from "react";

export default function Frame({ src }: { src: string }) {
  const frame = useRef<HTMLIFrameElement>(null);

  useEffect(() => {
    const listener = ({ source, data }: MessageEvent) => {
      if (source !== frame.current?.contentWindow) {
        return;
      }

      console.log("[Frame] Message Received", data);
    };

    window.addEventListener("message", listener);

    return () => {
      window.removeEventListener("message", listener);
    };
  }, []);

  return <iframe src={src} allow="payment *; publickey-credentials-get *" width="393" height="852" ref={frame} />;
}
```
