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

# Recipes

> Common patterns and code examples for Headless Commerce

# Recipes

Practical, copy-paste-ready code examples for the most common commerce workflows. Every recipe uses the TypeScript SDK.

<Info>
  All examples assume you have already installed and configured the SDK. See the [Introduction](/introduction#install-the-sdk) if you haven't.
</Info>

***

## Recipe 1: Customer Authentication

Register a new customer, log in, and use the customer token to access protected routes like order history.

```typescript theme={null}
import { createStorefrontClient } from '@headless-commerce/sdk';

const client = createStorefrontClient({
  apiKey: process.env.NEXT_PUBLIC_HC_API_KEY!,
});

// 1. Register a new customer
const customer = await client.customers.register({
  email: 'jane@example.com',
  password: 'SecureP@ss123!',
  first_name: 'Jane',
  last_name: 'Doe',
});

// 2. Log in to get a JWT token
const { token } = await client.customers.login({
  email: 'jane@example.com',
  password: 'SecureP@ss123!',
});

// 3. Set the customer token for subsequent requests
client.setCustomerToken(token);

// 4. Access protected routes
const { data: orders } = await client.customers.orders.list({ limit: 10 });
const profile = await client.customers.me();
console.log(profile.email); // "jane@example.com"
```

***

## Recipe 2: Cart Merging After Login

When an anonymous visitor adds items to a cart and then logs in, merge the guest cart into their existing customer cart.

```typescript theme={null}
import { createStorefrontClient } from '@headless-commerce/sdk';

const client = createStorefrontClient({
  apiKey: process.env.NEXT_PUBLIC_HC_API_KEY!,
});

// 1. Guest browses and adds items
const guestCart = await client.carts.create({ session_id: 'anon-session-456' });
await client.carts.addItem(guestCart.id, {
  variant_id: 'var_hoodie_l_navy',
  quantity: 1,
});

// 2. Guest decides to log in
const { token } = await client.customers.login({
  email: 'jane@example.com',
  password: 'SecureP@ss123!',
});
client.setCustomerToken(token);

// 3. Merge the anonymous cart into the customer's cart
// Items from the guest cart are added to the customer's existing cart.
// Duplicate variants have their quantities summed.
const mergedCart = await client.carts.merge({
  source_cart_id: guestCart.id,
});

console.log(mergedCart.items.length); // Combined items from both carts
```

***

## Recipe 3: Discount Code Workflow

Admin creates a discount code, the storefront applies it to a cart, and the customer checks out with the discount.

```typescript theme={null}
import { createAdminClient, createStorefrontClient } from '@headless-commerce/sdk';

// --- Admin side: create the discount ---
const admin = createAdminClient({ apiKey: 'sk_live_xxx' });

const discount = await admin.discounts.create({
  code: 'SUMMER20',
  type: 'percentage',
  value: 20, // 20% off
  starts_at: '2025-06-01T00:00:00Z',
  ends_at: '2025-08-31T23:59:59Z',
  usage_limit: 500,
  min_order_amount: 30000, // KRW
});

// --- Storefront side: apply to cart ---
const client = createStorefrontClient({
  apiKey: process.env.NEXT_PUBLIC_HC_API_KEY!,
});

const cart = await client.carts.create({ session_id: 'session-789' });
await client.carts.addItem(cart.id, {
  variant_id: 'var_dress_s_red',
  quantity: 1,
});

// Apply discount code
const updated = await client.carts.applyDiscount(cart.id, { code: 'SUMMER20' });
console.log(updated.discount_total); // -8000 (20% of 40000)

// Checkout proceeds with discount applied
const order = await client.carts.checkout(cart.id, {
  email: 'shopper@example.com',
  shipping_address: { line1: '456 Oak Ave', city: 'Busan', country: 'KR' },
  payment_method: 'stripe',
});
```

***

## Recipe 4: Inventory Management

List products with low stock, adjust inventory quantities, and configure safety stock thresholds.

```typescript theme={null}
import { createAdminClient } from '@headless-commerce/sdk';

const admin = createAdminClient({ apiKey: 'sk_live_xxx' });

// 1. List variants with low stock
const { data: lowStock } = await admin.inventory.list({
  status: 'low_stock',
  limit: 20,
});
console.log(`${lowStock.length} items below safety stock`);

// 2. Adjust inventory for a specific variant (e.g., restock)
await admin.inventory.adjust({
  variant_id: 'var_tshirt_m_black',
  quantity: 50, // positive = add, negative = subtract
  reason: 'Restock from supplier PO-2025-0042',
});

// 3. Set safety stock threshold (triggers inventory.low webhook)
await admin.inventory.update('var_tshirt_m_black', {
  safety_stock: 10,
  track_inventory: true,
});

// 4. Get current inventory for a variant
const inv = await admin.inventory.get('var_tshirt_m_black');
console.log(inv.available);    // 50
console.log(inv.safety_stock); // 10
```

***

## Recipe 5: Return & Refund Flow

A customer requests a return, the admin reviews and processes it through approval, receiving, completion, and finally issues a refund.

```typescript theme={null}
import { createAdminClient, createStorefrontClient } from '@headless-commerce/sdk';

const client = createStorefrontClient({
  apiKey: process.env.NEXT_PUBLIC_HC_API_KEY!,
});
client.setCustomerToken('cust_token_xxx');

// 1. Customer requests a return
const returnReq = await client.returns.create({
  order_id: 'order_abc123',
  items: [
    { order_item_id: 'oi_item1', quantity: 1, reason: 'Wrong size' },
  ],
  note: 'I ordered M but need L instead',
});

// --- Admin side ---
const admin = createAdminClient({ apiKey: 'sk_live_xxx' });

// 2. Admin approves the return
await admin.returns.approve(returnReq.id);

// 3. Admin marks items as received
await admin.returns.receive(returnReq.id, {
  items: [{ order_item_id: 'oi_item1', quantity: 1, condition: 'good' }],
});

// 4. Admin completes the return
await admin.returns.complete(returnReq.id);

// 5. Create a refund for the returned items
const refund = await admin.refunds.create({
  order_id: 'order_abc123',
  amount: 29000,
  reason: 'Return - wrong size',
  items: [{ order_item_id: 'oi_item1', quantity: 1 }],
});
console.log(refund.status); // "pending" → processed by payment provider
```

***

## Recipe 6: Fulfillment Lifecycle

Create a fulfillment for an order, add tracking info, mark as shipped, and then mark as delivered.

```typescript theme={null}
import { createAdminClient } from '@headless-commerce/sdk';

const admin = createAdminClient({ apiKey: 'sk_live_xxx' });

// 1. Create a fulfillment for specific order items
const fulfillment = await admin.fulfillments.create({
  order_id: 'order_abc123',
  items: [
    { order_item_id: 'oi_item1', quantity: 2 },
    { order_item_id: 'oi_item2', quantity: 1 },
  ],
  tracking_number: '1234567890',
  tracking_company: 'CJ Logistics',
  tracking_url: 'https://trace.cjlogistics.com/tracking/1234567890',
});

console.log(fulfillment.status); // "created"

// 2. Mark as shipped (triggers fulfillment.shipped webhook)
await admin.fulfillments.ship(fulfillment.id, {
  shipped_at: new Date().toISOString(),
  notify_customer: true, // sends shipping notification email
});

// 3. Mark as delivered (triggers fulfillment.delivered webhook)
await admin.fulfillments.deliver(fulfillment.id, {
  delivered_at: new Date().toISOString(),
  notify_customer: true,
});
```

***

## Recipe 7: Multi-Region Pricing

Create regions with different currencies and set region-specific prices for products.

```typescript theme={null}
import { createAdminClient } from '@headless-commerce/sdk';

const admin = createAdminClient({ apiKey: 'sk_live_xxx' });

// 1. Create regions
const krRegion = await admin.regions.create({
  name: 'South Korea',
  currency: 'KRW',
  countries: ['KR'],
  tax_rate: 10,
});

const usRegion = await admin.regions.create({
  name: 'United States',
  currency: 'USD',
  countries: ['US'],
  tax_rate: 0, // varies by state
});

// 2. Set region-specific prices for a variant
await admin.variants.setRegionPrices('var_tshirt_m_black', [
  { region_id: krRegion.id, price: 29000 },  // 29,000 KRW
  { region_id: usRegion.id, price: 2200 },   // $22.00 USD
]);

// 3. Storefront: fetch prices for a specific region
import { createStorefrontClient } from '@headless-commerce/sdk';

const storefront = createStorefrontClient({
  apiKey: process.env.NEXT_PUBLIC_HC_API_KEY!,
});

const product = await storefront.products.get('prod_abc123', {
  region_id: krRegion.id,
});
// product.variants[0].price → 29000 (KRW)
```

***

## Recipe 8: CSV Bulk Import

Import products from a CSV spreadsheet, handling validation errors gracefully.

```typescript theme={null}
import { createAdminClient } from '@headless-commerce/sdk';
import fs from 'node:fs';

const admin = createAdminClient({ apiKey: 'sk_live_xxx' });

// 1. Read the CSV file
const csvBuffer = fs.readFileSync('./products.csv');

// 2. Start the import job
const job = await admin.imports.create({
  type: 'products',
  file: new Blob([csvBuffer], { type: 'text/csv' }),
  options: {
    on_duplicate: 'update',   // "skip" | "update" | "error"
    notify_on_complete: true,
  },
});

console.log(job.id);     // "import_xyz789"
console.log(job.status); // "processing"

// 3. Poll for completion
let result = await admin.imports.get(job.id);
while (result.status === 'processing') {
  await new Promise((r) => setTimeout(r, 2000));
  result = await admin.imports.get(job.id);
}

// 4. Check results
console.log(`Imported: ${result.summary.created} created, ${result.summary.updated} updated`);
if (result.summary.errors > 0) {
  console.log('Errors:');
  for (const err of result.errors) {
    console.log(`  Row ${err.row}: ${err.message}`);
  }
}
```

Expected CSV format:

```csv theme={null}
name,sku,price,currency,status,variant_name,inventory_quantity
"Classic T-Shirt","TSH-001",29000,"KRW","active","M / Black",50
"Classic T-Shirt","TSH-002",29000,"KRW","active","L / Black",30
"Summer Dress","DRS-001",59000,"KRW","draft","S / Red",20
```

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Webhooks" icon="bell" href="/webhooks">
    Webhook setup, signature verification, and production-grade processing patterns.
  </Card>

  <Card title="API Reference" icon="book-open" href="/api-reference/introduction">
    Explore all 100+ REST endpoints.
  </Card>

  <Card title="SDKs" icon="code" href="/sdks">
    TypeScript and Python SDK reference with every resource and method.
  </Card>

  <Card title="Stripe Integration" icon="credit-card" href="/guides/stripe-integration">
    Set up Stripe payments for your storefront.
  </Card>
</CardGroup>
