Skip to main content

Checkout Integration Guide

This guide covers the complete checkout flow for physical products, including cart validation, shipping calculation, and payment processing. Follow this guide to avoid common pitfalls.

Critical Concepts

Frontend Displays, Backend Calculates

All Amounts Are in Cents

Every monetary value in the Khaime API is in cents (smallest currency unit).
A common configuration error is entering shipping as 450 thinking it means 4.50,whentheAPIinterpretsitas4.50, when the API interprets it as 4.50 (450 cents). If you meant $450, you’d enter 45000.

Shipping is Calculated Server-Side

Shipping fees are calculated by the backend based on:
  • Merchant’s shipping rules configuration
  • Delivery address (country, state, zip code)
  • Cart contents (weight, dimensions, quantity)
  • Shipping method selected
You cannot calculate shipping client-side. You must call the API with delivery details to get the actual shipping cost.

Shipping Rules System

Merchants can configure multiple shipping rules that apply to different destinations. The API evaluates all rules and returns both the matched rule and available options.

Shipping Rule Types

Charge Types

Rule Priority: The backend ranks rules in this order:
  1. specific_locations (most specific)
  2. specific_states
  3. nationwide
  4. General international fallback
If a customer in Lagos, Ikeja has all rules available, they get the specific_locations Ikeja rate.

API Response Structure

When validating a cart, the response includes shipping details in pricing_summary:

Example Response

The location Field

For specific_locations rules, the customer must select a merchant-defined location (city, area, or zone). This is separate from the city field: Send the selected location in delivery_details.address[0].location:
If location is omitted, the backend falls back to matching against city.

Displaying Shipping Options

When available_destinations has multiple options, let users choose their shipping method:

How Shipping Selection Works

Shipping rules are selected during cart validation, not payment intent. Correct Flow:
Key Points:
  • The location field tells the backend which specific_locations rule to match
  • The cart_unique_id has the shipping fee cached - don’t overwrite it
  • Payment intent uses the cached shipping from the cart_unique_id

Rule Configuration Examples

Shipping Fee Display: The shipping_fee at the top level of the response reflects the matched_rules fee. If the user selects a different option from available_destinations, update your UI to show that option’s fee instead.

Checkout Flow Overview


Step 1: Build Cart Items

Cart items must include specific fields. The requirements differ based on whether products have variations.

Cart Item Structure

Building Cart Items Correctly

Common validation errors:
  • 'main_variant' is not allowed to be empty - You included main_variant for a product without variations
  • 'product_variant_data' is required - Missing this field (use 'none' for non-variant products)
  • 'least_sub_variant_id' is not allowed - You included variant ID for a non-variant product

Step 2: Validate Cart with Shipping Address

Call cart validation WHEN THE USER SUBMITS THEIR SHIPPING ADDRESS, not when they click “Pay”. This ensures they see the full total (including shipping) before entering payment details.

Delivery Details Structure

Validate Cart API Call

Cart Validation Response

Extract Shipping and Update UI


Step 3: Create Payment Intent

After cart validation, create a payment intent when the user is ready to pay.

Payment Intent Request

Payment Intent Response

Amount Mismatch Warning: The amount_to_pay from the API may differ from your frontend subtotal because it includes:
  • Shipping fees
  • Platform fees
  • Taxes (if applicable)
  • Discounts applied
Always display amount_to_pay as the final total, not your calculated subtotal.

Step 4: Render Payment Element

Use Khaime.confirmPayment() to render the Stripe Payment Element.

Display Modes


React Integration: Critical Timing Issue

Wrong Approach (Will Fail)

Correct Approach (Use useEffect)

Pass the DOM element directly (paymentContainerRef.current) instead of an ID string to avoid race conditions.

Order Summary: Transparency Best Practices

Always show a clear breakdown of costs:

Format Currency Helper


Complete Checkout Flow Example


Troubleshooting

”Container element not found”

Cause: confirmPayment called before React rendered the container. Fix: Use useEffect to wait for the container to exist. See React Integration.

Amount mismatch between frontend and payment

Cause: Backend adds shipping, fees, or taxes that frontend doesn’t know about. Fix:
  1. Call validateCart with delivery details to get shipping
  2. Display amount_to_pay from payment intent as the final total
  3. Show shipping as a line item for transparency

”main_variant is not allowed to be empty”

Cause: Sending main_variant: '' for a product without variations. Fix: Only include main_variant and least_sub_variant_id for products where has_variation: true.

Unexpectedly high shipping

Cause: Shipping rules configured in dollars instead of cents, or per-item rates. Fix: Check merchant shipping rules configuration. All amounts must be in cents.

Multicurrency Support

Khaime supports 35+ currencies with automatic detection and real-time conversion.

How It Works

  1. Auto-detect currency from customer’s IP (or let them manually select)
  2. Convert prices using live exchange rates via /pricing/calculate
  3. Process payment in customer’s currency
  4. Merchant receives payout in their baseline currency

What Gets Converted Where

The skipConversion Pattern

Implement a formatPrice function that can skip conversion:

Displaying Prices Correctly

Calculating Total When API Doesn’t Provide It

When the API doesn’t return a total but you have shipping, you must manually combine:

Detect Customer Currency

Convert Price to Customer’s Currency

Currency Selector Component Pattern

Supported Currencies

For unambiguous currencies (NGN, GHS, KES), the currency code alone identifies the country. For ambiguous currencies (USD, EUR), use customer_country parameter if you need country-specific pricing rules.

Merchant Configuration Checklist

Before going live, verify:
  • Shipping rates are in cents (450 = 4.50,not4.50, not 450)
  • Shipping zones are configured correctly
  • Tax settings are correct for your regions
  • Platform fees are understood and accounted for
  • Test with various cart sizes and addresses
  • Multicurrency: Test with different currencies
  • Currency selector is visible and functional
  • Prices display correctly after currency conversion