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

# API Overview

> Authenticate, make requests, and handle responses from the Crave Storefront API.

The Storefront API exposes every operation your customers need to browse menus, build carts, and pay for orders. All endpoints return JSON over HTTPS and authenticate with a location-scoped API key.

## Base URL

```
https://api.craveup.com/api/v1
```

<Note>
  There is no sandbox server. Storefront applications connect directly to the production API using your API key.
</Note>

## Authentication

Include your API key in the `X-API-Key` header on every request:

<CodeGroup>
  ```ts SDK theme={null}
  import { createStorefrontClient } from '@craveup/storefront-sdk';

  const storefront = createStorefrontClient({
    apiKey: 'sk_live_abc123',
  });
  ```

  ```bash cURL theme={null}
  curl -H "X-API-Key: sk_live_abc123" \
       -H "Content-Type: application/json" \
       https://api.craveup.com/api/v1/locations/loc_123
  ```
</CodeGroup>

Generate an API key from the [Crave Dashboard](https://craveup.com/login) under **Settings > API Keys**. Each key is scoped to a single location.

## Location-scoped endpoints

Every storefront endpoint lives under `/locations/{locationId}`:

```
GET  /api/v1/locations/{locationId}
GET  /api/v1/locations/{locationId}/time-intervals
POST /api/v1/locations/{locationId}/ordering-sessions
POST /api/v1/locations/{locationId}/carts/{cartId}/cart-item
GET  /api/v1/locations/{locationId}/carts/{cartId}
PUT  /api/v1/locations/{locationId}/carts/{cartId}/set-delivery
GET  /api/v1/stripe/payment-intent?locationId=...&cartId=...
```

You can use either the location's ObjectId (`64a7b8c9d1e2f3a4b5c6d7e8`) or its slug (`downtown-pizza`) as `{locationId}`. Both formats work interchangeably.

## Resource groups

The API is organized into these groups:

| Group                 | Operations                                                               |
| --------------------- | ------------------------------------------------------------------------ |
| **Merchant**          | Look up a merchant and its locations by slug                             |
| **Locations**         | Get location info, order times, gratuity config, distance                |
| **Ordering Sessions** | Create or resume a cart                                                  |
| **Cart**              | Get, update, add items, set fulfillment, schedule order, manage gratuity |
| **Discounts**         | Apply or remove promo codes                                              |
| **Payments**          | Create a Stripe PaymentIntent                                            |
| **Analytics**         | Track storefront events (page views, checkout, order placed)             |
| **Ratings**           | Submit post-order experience ratings                                     |

## Request format

Send JSON bodies with `Content-Type: application/json`:

```bash theme={null}
curl -X POST "https://api.craveup.com/api/v1/locations/loc_123/carts/cart_456/cart-item" \
  -H "X-API-Key: sk_live_abc123" \
  -H "Content-Type: application/json" \
  -d '{
    "productId": "prod_margherita",
    "quantity": 2,
    "selections": [],
    "itemUnavailableAction": "remove_item"
  }'
```

## Response format

Successful responses return the resource directly:

```json theme={null}
{
  "id": "cart_456",
  "locationId": "loc_123",
  "status": "OPEN",
  "items": [],
  "totalQuantity": 0,
  "subTotal": "0.00",
  "orderTotalWithServiceFee": "0.00",
  "currency": "usd"
}
```

Error responses include a machine-readable code, a human-readable message, and the HTTP status:

```json theme={null}
{
  "error": "VALIDATION_ERROR",
  "message": "The 'quantity' field must be a positive integer.",
  "statusCode": 400
}
```

For the full list of error codes and handling strategies, see [Error Codes](/guides/error-codes).

## HTTP status codes

| Code  | Meaning                                                        |
| ----- | -------------------------------------------------------------- |
| `200` | Request succeeded                                              |
| `201` | Resource created                                               |
| `204` | Success, no content returned                                   |
| `400` | Invalid request data                                           |
| `401` | Missing or invalid API key                                     |
| `403` | Insufficient permissions or inactive subscription              |
| `404` | Resource not found                                             |
| `409` | Conflict with current state (e.g., discount already applied)   |
| `422` | Valid request, but cannot be processed (e.g., location closed) |
| `429` | Rate limit exceeded                                            |
| `500` | Internal server error                                          |

## Rate limiting

The API allows **200 requests per 10 minutes** per IP address. Rate limit state is returned in response headers:

| Header                  | Description                              |
| ----------------------- | ---------------------------------------- |
| `X-RateLimit-Remaining` | Requests remaining in the current window |
| `X-RateLimit-Reset`     | Unix timestamp when the window resets    |

When you exceed the limit, the API returns `429` with a `Retry-After` header. Implement exponential backoff for retries.

## Data types

| Type      | Format             | Example                      |
| --------- | ------------------ | ---------------------------- |
| ID        | String             | `"64a7b8c9d1e2f3a4b5c6d7e8"` |
| Slug      | URL-safe string    | `"downtown-pizza"`           |
| Price     | Decimal string     | `"12.99"`                    |
| Currency  | ISO 4217 lowercase | `"usd"`, `"gbp"`, `"aed"`    |
| Date      | `YYYY-MM-DD`       | `"2025-03-15"`               |
| Time      | 24-hour `HH:mm`    | `"18:30"`                    |
| Timestamp | ISO 8601           | `"2025-03-15T18:30:00Z"`     |

## Typical integration flow

The following example shows the standard ordering flow from session to payment:

<CodeGroup>
  ```ts SDK theme={null}
  import { createStorefrontClient } from '@craveup/storefront-sdk';

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

  const locationId = 'loc_123';

  // 1. Start an ordering session
  const { cartId } = await storefront.orderingSessions.start(locationId, {
    marketplaceId: locationId,
  });

  // 2. Add items
  await storefront.cart.addItem(locationId, cartId!, {
    productId: 'prod_margherita',
    quantity: 2,
    selections: [],
    itemUnavailableAction: 'remove_item',
  });

  // 3. Set customer details
  await storefront.cart.validateAndUpdateCustomer(locationId, cartId!, {
    customerName: 'Alex Johnson',
    emailAddress: 'alex@example.com',
  });

  // 4. Set order time
  await storefront.cart.updateOrderTime(locationId, cartId!, {
    pickupType: 'ASAP',
  });

  // 5. Create payment intent
  const { clientSecret } = await storefront.payments.createIntent(locationId, cartId!);

  // 6. Confirm payment with Stripe.js on the client
  ```

  ```bash cURL theme={null}
  # 1. Start an ordering session
  curl -X POST "https://api.craveup.com/api/v1/locations/loc_123/ordering-sessions" \
    -H "X-API-Key: $CRAVEUP_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"marketplaceId": "loc_123"}'

  # 2. Add an item
  curl -X POST "https://api.craveup.com/api/v1/locations/loc_123/carts/{cartId}/cart-item" \
    -H "X-API-Key: $CRAVEUP_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"productId": "prod_margherita", "quantity": 2, "selections": [], "itemUnavailableAction": "remove_item"}'

  # 3. Set customer details
  curl -X PUT "https://api.craveup.com/api/v1/locations/loc_123/cart/{cartId}/validate-and-update" \
    -H "X-API-Key: $CRAVEUP_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"customerName": "Alex Johnson", "emailAddress": "alex@example.com"}'

  # 4. Set order time
  curl -X PUT "https://api.craveup.com/api/v1/locations/loc_123/carts/{cartId}/update-order-time" \
    -H "X-API-Key: $CRAVEUP_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"pickupType": "ASAP"}'

  # 5. Create payment intent
  curl "https://api.craveup.com/api/v1/stripe/payment-intent?locationId=loc_123&cartId={cartId}" \
    -H "X-API-Key: $CRAVEUP_API_KEY"
  ```
</CodeGroup>

## Storefront scope

The Storefront API covers customer-facing operations only. Menu management, order fulfillment, analytics, and merchant settings are handled through the Admin API (coming soon) and the Crave Dashboard.

| Available            | Not available            |
| -------------------- | ------------------------ |
| Menu browsing        | Menu editing             |
| Cart management      | Order management         |
| Payment processing   | Customer accounts        |
| Discount application | Real-time order tracking |
| Analytics events     | Merchant settings        |

## Next steps

<CardGroup cols={2}>
  <Card title="Core Concepts" icon="shapes" href="/api-reference/overview/core-concepts">
    Understand the data model behind locations, menus, carts, and orders.
  </Card>

  <Card title="Quickstarts" icon="bolt" href="/quickstarts/nextjs">
    Build a working storefront in minutes with Next.js, React, or vanilla JS.
  </Card>

  <Card title="Storefront SDK" icon="code" href="/getting-started/storefront-sdk">
    Use the typed TypeScript client instead of raw HTTP.
  </Card>

  <Card title="Error Codes" icon="triangle-exclamation" href="/guides/error-codes">
    Handle every error the API can return.
  </Card>
</CardGroup>
