Skip to main content

What is the Crave Storefront API?

The Crave Storefront API is a RESTful API designed specifically for building customer-facing online ordering experiences. It provides all the functionality needed to create custom storefronts, mobile apps, or other ordering interfaces.

Base URL

All API requests should be made to the production API:
https://api.craveup.com/api/v1
Note: There is no local development server for the Crave API. All storefront applications connect directly to the production API using your API key.

Authentication

All API requests require authentication using an API key in the request header:
const headers = {
  'X-API-Key': 'your_api_key_here',
  'Content-Type': 'application/json'
};

API Capabilities

What You Can Do

The Storefront API enables you to:
  • Browse Menus: Get location information, menus, and products
  • Manage Carts: Create and manage shopping carts with automatic pricing
  • Process Payments: Create payment intents and handle checkout
  • Configure Orders: Set delivery addresses, tips, and order times
  • Apply Discounts: Apply and remove discount codes

What You Cannot Do

The Storefront API does not provide:
  • Order Management: View or modify existing orders (merchant-only)
  • Menu Management: Create or edit menus (merchant-only)
  • Customer Accounts: Persistent customer accounts or order history
  • Real-time Updates: Live order tracking or status updates
  • Admin Functions: Analytics, reporting, or merchant settings

API Structure

Location-Scoped Operations

All operations are scoped to a specific location (restaurant):
// All endpoints follow this pattern:
/api/v1/locations/{locationId}/...

// Examples:
GET /api/v1/locations/downtown-pizza/menus
POST /api/v1/locations/downtown-pizza/carts
GET /api/v1/locations/downtown-pizza/products

Resource Groups

The API is organized into logical resource groups:
  • Locations: Restaurant location information and settings
  • Menus: Menu categories and products
  • Products: Individual menu items with pricing and modifiers
  • Carts: Shopping cart management and pricing
  • Cart Items: Add, update, and remove items from carts
  • Customers: Basic customer information for orders
  • Payments: Payment processing through Stripe
  • Discounts: Discount codes and promotions

Request/Response Format

Request Format

All requests use JSON format:
// POST request example
fetch('/api/v1/locations/downtown-pizza/carts', {
  method: 'POST',
  headers: {
    'X-API-Key': 'your_api_key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    marketplaceId: 'downtown-pizza',
    currentCartId: ''
  })
});

Response Format

All responses return JSON with consistent structure:
// Success response
{
  "id": "cart_123",
  "items": [...],
  "subtotal": 2500,
  "tax": 200,
  "total": 2700
}

// Error response
{
  "error": "validation_error",
  "message": "Invalid location ID",
  "details": {
    "field": "locationId",
    "code": "invalid_format"
  }
}

HTTP Status Codes

The API uses standard HTTP status codes:
  • 200 OK: Request successful
  • 201 Created: Resource created successfully
  • 400 Bad Request: Invalid request data
  • 401 Unauthorized: Invalid or missing API key
  • 403 Forbidden: Merchant subscription required
  • 404 Not Found: Resource not found
  • 429 Too Many Requests: Rate limit exceeded
  • 500 Internal Server Error: Server error

Rate Limiting

  • Limit: 200 requests per 10 minutes per IP address
  • Headers:
    • X-RateLimit-Remaining: Requests remaining in current window
    • X-RateLimit-Reset: When the rate limit resets (Unix timestamp)
  • Exceeded: Returns 429 status with retry information

Data Types

Common Types

  • ID: MongoDB ObjectId string (e.g., "64a7b8c9d1e2f3a4b5c6d7e8")
  • Slug: URL-friendly string (e.g., "downtown-pizza")
  • Price: Integer in cents (e.g., 1299 for $12.99)
  • Timestamp: ISO 8601 format (e.g., "2024-01-15T14:30:00Z")
  • Time: 24-hour format (e.g., "14:30")

Location Identifiers

Location IDs can be either:
  • ObjectId: 64a7b8c9d1e2f3a4b5c6d7e8
  • Slug: downtown-pizza
Both formats work interchangeably in API endpoints.

Error Handling

Common Errors

// Invalid API key
{
  "error": "unauthorized",
  "message": "Invalid API key",
  "status": 401
}

// Merchant subscription required
{
  "error": "forbidden",
  "message": "Merchant subscription required",
  "status": 403
}

// Rate limit exceeded
{
  "error": "rate_limit_exceeded",
  "message": "Too many requests",
  "status": 429,
  "retryAfter": 60
}

Best Practices

  1. Always check status codes: Don’t assume success
  2. Handle rate limits: Implement exponential backoff
  3. Parse error responses: Extract error details for debugging
  4. Implement retries: For temporary failures (5xx errors)

Getting Started

  1. Generate a storefront – Run npx craveup init to clone a template and install dependencies.
  2. Add credentials – Populate .env.local with your API key, location ID, and base URL (https://api.craveup.com/api/v1).
  3. Call the API – Use the @craveup/storefront-sdk or issue direct requests with fetch, axios, or your language of choice.
  4. Explore endpoints – Start with:

Integration Examples

Basic Storefront Flow

// 1. Load location and menu
const [location, menu] = await Promise.all([
  fetchLocation(locationId),
  fetchMenu(locationId)
]);

// 2. Start an ordering session (creates or resumes a cart)
const { cartId, errorMessage } = await startOrderingSession(locationId, {
  fulfillmentMethod: 'pickup',
});

if (errorMessage) {
  throw new Error(errorMessage);
}

// 3. Add items to cart
await addItemToCart(locationId, cartId, {
  productId: 'prod_123',
  quantity: 2,
  modifiers: []
});

// 4. Configure cart
await setCartDelivery(locationId, cartId, deliveryAddress);
await setCartTip(locationId, cartId, tipAmount);

// 5. Process payment
const { clientSecret } = await createPaymentIntent(locationId, cartId);
// Handle payment with Stripe...

Error Handling Example

async function safeApiCall(url, options) {
  try {
    const response = await fetch(url, options);
    
    if (!response.ok) {
      const error = await response.json();
      throw new Error(`${error.error}: ${error.message}`);
    }
    
    return await response.json();
  } catch (error) {
    console.error('API call failed:', error);
    throw error;
  }
}

Next Steps

Support

For API support and questions:
  • Email: [email protected]
  • Documentation: This API reference
  • Status: Check API status at status.craveup.com