> ## 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; // "5b2e7f71-62cf-4bd5-b84e-df17f1f18927"
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('f8af3da4-f70e-4521-a04f-716c0c04fb77');

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 UUID or slug. Both work in storefront location endpoints:

```
/api/v1/storefront/locations/f8af3da4-f70e-4521-a04f-716c0c04fb77/...
/api/v1/storefront/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('f8af3da4-f70e-4521-a04f-716c0c04fb77');

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: 'web',
  fulfillmentMethod: 'takeout',
});

const cartId = session.cart.id;
```

`marketplaceId` is optional source attribution, such as `"web"` or
`"mobile"`; it is not a location identifier.

### 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 |
| `EXPIRED`   | Capability is no longer valid; start a new cart  |

### 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          |

Price fields are decimal strings. Format them using the cart currency and the customer's locale.

### 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.total; // "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(...)`    | Numeric table string such as `"12"` |
| 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 } = await storefront.checkout.createPaymentIntent('loc_123', cartId);
```

| Field          | Description                                     |
| -------------- | ----------------------------------------------- |
| `clientSecret` | Pass to `stripe.confirmPayment()` on the client |

## 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.

Poll `storefront.checkout.getOrderResult()` after payment. It distinguishes `payment_pending`, `order_pending`, `completed`, and `failed`. Signed-in customers can list and read only their own orders through `storefront.customer.orders`.

## Analytics events

Track key funnel events to measure storefront performance:

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

Every public analytics event requires authorization for its cart. `ORDER_PLACED` is recorded by the
API during authoritative order creation and is not accepted from clients.

## 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>
