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

# Core Concepts

> Understand the data model behind merchants, locations, menus, carts, and orders.

The Storefront API is built around five entities: **merchants**, **locations**, **menus**, **carts**, and **orders**. This page explains how they relate to each other and what data each one carries.

## Merchants

A merchant represents a restaurant brand. Each merchant has a name, logo, and one or more locations.

```ts theme={null}
const merchant = await storefront.merchant.getBySlug('downtown-pizza');

merchant.id;        // "64a7b8c9d1e2f3a4b5c6d7e8"
merchant.name;      // "Downtown Pizza Co."
merchant.locations;  // MerchantLocation[]
```

Use `merchant.getBySlug()` to resolve a brand slug into its list of locations. Each location in the response includes an `id`, display name, address, logo, and a `methodsStatus` object indicating which fulfillment methods are enabled.

## Locations

A location is a single restaurant site. All storefront operations — menus, carts, payments — are scoped to a location.

```ts theme={null}
const location = await storefront.locations.getById('loc_123');

location.restaurantDisplayName; // "Downtown Pizza — Market St"
location.addressString;         // "123 Market St, San Francisco, CA 94105"
location.addressData;           // { street, city, state, zipCode, country, lat, lng }
```

### Location identifiers

You can reference a location by either its ObjectId or slug. Both work in every endpoint:

```
/api/v1/locations/64a7b8c9d1e2f3a4b5c6d7e8/...
/api/v1/locations/downtown-pizza/...
```

### Fulfillment methods

Each location enables a subset of these fulfillment methods:

| Method       | Value          | Description                      |
| ------------ | -------------- | -------------------------------- |
| Pickup       | `takeout`      | Customer picks up at the counter |
| Delivery     | `delivery`     | Delivered to customer's address  |
| Table-side   | `table_side`   | Served to a table number         |
| Room service | `room_service` | Delivered to a hotel room        |

Check `methodsStatus` on the merchant location response to determine which options to show:

```ts theme={null}
const loc = merchant.locations[0];
loc.methodsStatus.pickup;      // true
loc.methodsStatus.delivery;    // true
loc.methodsStatus.table;       // false
loc.methodsStatus.roomService; // false
```

### Order times

Locations define when they accept orders. Fetch the available time slots before showing a schedule picker:

```ts theme={null}
const times = await storefront.locations.getOrderTimes('loc_123');

times.scheduleAllowed;         // true — scheduled orders accepted
times.requireScheduledOrders;  // false — ASAP is available
times.orderDays;               // RegularOrderDay[] or SpecialOrderDay[]
```

## Menus, categories, and products

Each location has one or more **menus**. A menu contains **categories**, and each category links to **products**. The active menu depends on the time of day.

```
Merchant → Location → Menu → Category → Product → Modifier
```

### Products

A product represents a single orderable item:

| Field          | Type                  | Description                                      |
| -------------- | --------------------- | ------------------------------------------------ |
| `id`           | `string`              | Unique product ID                                |
| `name`         | `string`              | Display name                                     |
| `description`  | `string`              | Short description                                |
| `price`        | `string`              | Base price as a decimal string (e.g., `"12.99"`) |
| `displayPrice` | `string`              | Formatted price with currency symbol             |
| `images`       | `string[]`            | Product image URLs                               |
| `modifiers`    | `Modifier[]`          | Available customizations                         |
| `availability` | `string`              | Current availability status                      |
| `nutrition`    | `object \| undefined` | Calorie count, dietary preferences, ingredients  |

### Modifiers

Modifiers let customers customize a product (e.g., size, toppings, extras). Each modifier group has selection rules:

```ts theme={null}
interface Modifier {
  id: string;
  name: string;           // "Choose your size"
  rule: {
    min: number;          // 1 — must select at least one
    max: number;          // 1 — can select at most one
  };
  items: ModifierItem[];  // [{ id, name, price, maxQuantity }]
}
```

Modifier items can have nested child groups for multi-level customization (e.g., "Choose your protein" > "Choose your preparation").

## Carts

A cart holds the customer's selections and computes all pricing automatically. You create a cart by starting an **ordering session**:

```ts theme={null}
const session = await storefront.orderingSessions.start('loc_123', {
  marketplaceId: 'loc_123',
});

const cartId = session.cartId;
```

### Cart lifecycle

| Status      | Meaning                                          |
| ----------- | ------------------------------------------------ |
| `OPEN`      | Active — items can be added, removed, or updated |
| `LOCKED`    | Payment is processing — no modifications allowed |
| `COMPLETED` | Payment confirmed — order sent to the restaurant |

### Automatic pricing

Every time you modify the cart, the API recalculates all totals:

| Field                       | Description                            |
| --------------------------- | -------------------------------------- |
| `subTotal`                  | Sum of item prices before tax and fees |
| `taxTotal`                  | Tax based on the location's tax rates  |
| `serviceFeeTotal`           | Platform service fee                   |
| `fulfillmentMethodFeeTotal` | Delivery or fulfillment fee            |
| `waiterTipTotal`            | Customer gratuity                      |
| `orderTotalWithServiceFee`  | Final total the customer pays          |

All price fields have a corresponding `*Formatted` variant (e.g., `subTotalFormatted: "$25.98"`) for display.

### Cart items

Each item in the cart tracks its product, quantity, modifier selections, special instructions, and computed totals:

```ts theme={null}
const cart = await storefront.cart.get('loc_123', cartId);

cart.items.forEach((item) => {
  item.name;                // "Margherita Pizza"
  item.quantity;            // 2
  item.totalFormatted;      // "$25.98"
  item.selections;          // CartModifierGroup[] — chosen modifiers
  item.specialInstructions; // "Extra crispy"
});
```

### Fulfillment configuration

Before checkout, set the fulfillment method on the cart. Each method requires different data:

| Method       | API call                | Required data                      |
| ------------ | ----------------------- | ---------------------------------- |
| Pickup       | `cart.update(...)`      | `{ fulfillmentMethod: 'takeout' }` |
| Delivery     | `cart.setDelivery(...)` | Full address with `lat`/`lng`      |
| Table-side   | `cart.setTable(...)`    | Table number string                |
| Room service | `cart.setRoom(...)`     | Room number and last name          |

## Payments

Crave processes payments through Stripe Connect. You create a `PaymentIntent` via the API and confirm it on the client with Stripe.js:

```ts theme={null}
const { clientSecret, stripeAccountId } = await storefront.payments.createIntent(
  'loc_123',
  cartId
);
```

| Field             | Description                                     |
| ----------------- | ----------------------------------------------- |
| `clientSecret`    | Pass to `stripe.confirmPayment()` on the client |
| `stripeAccountId` | The restaurant's connected Stripe account       |

<Warning>
  Always pass the `stripeAccountId` when initializing Stripe on the client. This routes the payment to the correct connected account.
</Warning>

## Orders

Orders are created automatically when a payment succeeds — you do not create them via the API. After payment, the order appears in the restaurant's merchant dashboard for fulfillment.

The Storefront API does not expose order management endpoints. To track order completion from the customer's perspective, poll the cart status until it reaches `COMPLETED`.

## Analytics events

Track key funnel events to measure storefront performance:

```ts theme={null}
await storefront.analyticsEvents.track('loc_123', {
  cartId,
  eventType: 'ORDER_PLACED', // 'SCAN' | 'CART_VIEW' | 'CHECKOUT_VIEW' | 'ORDER_PLACED'
  metadata: { total: cart.orderTotalWithServiceFee },
});
```

## Currencies and countries

The API supports these currencies and countries:

| Currency          | Code  | Countries |
| ----------------- | ----- | --------- |
| US Dollar         | `usd` | US        |
| British Pound     | `gbp` | GB        |
| UAE Dirham        | `aed` | AE        |
| Australian Dollar | `aud` | AU        |

Currency is set at the merchant level and applies to all locations under that merchant.

## Next steps

<CardGroup cols={2}>
  <Card title="Display Menu" icon="utensils" href="/guides/display-menu">
    Fetch menus, categories, and products for a location.
  </Card>

  <Card title="Manage Cart" icon="cart-shopping" href="/guides/manage-cart">
    Add items, apply modifiers, and manage the cart lifecycle.
  </Card>

  <Card title="Checkout Flow" icon="credit-card" href="/guides/checkout-flow">
    Collect customer details, set order time, and process payment.
  </Card>

  <Card title="Fulfillment Methods" icon="truck" href="/guides/fulfillment-methods">
    Configure delivery, table-side, and room service.
  </Card>
</CardGroup>
