Documentation Index
Fetch the complete documentation index at: https://docs.cravejs.com/llms.txt
Use this file to discover all available pages before exploring further.
The Storefront SDK (@craveup/storefront-sdk) gives you a thin, type-safe wrapper around the Crave Storefront API. It handles headers, timeouts, query strings, and customer auth tokens so you can focus on product workflows instead of request plumbing.
Installation
pnpm add @craveup/storefront-sdk
The CLI templates already include this dependency. Install it manually if you are integrating the SDK into an existing project.
Creating a client
// lib/storefront-client.ts
import { createStorefrontClient } from '@craveup/storefront-sdk';
export const storefrontClient = createStorefrontClient({
apiKey: process.env.NEXT_PUBLIC_CRAVEUP_API_KEY, // location-scoped API key
getAuthToken: () => localStorage.getItem('craveup-auth-token'), // optional customer JWT
defaultTimeoutMs: 15_000, // optional (defaults to 10s)
});
Client options
| Option | Required | Description |
|---|
baseUrl | optional | Override the API base URL. When omitted, the SDK infers dev vs prod from the API key. |
apiKey | ⚠️* | Location-scoped API key. Required unless you inject it via headers on every call. |
getAuthToken | optional | Function that returns a customer JWT for authenticated flows (OTP login). Can resolve a promise for async storage. |
fetch | optional | Supply a custom fetch implementation (e.g. cross-fetch) when running in Node.js. |
defaultTimeoutMs | optional | Global request timeout in milliseconds (defaults to 10 000). |
*If you omit apiKey, the client looks for NEXT_PUBLIC_CRAVEUP_API_KEY. You can also pass the header per-request via headers: { 'X-API-Key': '...' }.
Using in Node.js / SSR environments
import fetch from 'cross-fetch';
import { createStorefrontClient } from '@craveup/storefront-sdk';
export const storefrontClient = createStorefrontClient({
apiKey: process.env.NEXT_PUBLIC_CRAVEUP_API_KEY,
baseUrl: process.env.CRAVEUP_API_URL, // optional override
fetch, // polyfill for Node runtimes
});
Request configuration
Every SDK method accepts an optional RequestConfig (RequestOptions under the hood):
await storefrontClient.cart.get(locationId, cartId, {
query: { include: 'items' }, // appended to the URL
headers: { 'X-Session-Id': sessionId },
timeoutMs: 5_000, // per-call timeout
skipAuth: true, // ignore apiKey + auth token for public endpoints
credentials: 'include', // passthrough to fetch
});
Available modules
createStorefrontClient exposes a set of grouped helpers. The most common ones are shown below; all public types are re-exported from the package.
Merchant
const merchant = await storefrontClient.merchant.getBySlug('downtown-pizza');
merchant.locations.forEach((location) => console.log(location.restaurantDisplayName));
// Basic location metadata
const location = await storefrontClient.locations.getById(locationId);
// Operating hours
const operatingHours = await storefrontClient.locations.getOrderTimes(locationId);
// Tip configuration
const gratuity = await storefrontClient.locations.getGratuity(locationId);
Ordering sessions
Use ordering sessions to bootstrap a cart and persist metadata:
const session = await storefrontClient.orderingSessions.start(locationId, {
marketplaceId: locationId,
returnUrl: 'https://my-storefront.com/checkout/success',
});
console.log(session.cartId); // use this cart ID for subsequent calls
Cart lifecycle
const cart = await storefrontClient.cart.get(locationId, cartId);
// Add an item
await storefrontClient.cart.addItem(locationId, cart.id, {
productId: 'prod_margherita',
quantity: 2,
selections: [], // modifier selections (see SelectedModifierTypes)
itemUnavailableAction: 'remove_item',
});
// Update customer details prior to checkout
await storefrontClient.cart.validateAndUpdateCustomer(locationId, cart.id, {
customerName: 'Alex Johnson',
emailAddress: 'alex@example.com',
});
// Schedule the order
await storefrontClient.cart.updateOrderTime(locationId, cart.id, {
pickupType: 'LATER',
orderDate: '2024-11-12',
orderTime: '18:30',
});
// Configure fulfillment
await storefrontClient.cart.setDelivery(locationId, cart.id, {
fulfilmentMethod: 'delivery',
address: '123 Main Street',
lat: 37.7749,
lng: -122.4194,
});
Other helpers you can call on cart:
updateGratuity
setTable
setRoom
updateItemQuantity
delete (clears the cart)
Need recommended items? Call the /carts/{cartId}/products endpoint with the http helper.
Discounts
await storefrontClient.discounts.apply(locationId, {
code: 'SAVE10',
cartId,
});
await storefrontClient.discounts.remove(locationId, cartId);
Analytics events
await storefrontClient.analyticsEvents.track(locationId, {
cartId,
eventType: 'CART_VIEW',
metadata: { total: cart.orderTotalWithServiceFee, currency: cart.currency },
});
Direct HTTP access
Need an endpoint the SDK does not wrap yet? Use the underlying http helper—it exposes get, post, put, patch, and delete with the same RequestConfig options.
const suggestions = await storefrontClient.http.get(
`/api/v1/locations/${locationId}/carts/${cartId}/products`,
{ query: { limit: 5 } }
);
Typed responses & imports
All DTOs used by the API are exported so you can declare explicit return types:
import type { StorefrontCart, MerchantApiResponse } from '@craveup/storefront-sdk';
const merchant: MerchantApiResponse = await storefrontClient.merchant.getBySlug(slug);
const cart: StorefrontCart = await storefrontClient.cart.get(locationId, merchant.locations[0].id);
Refer to packages/storefront-sdk/src/types in the monorepo for the complete list.
Error handling
The SDK throws an ApiError whenever the API responds with a non-2xx status:
import { ApiError } from '@craveup/storefront-sdk';
try {
await storefrontClient.discounts.apply(locationId, { code: 'INVALID', cartId });
} catch (error) {
if (error instanceof ApiError) {
console.error('Failed request', {
status: error.status,
url: error.url,
body: error.body,
});
}
}
The thrown error includes status, statusText, url, and the raw response body (where provided). Handle specific status codes to deliver better UX—for example, show a toast when a discount is no longer valid.
Working alongside the REST docs
Each SDK method corresponds one-to-one with a REST endpoint documented in the Storefront API reference. Use the SDK for JavaScript/TypeScript apps and the REST examples for other platforms; the payloads and response shapes are identical.
Ready to put it all together? Follow the Build a Custom Storefront guide for an end-to-end walkthrough.