Frontend Integration

Frontend Integration Guide

Ready to connect your application to BareCommerce Core? This guide covers authentication, API routes, integration patterns, and practical examples.

System Architecture

Key Points:

  • Your frontend communicates with BareCommerce API
  • Payment providers are external (Stripe, PayPal, Square)
  • Orders are created automatically from webhooks, not API calls
  • All data is stored in BareCommerce (you don't need a database)
  • Files are stored in Cloudflare R2 with no egress fees

Key Understanding: Orders Are Webhook-Driven

Important: BareCommerce Core creates orders exclusively via webhooks from payment providers. There is no API endpoint to manually create orders. You cannot POST to create an order.

Instead:

  1. Your frontend creates a Payment Intent with order metadata
  2. Payment provider processes the payment
  3. Payment provider sends a webhook to BareCommerce
  4. BareCommerce automatically creates the order
  5. Your frontend fetches the order via GET endpoint

The Order Flow

Storefront
    ↓
Customer adds items to cart
    ↓
Creates Payment Intent (with order metadata)
    ↓
Payment Provider (Stripe/PayPal/Square)
    ↓
Customer completes payment
    ↓
Payment Provider sends webhook
    ↓
BareCommerce creates order automatically
    ↓
Frontend fetches order via GET /orders
    ↓
Show confirmation to customer

Authentication

For Merchant Dashboard

Session-based login:

POST /api/auth/merchant/login
{
  "email": "merchant@example.com",
  "password": "password"
}

Response sets barecommerce_session cookie. OAuth (GitHub, Google) also supported.

For Storefronts & Integrations

API key authentication:

X-API-Key: sk_live_xxxxxxxxxxxxxxxxxxxxx

API keys are scoped to stores and limited by permissions.

Core API Routes

Authentication

POST   /api/auth/merchant/signup
POST   /api/auth/merchant/login
POST   /api/auth/merchant/logout
GET    /api/auth/merchant/me
POST   /api/auth/merchant/avatar (v1.7 - Upload avatar)
GET    /api/auth/github
GET    /api/auth/google

Products

GET    /api/stores/{storeId}/products
POST   /api/stores/{storeId}/products
GET    /api/stores/{storeId}/products/{id}
PUT    /api/stores/{storeId}/products/{id}
DELETE /api/stores/{storeId}/products/{id}
POST   /api/stores/{storeId}/products/bulk (v1.7 - Bulk operations)
GET    /api/stores/{storeId}/products/attributes (v1.7 - Get attributes)
GET    /api/stores/{storeId}/products/import-schema (v1.7 - Import schema)
GET    /api/stores/{storeId}/products/by-variant-group?variantGroupId=xxx
GET    /api/stores/{storeId}/products/by-attributes?color=red&size=m

Categories

GET    /api/stores/{storeId}/categories
POST   /api/stores/{storeId}/categories
GET    /api/stores/{storeId}/categories/{id}
PUT    /api/stores/{storeId}/categories/{id}
DELETE /api/stores/{storeId}/categories/{id}

Customers

GET    /api/stores/{storeId}/customers
POST   /api/stores/{storeId}/customers
GET    /api/stores/{storeId}/customers/{id}
PUT    /api/stores/{storeId}/customers/{id}
DELETE /api/stores/{storeId}/customers/{id}

Orders (Read-Only)

GET    /api/stores/{storeId}/orders
GET    /api/stores/{storeId}/orders/{id}

⚠️ Important: Orders are created exclusively via payment provider webhooks. There are no POST/PUT/DELETE endpoints for orders.

Media

GET    /api/stores/{storeId}/media
POST   /api/stores/{storeId}/media
GET    /api/stores/{storeId}/media/{id}
PUT    /api/stores/{storeId}/media/{id}
DELETE /api/stores/{storeId}/media/{id}

Pages

GET    /api/stores/{storeId}/pages
POST   /api/stores/{storeId}/pages
GET    /api/stores/{storeId}/pages/{id}
PUT    /api/stores/{storeId}/pages/{id}
DELETE /api/stores/{storeId}/pages/{id}

Webhooks

GET    /api/stores/{storeId}/webhooks
POST   /api/stores/{storeId}/webhooks
GET    /api/stores/{storeId}/webhooks/{id}
PUT    /api/stores/{storeId}/webhooks/{id}
DELETE /api/stores/{storeId}/webhooks/{id}

API Keys

GET    /api/stores/{storeId}/api-keys
POST   /api/stores/{storeId}/api-keys
GET    /api/stores/{storeId}/api-keys/{id}
PUT    /api/stores/{storeId}/api-keys/{id}
DELETE /api/stores/{storeId}/api-keys/{id}

Audit Logs

GET    /api/stores/{storeId}/audit-logs
GET    /api/stores/{storeId}/audit-logs/{id}

Response Format

Single Resource:

{
  "item": { ...fields... }
}

List:

{
  "items": [...],
  "total": 100
}

Error:

{
  "error": {
    "code": "ERROR_CODE",
    "message": "Human readable message",
    "details": { ...context... }
  }
}

Common Error Codes

CodeHTTPDescription
VALIDATION_ERROR400Invalid field values
UNAUTHORIZED401Auth required
FORBIDDEN403Insufficient permissions
NOT_FOUND404Resource not found
CONFLICT409Duplicate or state conflict
RATE_LIMITED429Too many requests
INTERNAL_ERROR500Server error

Database Schema at a Glance

Products

id, storeId, title, slug, price, sku, barcode
variantGroupId (groups variants)
attributes (JSON: color, size, etc)
status (draft|published|archived|deleted)
stock, trackStock, allowBackorder
categoryIds, mediaIds (JSON arrays)

Orders

id, orderNumber (auto-generated)
customerId, storeId
status (pending|paid|fulfilled|cancelled)
total, subtotal, tax, shipping, discount
currency (default: USD)
paymentProvider, paymentId, paymentStatus
items (OrderItem[])
shippingAddress, billingAddress (JSON)
placedAt, paidAt, fulfilledAt, cancelledAt

Variants

Variants are just Products with the same variantGroupId:

- Product 1: Blue Shirt / M
- Product 2: Blue Shirt / L  
- Product 3: Red Shirt / M

Query with:

GET /api/stores/{storeId}/products/by-variant-group?variantGroupId=vg_123

Integration Patterns

Pattern 1: Public Storefront

Your Job:

  1. Fetch and display products
  2. Build shopping cart
  3. Create Payment Intent with order metadata
  4. Send to payment provider

BareCommerce Job:

  1. Receive webhook from payment provider
  2. Create order automatically
  3. Make available via GET /orders

Flow:

1. Display products
2. Customer adds items
3. Create Payment Intent
4. Payment Provider
5. Payment webhook
6. BareCommerce creates order
7. GET /orders to fetch
8. Show confirmation

Pattern 2: Merchant Dashboard

Operations:

  • Create/read/update/delete products
  • Create/read/update/delete categories
  • View orders (read-only)
  • Manage customers
  • View activity logs
  • Configure store

Auth: Session (merchant login)

Pattern 3: Headless / Programmatic

Operations:

  • Fetch products
  • Listen to webhooks
  • Read orders
  • Sync to custom systems

Auth: API Key

Common Tasks

Fetch Products

const response = await fetch(
  `https://api.barecommercecore.com/api/stores/${storeId}/products?status=published&limit=20`,
  { headers: { "X-API-Key": apiKey } }
);
const { items } = await response.json();

Fetch Variants

const response = await fetch(
  `https://api.barecommercecore.com/api/stores/${storeId}/products/by-variant-group?variantGroupId=vg_123`,
  { headers: { "X-API-Key": apiKey } }
);
const { items: variants } = await response.json();

Fetch Orders

const response = await fetch(
  `https://api.barecommercecore.com/api/stores/${storeId}/orders?status=paid`,
  { headers: { "X-API-Key": apiKey } }
);
const { items: orders } = await response.json();

Create Payment Intent with Metadata

const stripe = require("stripe")(STRIPE_SECRET_KEY);
 
const paymentIntent = await stripe.paymentIntents.create({
  amount: 9999, // $99.99 in cents
  currency: "usd",
  metadata: {
    store_id: storeId,
    customer_id: customerId,
    items: JSON.stringify([
      { productId: "prod_1", quantity: 2, unitPrice: "29.99" }
    ]),
    subtotal: "59.98",
    tax: "4.80",
    shipping: "10.00"
  }
});
 
return { clientSecret: paymentIntent.client_secret };

Webhooks

Events You'll Receive

order.created        ← Order created from payment
order.updated        - Order status changed
product.created      - New product
product.updated      - Product changed
category.created     - New category
customer.created     - New customer

Webhook Payload

{
  "id": "webhook_event_id",
  "event": "order.created",
  "timestamp": "2024-01-15T10:30:00Z",
  "storeId": "store_123",
  "data": {
    "id": "order_123",
    "orderNumber": "ORD-000001",
    "customerId": "cust_456",
    "total": "99.99",
    "status": "paid",
    "items": [...],
    ...all order fields...
  }
}

Verify Webhook Signature

All webhooks are signed with HMAC-SHA256:

import crypto from "crypto";
 
function verifySignature(body: string, signature: string, secret: string) {
  const hash = crypto
    .createHmac("sha256", secret)
    .update(body)
    .digest("hex");
  
  return crypto.timingSafeEqual(
    Buffer.from(hash),
    Buffer.from(signature)
  );
}
 
export async function POST(request: Request) {
  const signature = request.headers.get("x-signature");
  const body = await request.text();
  
  if (!verifySignature(body, signature!, WEBHOOK_SECRET)) {
    return Response.json({ error: "Invalid" }, { status: 401 });
  }
  
  const event = JSON.parse(body);
  
  if (event.event === "order.created") {
    const order = event.data;
    
    // Send confirmation email
    await sendOrderConfirmation(order);
    
    // Notify fulfillment
    await notifyWarehouse(order);
    
    // Update inventory
    await updateInventory(order.items);
  }
  
  return Response.json({ ok: true });
}

Pagination

All list endpoints support:

?limit=50&offset=0
  • limit: 1-200 (default 50)
  • offset: Skip count (default 0)

Error Handling

async function apiCall(url: string, options: RequestInit) {
  try {
    const response = await fetch(url, options);
    
    if (!response.ok) {
      const { error } = await response.json();
      
      switch (error.code) {
        case "VALIDATION_ERROR":
          error.details?.forEach(({ field, reason }) => {
            console.error(`${field}: ${reason}`);
          });
          break;
        
        case "UNAUTHORIZED":
          redirect("/login");
          break;
        
        case "RATE_LIMITED":
          await new Promise(r => setTimeout(r, 1000));
          return apiCall(url, options); // Retry
          break;
        
        default:
          console.error(error.message);
      }
      
      throw new Error(error.code);
    }
    
    return response.json();
  } catch (err) {
    console.error("API error:", err);
    throw err;
  }
}

Integration Checklist

  • Understand orders are webhook-driven only
  • Set up payment provider (Stripe/PayPal/Square)
  • Create API key or set up session auth
  • Implement product fetching
  • Implement category browsing
  • Implement variant selection
  • Build shopping cart
  • Create Payment Intent with metadata
  • Build checkout flow
  • Implement webhook receiver
  • Verify webhook signatures
  • Handle order.created webhook
  • Fetch orders via GET /orders
  • Show order confirmation
  • Implement error handling
  • Test in payment provider test mode
  • Deploy to staging
  • Test end-to-end
  • Deploy to production
  • Switch to live API keys
  • Monitor webhook delivery

Next Steps

For detailed technical specs, see the FRONTEND_INTEGRATION_GUIDE.md in the barecommerce-core repository.