skills/frontic/skills/shopware-headless-commerce

shopware-headless-commerce

SKILL.md

Shopware 6 Store API — Headless Storefront

Procedural guide for building headless storefronts against Shopware 6.6+ Store API. Covers the stateful/write operations: context, cart, checkout, and account. For product data, listings, and pages use the Frontic skill instead.

Architecture

Frontic Client  →  Product data, listings, pages, categories (read)
Store API       →  Context, cart, checkout, account, payment (write/session)

Both share the same Shopware backend. Frontic handles optimized data delivery; the Store API handles session-bound operations.

Essential Headers

Every request to /store-api/* requires:

Header Required Purpose
sw-access-key Always Sales channel API key (from Admin > Sales Channels)
sw-context-token After first request Session token. Persist from every response.
sw-language-id Optional Override language
sw-currency-id Optional Override currency
Content-Type For POST/PATCH application/json

Critical rule: Always read and persist the sw-context-token from response headers. It can change after login, registration, or context switches.

Core Workflows

Guest → Cart → Login → Checkout

1. GET  /store-api/context                          → Get anonymous token
2. POST /store-api/checkout/cart/line-item           → Add items to cart
3. POST /store-api/account/login                     → Login (merges guest cart)
   (update stored sw-context-token from response)
4. PATCH /store-api/context                          → Set payment + shipping method
5. POST /store-api/checkout/order                    → Create order
6. POST /store-api/handle-payment                    → Initiate payment
7. If redirectUrl → redirect to provider → return to finishUrl

Guest Checkout (No Account)

1. GET  /store-api/context                           → Get anonymous token
2. POST /store-api/account/register { guest: true }  → Register as guest
3. POST /store-api/checkout/cart/line-item            → Add items
4. PATCH /store-api/context                           → Set methods + addresses
5. POST /store-api/checkout/order                     → Create order
6. POST /store-api/handle-payment                     → Handle payment

Payment Redirect Handling

const { redirectUrl } = await storeApi('/handle-payment', {
  orderId, finishUrl, errorUrl
})

if (redirectUrl) {
  // Async payment (PayPal, Stripe, etc.) — redirect to provider
  window.location.href = redirectUrl
} else {
  // Sync payment (invoice, prepayment) — show confirmation
  navigateTo('/checkout/finish')
}

Reference Files

  • Context & session management: Headers, context token lifecycle, GET/PATCH /context, available languages/currencies/countries/payment methods/shipping methods
  • Cart operations: Add/update/remove line items, promotion codes, cart structure, calculation pipeline
  • Checkout & payment: Order creation, handle-payment flow, sync vs async payments, payment retry, order cancellation
  • Account management: Registration (regular + guest + double opt-in), login/logout, profile, addresses, password recovery, order history, wishlist, newsletter

Common Patterns

API Client Wrapper

Create a typed wrapper for Store API calls:

async function storeApi<T>(
  endpoint: string,
  body?: Record<string, unknown>,
  method: string = 'POST'
): Promise<T> {
  const contextToken = getContextToken() // from cookie/storage

  const response = await fetch(`${SHOPWARE_URL}/store-api${endpoint}`, {
    method,
    headers: {
      'Content-Type': 'application/json',
      'sw-access-key': SW_ACCESS_KEY,
      ...(contextToken && { 'sw-context-token': contextToken }),
    },
    body: body ? JSON.stringify(body) : undefined,
  })

  // Always persist the (potentially new) context token
  const newToken = response.headers.get('sw-context-token')
  if (newToken) setContextToken(newToken)

  if (!response.ok) {
    const error = await response.json()
    throw new StoreApiError(error)
  }

  return response.json()
}

Error Response Shape

Store API errors follow this structure:

{
  "errors": [
    {
      "status": "400",
      "code": "CHECKOUT__CART_PRODUCT_NOT_FOUND",
      "title": "Not Found",
      "detail": "Product not found",
      "meta": { "parameters": { "productId": "..." } }
    }
  ]
}

Handle errors by checking errors[].code. Common codes:

Code Meaning
CHECKOUT__CART_PRODUCT_NOT_FOUND Product ID doesn't exist
CHECKOUT__CUSTOMER_NOT_LOGGED_IN Endpoint requires authentication
CHECKOUT__ORDER_PAYMENT_METHOD_NOT_CHANGEABLE Payment can't be changed
VIOLATION::* Validation errors (missing fields, invalid format)

Criteria Object (Filtering & Pagination)

Many list endpoints accept a criteria body:

{
  "limit": 10,
  "page": 1,
  "sort": [{ "field": "createdAt", "order": "DESC" }],
  "filter": [
    { "type": "equals", "field": "active", "value": true }
  ],
  "associations": {
    "stateMachineState": {},
    "deliveries": {}
  }
}

Associations

Load related entities by specifying associations in the request body. These can be nested:

{
  "associations": {
    "transactions": {
      "associations": {
        "stateMachineState": {}
      }
    }
  }
}
Weekly Installs
4
Repository
frontic/skills
First Seen
Feb 27, 2026
Installed on
opencode4
gemini-cli4
github-copilot4
codex4
kimi-cli4
amp4