DEV Community

Cover image for Medusa Checkout Flow: Step-by-Step Guide to Building a Complete E-Commerce Checkout
Michał Miler for u11d

Posted on • Originally published at u11d.com

Medusa Checkout Flow: Step-by-Step Guide to Building a Complete E-Commerce Checkout

Building an e-commerce storefront requires implementing a robust checkout flow that handles cart management, shipping, and payment processing. Medusa.js provides a comprehensive set of Store APIs that make this process straightforward. In this article, we'll explore the complete Medusa checkout flow by walking through each API endpoint required to take a customer from an empty cart to a completed order.

Understanding the Medusa Checkout Process

The Medusa checkout flow consists of seven essential steps:

  1. Cart Creation - Initialize a new shopping cart
  2. Add Items - Add products to the cart
  3. Set Shipping Address - Configure delivery information
  4. Select Shipping Method - Choose delivery options
  5. Payment Collection - Initialize payment processing
  6. Payment Session - Set up payment provider
  7. Complete Order - Finalize the purchase

Each step builds upon the previous one, creating a seamless user experience while maintaining data integrity throughout the process.

Prerequisites and Setup

Before diving into the implementation, ensure you have:

  • A running Medusa v2 application
  • Valid publishable API key
  • Product variants, regions, and shipping options configured
  • Payment provider set up (we'll use the system default)
  • curl and jq installed for making API requests and parsing JSON responses

curl and jq Installation

# macOS (using Homebrew)

brew install curl jq

# Ubuntu/Debian

sudo apt update
sudo apt install curl jq

# Windows (using Chocolatey)

choco install curl jq
Enter fullscreen mode Exit fullscreen mode

Environment Variables

Set the following variables before running the checkout flow:

export BASE_URL="<http://localhost:9000>"
export PUBLISHABLE_KEY="pk_<your_publishable_key_here>"
export REGION_ID="reg_<your_region_id>"
export PRODUCT_VARIANT_ID="variant_<your_variant_id>"
export SHIPPING_OPTION_ID="so_<your_shipping_option_id>"
export PAYMENT_PROVIDER_ID="pp_system_default"
Enter fullscreen mode Exit fullscreen mode

Note: The CART_ID and PAYMENT_COLLECTION_ID variables should be set during the checkout process after cart creation and payment collection initialization.

Step-by-Step Implementation

1. Create a New Cart

The checkout journey begins with creating a new cart associated with a specific region:

curl -X POST "$BASE_URL/store/carts" \
  -H "Content-Type: application/json" \
  -H "x-publishable-api-key: $PUBLISHABLE_KEY" \
  -d '{ "region_id": "'$REGION_ID'" }'
Enter fullscreen mode Exit fullscreen mode

Key Points:

  • Each cart gets a unique identifier used in subsequent API calls
  • Regions define currency, tax rates, and fulfillment settings

2. Add Products to Cart

Once the cart exists, add product variants with specified quantities:

curl -X POST "$BASE_URL/store/carts/$CART_ID/line-items" \
  -H "Content-Type: application/json" \
  -H "x-publishable-api-key: $PUBLISHABLE_KEY" \
  -d '{ "variant_id": "'$PRODUCT_VARIANT_ID'", "quantity": 1 }'
Enter fullscreen mode Exit fullscreen mode

Key Points:

  • Use variant_id rather than product_id for specific product configurations
  • Quantities can be updated by calling this endpoint again
  • Inventory levels are automatically checked during this step

3. Set Shipping Address and Customer Information

Configure the delivery address and customer contact details:

curl -X POST "$BASE_URL/store/carts/$CART_ID" \
  -H "Content-Type: application/json" \
  -H "x-publishable-api-key: $PUBLISHABLE_KEY" \
  -d '{
    "shipping_address": {
      "first_name": "John",
      "last_name": "Doe",
      "address_1": "Nordmarksvej 9",
      "city": "Billund",
      "country_code": "dk",
      "postal_code": "7190",
      "phone": "1234567890"
    },
    "email": "john.doe@example.com"
  }'
Enter fullscreen mode Exit fullscreen mode

Key Points:

  • country_code must match the region's available countries
  • Email is required for order confirmation and customer account association
  • Billing address can be set separately if different from shipping address

4. Select Shipping Method

Choose from available shipping options for the cart's region and address:

curl -X POST "$BASE_URL/store/carts/$CART_ID/shipping-methods" \
  -H "Content-Type: application/json" \
  -H "x-publishable-api-key: $PUBLISHABLE_KEY" \
  -d '{ "option_id": "'$SHIPPING_OPTION_ID'" }'
Enter fullscreen mode Exit fullscreen mode

5. Create Payment Collection

Initialize the payment processing system for the cart:

curl -X POST "$BASE_URL/store/payment-collections" \
  -H "Content-Type: application/json" \
  -H "x-publishable-api-key: $PUBLISHABLE_KEY" \
  -d '{ "cart_id": "'$CART_ID'" }'
Enter fullscreen mode Exit fullscreen mode

6. Initialize Payment Session

Set up the payment provider session for processing:

curl -X POST "$BASE_URL/store/payment-collections/$PAYMENT_COLLECTION_ID/payment-sessions" \
  -H "Content-Type: application/json" \
  -H "x-publishable-api-key: $PUBLISHABLE_KEY" \
  -d '{ "provider_id": "'$PAYMENT_PROVIDER_ID'" }'
Enter fullscreen mode Exit fullscreen mode

Key Points:

  • Payment providers (Stripe, PayPal, etc.) require specific session initialization
  • Provider ID must match configured payment providers in your Medusa setup
  • Session contains payment intent or equivalent for the provider

7. Complete the Order

Finalize the checkout process and create the order:

curl -X POST "$BASE_URL/store/carts/$CART_ID/complete" \
  -H "Content-Type: application/json" \
  -H "x-publishable-api-key: $PUBLISHABLE_KEY"
Enter fullscreen mode Exit fullscreen mode

Key Points:

  • This step validates all cart information and processes payment
  • Inventory is reserved and order confirmation is triggered
  • The cart is converted to an immutable order record

Complete Implementation Example

Here's a complete shell script implementing the entire checkout flow:

#!/bin/bash

# Configuration
BASE_URL="<http://localhost:9000>"
PUBLISHABLE_KEY="pk_"
REGION_ID="reg_"
PRODUCT_VARIANT_ID="variant_"
SHIPPING_OPTION_ID="so_"
PAYMENT_PROVIDER_ID="pp_system_default"

# 1. Create cart
echo "Creating cart..."
CART_RESPONSE=$(curl -s -X POST "$BASE_URL/store/carts" \
  -H "Content-Type: application/json" \
  -H "x-publishable-api-key: $PUBLISHABLE_KEY" \
  -d '{ "region_id": "'$REGION_ID'" }')

CART_ID=$(echo $CART_RESPONSE | jq -r '.cart.id')
echo "Cart created with ID: $CART_ID"

# 2. Add item to cart
echo "Adding item to cart..."
curl -s -X POST "$BASE_URL/store/carts/$CART_ID/line-items" \
  -H "Content-Type: application/json" \
  -H "x-publishable-api-key: $PUBLISHABLE_KEY" \
  -d '{ "variant_id": "'$PRODUCT_VARIANT_ID'", "quantity": 1 }' > /dev/null

# 3. Set shipping address and email
echo "Setting shipping address..."
curl -s -X POST "$BASE_URL/store/carts/$CART_ID" \
  -H "Content-Type: application/json" \
  -H "x-publishable-api-key: $PUBLISHABLE_KEY" \
  -d '{
    "shipping_address": {
      "first_name": "John",
      "last_name": "Doe",
      "address_1": "Nordmarksvej 9",
      "city": "Billund",
      "country_code": "dk",
      "postal_code": "7190",
      "phone": "1234567890"
    },
    "email": "john.doe@example.com"
  }' > /dev/null

# 4. Set shipping method
echo "Setting shipping method..."
curl -s -X POST "$BASE_URL/store/carts/$CART_ID/shipping-methods" \
  -H "Content-Type: application/json" \
  -H "x-publishable-api-key: $PUBLISHABLE_KEY" \
  -d '{ "option_id": "'$SHIPPING_OPTION_ID'" }' > /dev/null

# 5. Create payment collection
echo "Creating payment collection..."
PAYMENT_COLLECTION_RESPONSE=$(curl -s -X POST "$BASE_URL/store/payment-collections" \
  -H "Content-Type: application/json" \
  -H "x-publishable-api-key: $PUBLISHABLE_KEY" \
  -d '{ "cart_id": "'$CART_ID'" }')

PAYMENT_COLLECTION_ID=$(echo $PAYMENT_COLLECTION_RESPONSE | jq -r '.payment_collection.id')
echo "Payment collection created with ID: $PAYMENT_COLLECTION_ID"

# 6. Initialize payment session
echo "Initializing payment session..."
curl -s -X POST "$BASE_URL/store/payment-collections/$PAYMENT_COLLECTION_ID/payment-sessions" \
  -H "Content-Type: application/json" \
  -H "x-publishable-api-key: $PUBLISHABLE_KEY" \
  -d '{ "provider_id": "'$PAYMENT_PROVIDER_ID'" }' > /dev/null

# 7. Complete the cart
echo "Completing order..."
ORDER_RESPONSE=$(curl -s -X POST "$BASE_URL/store/carts/$CART_ID/complete" \
  -H "Content-Type: application/json" \
  -H "x-publishable-api-key: $PUBLISHABLE_KEY")

ORDER_ID=$(echo $ORDER_RESPONSE | jq -r '.order.id')
echo "Order completed successfully: $ORDER_ID"
Enter fullscreen mode Exit fullscreen mode

Troubleshooting

  1. Check Service Health: Test if the service is responding by visiting http://localhost:9000/store/products in your browser. You should see a JSON response with available products.
  2. Validate API Key: Confirm your publishable API key is correct and has proper permissions for store operations.
  3. No Products Available: Verify products exist in your store by checking the /store/products endpoint. Ensure products are published and have available variants.
  4. Invalid Shipping Address:
    • Validate address format matches the expected country standards
    • Ensure the country_code is listed under the region's allowed countries
    • Check /store/regions/{region_id} to see available countries for your region
  5. Shipping Option Not Available: Verify the shipping option is enabled for the selected region and address. Check /store/shipping-options for available options in your region.
  6. Insufficient Inventory: Check stock levels before adding items. The API will return inventory errors if requested quantities exceed available stock.
  7. Payment Provider Issues:
    • Ensure the payment provider is properly configured in your Medusa setup
    • Handle payment failures gracefully with appropriate error messaging
    • Verify payment provider credentials are valid

Conclusion

The Medusa checkout flow provides a robust foundation for e-commerce applications with its well-structured API endpoints. By following this seven-step process, you can build reliable checkout experiences that handle modern e-commerce requirements.

Key takeaways:

  • Each step depends on the previous one's completion
  • Implement proper validation and retry logic
  • Track cart state throughout the process
  • Provide user feedback at each step

This approach supports various checkout scenarios including guest flows, multiple payment methods, and subscription purchases.

Top comments (0)