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

# Quickstart

> Search products, build a cart, launch checkout, and track an order.

<Note>Want to skip the reading and run it live? Check out our [demo app](https://demo.henrylabs.ai).</Note>

<Tip>
  This guide shows the full E2E flow - search → cart → checkout → order tracking. You don't have to use all of it. Jump to whichever feature you need: you can call `cart.checkout.purchase` directly
  with a product link, or use `products.details` standalone without ever touching the cart.
</Tip>

## Prerequisites

* Node.js 18+ (or Bun/Deno)
* An API key from the [Henry Dashboard](https://app.henrylabs.ai)
* A server-side environment (API key must stay private)

## Setup

<Steps>
  <Step title="Install the SDK">
    <CodeGroup>
      ```bash npm theme={null}
      npm i @henrylabs/sdk
      ```

      ```bash bun theme={null}
      bun add @henrylabs/sdk
      ```

      ```bash pnpm theme={null}
      pnpm add @henrylabs/sdk
      ```

      ```bash yarn theme={null}
      yarn add @henrylabs/sdk
      ```
    </CodeGroup>
  </Step>

  <Step title="Set your environment variable">
    ```bash theme={null}
    #.env.local
    HENRY_SDK_API_KEY=your_api_key_here
    ```
  </Step>

  <Step title="Initialize the client">
    ```typescript theme={null}
    import HenrySDK from '@henrylabs/sdk';

    const henry = new HenrySDK({
      apiKey: process.env.HENRY_SDK_API_KEY!,
    });
    ```
  </Step>
</Steps>

***

## End-to-end walkthrough

### Step 1 - Search for products

Product search is async. The initial call returns a `refId` so in this example we'll poll until results arrive.

```typescript theme={null}
// Kick off the search
const search = await henry.products.search({
	type: 'global',
	filters: { type: 'text', query: 'Nike Air Max' },
	limit: 10,
});

// Poll until complete
async function pollUntilDone<T extends { status: string; refId: string }>(initial: T, poll: (args: { refId: string }) => Promise<T>, intervalMs = 1000): Promise<T> {
	let current = initial;
	while (current.status === 'pending' || current.status === 'processing') {
		await new Promise((r) => setTimeout(r, intervalMs));
		current = await poll({ refId: initial.refId });
	}
	return current;
}

const searchResult = await pollUntilDone(search, (args) => henry.products.pollSearch(args));

const products = searchResult.result?.products ?? [];
const first = products[0];
console.log(first.name, first.price.value, first.price.currency);
// → "Nike Air Max 270" "150.00" "USD"
```

<Tip>Cache the `refId` - you can re-poll any time to retrieve results without re-running the search.</Tip>

***

### Step 2 - Fetch product details

Use the product `link` from the search result to pull full details: rich images, all variants, and live availability.

```typescript theme={null}
const detailResult = await henry.products.details({
	link: first.link,
});

const detail = await pollUntilDone(detailResult, (args) => henry.products.pollDetails(args));

const product = detail.result;
console.log(product?.name, product?.variants);
```

***

### Step 3 - Create a cart

Pass one or more product links to `cart.create`. The response includes a `cartId` and a ready-to-use `checkoutUrl` for hosted checkout.

```typescript theme={null}
const cart = await henry.cart.create({
	items: [
		{
			link: first.link,
			quantity: 1,
			selectedOptions: ['regular', 'black', '10-w'],
		},
	],
});

const { cartId, checkoutUrl } = cart.data;
console.log('Cart:', cartId);
console.log('Checkout URL:', checkoutUrl);
// → https://checkout.henrylabs.ai/cart/<card_id>
```

***

### Step 4 - Add more items (optional)

You can add products to an existing cart at any time.

```typescript theme={null}
await henry.cart.item.add(cartId, {
	item: {
		link: 'https://www.nike.com/t/air-max-270-shoes/AH8050-002',
		quantity: 2,
	},
});
```

***

### Step 5 - Launch hosted checkout

The `checkoutUrl` returned by `cart.create` points to Henry's hosted checkout modal. Redirect your user, open it in an iframe, or pop it in a modal - Henry handles payment, address, and tax collection.

```typescript theme={null}
// Option A: Full page redirect (server-side)
res.redirect(checkoutUrl);

// Option B: Embed in an iframe (client-side)
const iframe = document.createElement('iframe');
iframe.src = checkoutUrl;
iframe.style.cssText = 'width:100%;height:700px;border:none;border-radius:12px';
document.getElementById('checkout-container')!.appendChild(iframe);

// - [Optional]: Listen for completion events
window.addEventListener('message', (event) => {
	if (!event.origin.endsWith('.henrylabs.ai')) return;

	const { action, orderId } = event.data ?? {};
	if (action === 'orderCompleted') {
		console.log('Order placed:', orderId);
	}
});
```

<Info>Need full control over the checkout UI? See [Headless Checkout](/v1/sdk/server/guides/checkout#headless-checkout)</Info>

***

### Step 6 - Track the order

The recommended approach is webhooks - Henry will POST to your endpoint when the order status changes, so you don't have to poll.

Register a webhook endpoint in the [Henry Dashboard](https://app.henrylabs.ai), then handle the events:

```typescript theme={null}
app.post('/webhooks/henry', express.raw({ type: 'application/json' }), async (req, res) => {
	if (!verifyHenryWebhook(req.body.toString(), req.headers['x-henry-signature'], req.headers['x-henry-timestamp'])) {
		return res.sendStatus(401);
	}

	const { event, data } = JSON.parse(req.body.toString());

	if (event === 'order.purchase.full.complete') {
		console.log('Order complete:', data.refId, data.result?.costs);
	} else if (event === 'order.purchase.full.cancelled') {
		console.log('Order cancelled:', data.refId);
	}

	res.sendStatus(200);
});
```

<Tip>See the [Webhooks guide](/v1/sdk/server/guides/webhooks) for signature verification and the full list of events. If you need to check order status on demand, use `orders.list({cartId})`.</Tip>

***

## Next steps

<CardGroup cols={2}>
  <Card title="Product Discovery" icon="magnifying-glass" href="/v1/sdk/server/guides/product-discovery">
    Deep dive: search filters, async polling, and rich product details
  </Card>

  <Card title="Universal Cart" icon="cart-shopping" href="/v1/sdk/server/guides/universal-cart">
    Create, manage, and configure multi-merchant carts
  </Card>

  <Card title="Checkout" icon="credit-card" href="/v1/sdk/server/guides/checkout">
    Hosted checkout with postMessage events, and Pro headless checkout
  </Card>

  <Card title="Order Management" icon="receipt" href="/v1/sdk/server/guides/order-management">
    List, filter, and poll orders across all your users
  </Card>
</CardGroup>
