> ## 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.

# Build a Subscription Integration

> This guide describes how to sell a fixed-price monthly subscription offering using Flex.

At this point you should have a flex account, access to the partner dashboard, and have gone through the onboarding process of adding your payout information with Stripe.

Below we walk through a full example of how to integrate Flex Checkout into your checkout flow.

<Steps titleSize="h3">
  <Step title="Create an API Key in the partner dashboard">
    <Note>
      If you're just getting started, be sure to create an API Key in test mode to safely distinguish between testing and production.
    </Note>

    In the partner dashboard, navigate to the Developers section. Here we will find an API Keys tab
    where you can create an API Key to interact with Flex.

    Select the `New API Key` button and give your API Key a name. With this key we can now interact with
    the Flex API.
  </Step>

  <Step title="Define a product to sell">
    Always keep sensitive information about your product inventory, such as price and availability,
    on your server to prevent customer manipulation from the client. Define product information when
    you create the Checkout Session using predefined price IDs or on the fly with price\_data.

    For this example we've created a product that is eligible via a letter of medical necessity. To learn more
    about creating products and their eligibility review the [Product docs](/developer-guides/products-and-prices/how-products-and-prices-work) or Product API.

    ```bash theme={null}
    curl --request POST \
      --url https://api.withflex.com/v1/products \
      --header 'authorization: Bearer fsk_test_YzNiYjdhNWItN2FkOS00ZTMyLWE5MmQtZTdhNzMzYzE2NTIy' \
      --header 'content-type: application/json' \
      --data '{"product": {"name": "Test Product","description": "Test Product Description","visit_type": "gym","hsa_fsa_eligibility": "letter_of_medical_necessity"}}'
    ```

    The response we get back is:

    ```json theme={null}
    {
      "product": {
        "product_id": "fprod_01HW5MXAPBE79RHMMJJGB4ACAB",
        "name": "Test Product",
        "description": "Test Product Description",
        "created_at": "2024-04-23T14:14:16.029253Z",
        "visit_type": "gym",
        "active": true,
        "upc_code": null,
        "gtin": null,
        "hsa_fsa_eligibility": "letter_of_medical_necessity"
      }
    }
    ```
  </Step>

  <Step title="Define the pricing model">
    Given the `product_id` that was returned to in the previous payload we'll define a pricing model where we'll charge
    \$49.99 every month

    ```bash theme={null}
    curl --request POST \
      --url https://api.withflex.com/v1/prices \
      --header 'authorization: Bearer fsk_test_YzNiYjdhNWItN2FkOS00ZTMyLWE5MmQtZTdhNzMzYzE2NTIy' \
      --header 'content-type: application/json' \
      --data '{"price": {"product": "fprod_01HW5MXAPBE79RHMMJJGB4ACAB","description": "Our awesome new price","unit_amount": 4999,"recurring": {"interval": "monthly"}}}'
    ```

    The response we get back is:

    ```json theme={null}
    {
      "price": {
        "price_id": "fprice_01HWDV9J9JWY5SDFJZNFXN5S6P",
        "description": "Our awesome new price",
        "unit_amount": 4999,
        "price": 4999,
        "recurring": {
          "interval": "monthly",
          "trial_period_days": null
        },
        "active": true,
        "product": "fprod_01HW5MXAPBE79RHMMJJGB4ACAB",
        "created_at": "2024-04-26T18:39:43.93664Z",
        "type": "recurring",
        "metadata": null
      }
    }
    ```
  </Step>

  <Step title="Supply success and cancel URLs">
    Specify URLs for success and cancel pages—make sure they're publicly accessible so Flex can redirect customers to them.
    You can also handle both the success and canceled states with the same URL.

    `success_url: https://withflex.com/thank-you?success=true`
    `cancel_url: https://withflex.com/thank-you?canceled=true`
  </Step>

  <Step title="Build your checkout">
    On your site you should have an order preview page. On the order preview page you will add a button that will
    trigger your server to generate a checkout session.
  </Step>

  <Step title="Generate a checkout session">
    On the server you will generate a checkout session.

    ```bash theme={null}
    curl --request POST \
      --url https://api.withflex.com/v1/checkout/sessions \
      --header 'authorization: Bearer fsk_test_YzNiYjdhNWItN2FkOS00ZTMyLWE5MmQtZTdhNzMzYzE2NTIy' \
      --header 'content-type: application/json' \
      --data '{"checkout_session": {"line_items": [{"price": "fprice_01HWDV9J9JWY5SDFJZNFXN5S6P","quantity": 1}],"success_url": "https://withflex.com/thank-you?success=true","mode": "subscription","cancel_url": "https://withflex.com/thank-you?canceled=true"}}'
    ```
  </Step>

  <Step title="Redirect users to checkout">
    The response we got back looks like:

    ```json theme={null}
    {
      "checkout_session": {
        "allow_promotion_codes": false,
        "amount_total": 4999,
        "amount_subtotal": 4999,
        "cancel_url": "https://withflex.com/thank-you?canceled=true",
        "capture_method": "automatic",
        "checkout_session_id": "fcs_01HWDVDMWQT1N8TJJYDWKW4ZHZ",
        "created_at": 1714156917,
        "customer": null,
        "customer_email": null,
        "defaults": {
          "email": null,
          "first_name": null,
          "last_name": null,
          "phone": null
        },
        "expires_at": 1714160517,
        "invoice": null,
        "hsa_fsa_eligible": true,
        "letter_of_medical_necessity_required": true,
        "metadata": null,
        "mode": "subscription",
        "multiple_subscriptions": false,
        "payment_intent_id": null,
        "redirect_url": "http://localhost:3000/pay/c/fcs_01HWDVDMWQT1N8TJJYDWKW4ZHZ",
        "setup_intent": null,
        "shipping_options": null,
        "shipping_address_collection": false,
        "shipping_details": null,
        "status": "open",
        "success_url": "https://withflex.com/thank-you?success=true",
        "subscription": null,
        "tax_rate": null,
        "test_mode": false,
        "total_details": {
          "amount_discount": 0,
          "amount_tax": null,
          "amount_shipping": null
        },
        "visit_type": "gym"
      }
    }
    ```
  </Step>

  <Step title="Provision and monitor subscriptions">
    After the subscription signup succeeds, the customer returns to the `success_url` specified, which initiates a `checkout.session.completed` event.
    When you receive a `checkout.session.completed` event, you can provision the subscription. Continue to provision for each billinging cycle as you receive
    `invoice.paid` events. If you receive an `invoice.payment_failed` event, notify your customer and perform the appropriate action your team
    has decided at this moment.

    To determine the next step for your system's logic, check the event type and parse the payload of each event, such as invoice.paid.
    Store the subscription\_id and customer\_id event objects in your database for verification.
  </Step>

  <Step title="Try it out">
    Navigate to the redirect\_url and use any of these tests cards to simulate a payment.

    Payment succeeds: `4242424242424242`
    Payment is decline: `4000000000009995`

    If you have setup your webhooks, you should see the `checkout.session.completed` upon a successful payment.
  </Step>

  <Step title="Congratulations!">
    You have a basic subscriptions integration working!
  </Step>
</Steps>

## Next steps

Depending on your setup/business you may want to rely on additional parameters that are available as part of the Checkout Session API.
Some of the common scenarios, can be found [here](/developer-guides/integration/checkout/guides).
