Skip to main content

Overview

Once a shopper has a cart, you can either redirect them to Henry’s hosted checkout or run the entire checkout flow server-side with our headless APIs. Both approaches reuse the cart you built with the Universal Cart guide and return an order ID you can track afterwards.

Hosted checkout (fastest path)

Hosted checkout handles authentication, address capture, taxes, payments, and confirmation in a single responsive UI.
1

Generate a checkout URL

Call POST /cart/checkout with the shopper’s x-user-id.
const checkoutRes = await fetch("https://api.sandbox.henrylabs.ai/v0/cart/checkout", {
  method: "POST",
  headers: {
    "x-api-key": process.env.HENRY_API_KEY,
    "x-user-id": "user_123"
  }
});

const { data } = await checkoutRes.json();
const checkoutUrl = data.checkout_url;
The response returns a checkout_url that you can embed in an iframe, open in a new tab, or load inside a native webview.
2

Listen for postMessage events

When you embed the checkout page, subscribe to window.postMessage to react to key lifecycle events such as orderCompleted or checkoutClosed. Refer to the hosted integration example in the E2E Hosted Checkout guide.

Headless checkout API

Use the headless endpoints when you want full control over the checkout experience but still rely on Henry for payments, risk, and order orchestration.
1

Create a quote session

Send POST /checkout/session/quote with shipping details. The response returns a session_token and order_metadata containing taxes and totals.
const quoteRes = await fetch("https://api.sandbox.henrylabs.ai/v0/checkout/session/quote", {
  method: "POST",
  headers: {
    "x-api-key": process.env.HENRY_API_KEY,
    "x-user-id": "user_123",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    shippingDetails: {
      fullName: "Jamie Merchant",
      email: "jamie@example.com",
      phoneNumber: "+19175551234",
      addressLine1: "350 5th Ave",
      addressLine2: "Floor 21",
      city: "New York",
      stateOrProvince: "NY",
      postalCode: "10118",
      countryCode: "US"
    }
  })
});

const {
  data: { session_token: sessionToken, order_metadata: orderMetadata }
} = await quoteRes.json();
console.log(orderMetadata.total_price, orderMetadata.tax);
2

Review the session state

Use the session token to inspect the products and any shipping metadata Henry derived.
const productsRes = await fetch("https://api.sandbox.henrylabs.ai/v0/checkout/session/products", {
  headers: { "x-session-token": sessionToken }
});
const productsData = await productsRes.json();

const shippingRes = await fetch("https://api.sandbox.henrylabs.ai/v0/checkout/session/shipping", {
  headers: { "x-session-token": sessionToken }
});
const shippingData = await shippingRes.json();
The products payload mirrors your cart, while the shipping response indicates whether Henry already has shipping info (hasShipping) and echoes the validated address.
3

Collect a payment method

Launch Henry’s hosted card collection modal so the shopper can add a card before you place the order.
const cardCollectRes = await fetch("https://api.sandbox.henrylabs.ai/v0/wallet/card-collect", {
  method: "POST",
  headers: {
    "x-api-key": process.env.HENRY_API_KEY,
    "x-user-id": "user_123"
  }
});

const {
  data: { modal_url: modalUrl }
} = await cardCollectRes.json();

// Redirect or open the URL in a modal so the buyer can add a card
window.location.href = modalUrl;
4

Confirm checkout

When the buyer approves the totals and payment method, call POST /checkout/session/confirm to place the order. Provide the session token and include shipping details if you need to override the quote.
const confirmRes = await fetch("https://api.sandbox.henrylabs.ai/v0/checkout/session/confirm", {
  method: "POST",
  headers: {
    "x-api-key": process.env.HENRY_API_KEY,
    "x-session-token": sessionToken,
    "x-user-id": "user_123",
    "Content-Type": "application/json"
  },
  // Optionally override shipping details
  // body: JSON.stringify({
  //   shippingDetails: {
  //     fullName: "Jamie Merchant",
  //     email: "jamie@example.com",
  //     phoneNumber: "+19175551234",
  //     addressLine1: "350 5th Ave",
  //     city: "New York",
  //     stateOrProvince: "NY",
  //     postalCode: "10118",
  //     countryCode: "US"
  //   }
  // })
});

const {
  data: { id: orderId, status, grandTotal }
} = await confirmRes.json();
The confirmation response contains the newly created orderId, monetary breakdown (subtotal, tax, shipping, grandTotal), and line-item snapshot so you can display a receipt instantly.
Both hosted and headless flows return an order identifier you can monitor via the Order Management guide.