### Install ngrok and Start Local Webhook Server (Bash) Source: https://quickbutik.dev/webhooks/setup This snippet demonstrates how to install ngrok globally using npm and start a local Node.js webhook server. It's essential for exposing your local development environment to external services like Quickbutik for testing. ```bash # Install ngrok npm install -g ngrok # Start your local webhook server node webhook-server.js # In another terminal, expose your local server ngrok http 3000 # Copy the ngrok URL to your Quickbutik webhook settings # Example: https://abc123.ngrok.io/webhooks/quickbutik ``` -------------------------------- ### Quick Start Examples Source: https://quickbutik.dev/api-v1/authentication Examples of how to authenticate requests using Basic Authentication in various programming languages. ```APIDOC ## Quick Start ```bash cURL theme={null} curl https://api.quickbutik.com/v1/orders \ -u your_api_key:your_api_key ``` ```javascript Node.js theme={null} const apiKey = 'your_api_key'; const credentials = Buffer.from(`${apiKey}:${apiKey}`).toString('base64'); fetch('https://api.quickbutik.com/v1/orders', { headers: { 'Authorization': `Basic ${credentials}` } }); ``` ```python Python theme={null} import requests import base64 api_key = 'your_api_key' credentials = base64.b64encode(f'{api_key}:{api_key}'.encode()).decode() response = requests.get( 'https://api.quickbutik.com/v1/orders', headers={'Authorization': f'Basic {credentials}'} ) ``` ```php PHP theme={null} ``` ``` -------------------------------- ### Products Count Example Source: https://quickbutik.dev/api-v1/introduction Example of how to fetch the count of products using curl. ```APIDOC ## GET /products/count ### Description Fetches the total number of products in your store. ### Method GET ### Endpoint /products/count ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```bash curl https://api.quickbutik.com/v1/products/count \ -u your_api_key:your_api_key ``` ### Response #### Success Response (200) - **count** (string) - The total number of products. #### Response Example ```json { "count": "42" } ``` ``` -------------------------------- ### Bash: Setting up ngrok for Local Webhook Testing Source: https://quickbutik.dev/webhooks/introduction Provides instructions for setting up ngrok to expose a local development server to the internet for testing webhooks. This involves installing ngrok, starting a local server, and then using ngrok to create a public URL. ```bash # Install ngrok npm install -g ngrok # Start your webhook server node webhook-server.js # In another terminal, expose your local server ngrok http 3000 # Use the ngrok URL in your Quickbutik webhook settings # Example: https://abc123.ngrok.io/webhooks/quickbutik ``` -------------------------------- ### Example Authorization Header Construction Source: https://quickbutik.dev/api-v1/authentication Step-by-step example of constructing the Authorization header using an example API key. ```APIDOC ## Example Let's say your API key is `sk_live_abc123`. Here's how you'd construct the Authorization header: ```text Step 1: Format theme={null} sk_live_abc123:sk_live_abc123 ``` ```text Step 2: Base64 encode theme={null} c2tfbGl2ZV9hYmMxMjM6c2tfbGl2ZV9hYmMxMjM= ``` ```text Step 3: Authorization header theme={null} Authorization: Basic c2tfbGl2ZV9hYmMxMjM6c2tfbGl2ZV9hYmMxMjM= ``` ``` -------------------------------- ### Dockerfile for Production Webhook Server Source: https://quickbutik.dev/webhooks/setup A Dockerfile to containerize the Node.js webhook server. It sets up a production environment using Node.js 18 Alpine, installs dependencies, copies the application code, creates a non-root user for security, and defines a health check. ```dockerfile FROM node:18-alpine WORKDIR /app # Install dependencies COPY package*.json ./ RUN npm ci --only=production # Copy application COPY . . # Create non-root user RUN addgroup -g 1001 -S webhook RUN adduser -S webhook -u 1001 # Security RUN chown -R webhook:webhook /app USER webhook # Health check HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD curl -f http://localhost:3000/health || exit 1 EXPOSE 3000 CMD ["node", "webhook-server.js"] ``` -------------------------------- ### Basic Local Webhook Server with Express (JavaScript) Source: https://quickbutik.dev/webhooks/setup A simple Express.js server setup to receive and log incoming webhook events from Quickbutik. It listens on port 3000 and responds with a 200 OK status. This is suitable for basic local testing. ```javascript const express = require('express'); const app = express(); app.get('/webhooks/quickbutik', (req, res) => { console.log('Webhook received:', { event_type: req.query.event_type, order_id: req.query.order_id, product_id: req.query.product_id, timestamp: new Date().toISOString(), ip: req.ip, headers: req.headers }); res.status(200).send('OK'); }); app.listen(3000, () => { console.log('Webhook server listening on port 3000'); }); ``` -------------------------------- ### GET /orders Source: https://quickbutik.dev/api-v1/quickstart-tutorial Retrieves a list of orders. Supports query parameters for filtering and pagination. ```APIDOC ## GET /orders ### Description Retrieves a list of orders. Supports query parameters for filtering and pagination. ### Method GET ### Endpoint /orders ### Query Parameters - **limit** (integer) - Optional - The maximum number of orders to return. - **offset** (integer) - Optional - The number of orders to skip before returning results. - **status** (string) - Optional - Filter orders by their status (e.g., 'pending', 'shipped'). ### Request Example ```http GET /v1/orders?limit=10&status=pending ``` ### Response #### Success Response (200) - **orders** (array) - An array of order objects. - **order_id** (integer) - The unique identifier for the order. - **customer_name** (string) - The name of the customer. - **status** (string) - The current status of the order. - **total_price** (number) - The total price of the order. #### Response Example ```json { "orders": [ { "order_id": 12345, "customer_name": "John Doe", "status": "pending", "total_price": 99.99 }, { "order_id": 12346, "customer_name": "Jane Smith", "status": "shipped", "total_price": 45.50 } ] } ``` ``` -------------------------------- ### Complete Category Template Example (Mustache) Source: https://quickbutik.dev/theme-development/pages/category This comprehensive Mustache template provides a full example of a category page structure, including breadcrumbs, category title, description1, and a section for additional information (description2). It serves as a blueprint for creating detailed category pages. ```mustache

{{category.name}}

{{#category.description1}}
{{&category.description1}}
{{/category.description1}}
{{#category.description2}}

{{#lang}}Additional Information{{/lang}}

{{&category.description2}}
{{/category.description2}}
``` -------------------------------- ### GET /v1/orders Source: https://quickbutik.dev/api-v1/quickstart-tutorial Retrieves a list of recent orders. Supports filtering by limit and including detailed information. ```APIDOC ## GET /v1/orders ### Description Retrieves a list of recent orders. Supports filtering by limit and including detailed information. ### Method GET ### Endpoint /v1/orders ### Query Parameters - **limit** (integer) - Optional - The maximum number of orders to return. - **include_details** (boolean) - Optional - Whether to include detailed information for each order. ### Request Example ```bash curl "https://api.quickbutik.com/v1/orders?limit=5&include_details=true" \ -u your_api_key:your_api_key \ -H "Content-Type: application/json" ``` ### Response #### Success Response (200) - **order_id** (string) - The unique identifier for the order. - **date_created** (string) - The timestamp when the order was created. - **total_amount** (string) - The total amount of the order. - **status** (string) - The current status of the order. #### Response Example ```json [ { "order_id": "12345", "date_created": "2025-01-29 11:35:39", "total_amount": "148.95", "status": "1" } ] ``` ``` -------------------------------- ### Basic Authentication - Header Example Source: https://quickbutik.dev/api-v1/products/create-products Provides an example of the 'Authorization' header format using Base64 encoded API key credentials for Basic Authentication. ```http Authorization: Basic c2tfbGl2ZV9hYmMxMjM6c2tfbGl2ZV9hYmMxMjM= ``` -------------------------------- ### Basic Authentication Source: https://quickbutik.dev/api-v1/products/get-products Explains how to use Basic Authentication with API Keys for authenticating requests to the Quickbutik API. It includes the format, encoding process, and a cURL example. ```APIDOC ## Basic Authentication ### Description Details the process for authenticating API requests using Basic Authentication with API Keys. This method requires formatting your API key as credentials, Base64 encoding it, and including it in the `Authorization` header. ### Method Basic Auth ### Security Scheme Details - **Type**: `http` - **Scheme**: `basic` ### How it works: 1. Format your credentials as `api_key:api_key` (using the SAME API key for both username and password). 2. Base64 encode the formatted string. 3. Include in the `Authorization` header as: `Authorization: Basic ENCODED_STRING`. ### Example: - API Key: `sk_live_abc123` - Formatted: `sk_live_abc123:sk_live_abc123` - Base64 Encoded: `c2tfbGl2ZV9hYmMxMjM6c2tfbGl2ZV9hYmMxMjM=` - Header: `Authorization: Basic c2tfbGl2ZV9hYmMxMjM6c2tfbGl2ZV9hYmMxMjM=` ### cURL Example: ```bash curl https://api.quickbutik.com/v1/orders -u your_api_key:your_api_key ``` **Note**: All API requests must be made over HTTPS. Requests made over HTTP will be rejected. API keys can be generated in the Quickbutik Control Panel under Settings → API. ``` -------------------------------- ### Authenticate and Fetch Product Count Source: https://quickbutik.dev/api-v1/quickstart-tutorial Demonstrates how to authenticate with the Quickbutik API using an API key and fetch the total product count. Includes examples for cURL, Node.js, and Python. Requires a Quickbutik store and API key. ```bash # Replace 'your_api_key' with your actual API key curl https://api.quickbutik.com/v1/products/count \ -u your_api_key:your_api_key \ -H "Content-Type: application/json" ``` ```javascript const fetch = require('node-fetch'); // or use built-in fetch in Node 18+ const apiKey = 'your_api_key'; const credentials = Buffer.from(`${apiKey}:${apiKey}`).toString('base64'); async function getProductCount() { try { const response = await fetch('https://api.quickbutik.com/v1/products/count', { headers: { 'Authorization': `Basic ${credentials}`, 'Content-Type': 'application/json' } }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } const data = await response.json(); console.log('Product count:', data.count); return data; } catch (error) { console.error('Error:', error.message); } } getProductCount(); ``` ```python import requests import base64 import json api_key = 'your_api_key' credentials = base64.b64encode(f'{api_key}:{api_key}'.encode()).decode() def get_product_count(): try: response = requests.get( 'https://api.quickbutik.com/v1/products/count', headers={ 'Authorization': f'Basic {credentials}', 'Content-Type': 'application/json' } ) response.raise_for_status() data = response.json() print(f"Product count: {data['count']}") return data except requests.exceptions.RequestException as error: print(f"Error: {error}") get_product_count() ``` -------------------------------- ### Fetch Product Count using cURL Source: https://quickbutik.dev/api-v1/introduction This snippet demonstrates how to fetch the total count of products in your Quickbutik store using a cURL command. It requires your API key for authentication and targets the '/products/count' endpoint. This is a basic example to test your API setup. ```bash curl https://api.quickbutik.com/v1/products/count \ -u your_api_key:your_api_key ``` -------------------------------- ### Example of Base64 Encoding for Authentication Header Source: https://quickbutik.dev/api-v1/authentication Illustrates the step-by-step process of creating the Authorization header value for Basic Authentication. It shows formatting the API key, base64 encoding it, and constructing the final header. ```text sk_live_abc123:sk_live_abc123 ``` ```text c2tfbGl2ZV9hYmMxMjM6c2tfbGl2ZV9hYmMxMjM= ``` ```text Authorization: Basic c2tfbGl2ZV9hYmMxMjM6c2tfbGl2ZV9hYmMxMjM= ``` -------------------------------- ### Robust Production Webhook Server with Express (JavaScript) Source: https://quickbutik.dev/webhooks/setup An advanced Express.js webhook server for production. It includes security middleware (helmet, rate limiting), a health check endpoint, and asynchronous processing by queuing events. This setup enhances reliability and security. ```javascript const express = require('express'); const rateLimit = require('express-rate-limit'); const helmet = require('helmet'); const app = express(); // Security middleware app.use(helmet()); // Rate limiting const webhookLimiter = rateLimit({ windowMs: 1 * 60 * 1000, // 1 minute max: 100, // limit each IP to 100 requests per windowMs message: 'Too many webhook requests from this IP', standardHeaders: true, legacyHeaders: false, }); app.use('/webhooks', webhookLimiter); // Health check endpoint app.get('/health', (req, res) => { res.status(200).json({ status: 'healthy', timestamp: new Date().toISOString() }); }); // Webhook endpoint app.get('/webhooks/quickbutik', async (req, res) => { const { event_type, order_id, product_id } = req.query; // Log webhook receipt console.log(`Webhook received: ${event_type}`, { order_id, product_id, timestamp: new Date().toISOString(), ip: req.ip }); // Respond immediately res.status(200).send('OK'); try { // Add to processing queue await addToQueue({ event_type, order_id, product_id, received_at: new Date().toISOString() }); } catch (error) { console.error('Failed to queue webhook:', error); // Send alert but don't fail the webhook response await sendAlert({ type: 'webhook_queue_error', event_type, error: error.message }); } }); async function addToQueue(webhookData) { // Add to Redis queue, SQS, or your preferred queue system // This ensures webhook processing doesn't block the response if (process.env.REDIS_URL) { const redis = require('redis'); const client = redis.createClient({ url: process.env.REDIS_URL }); await client.lPush('webhook_queue', JSON.stringify(webhookData)); } } const PORT = process.env.PORT || 3000; app.listen(PORT, () => { console.log(`Webhook server running on port ${PORT}`); }); ``` -------------------------------- ### Example Success Response Source: https://quickbutik.dev/api-v1/introduction This JSON object represents a successful API response. It typically contains the requested data or a summary, such as the count of products. The structure is consistent across successful requests. ```json { "count": "42" } ``` -------------------------------- ### Dockerfile for Production Deployment (Dockerfile) Source: https://quickbutik.dev/api-v1/guides/order-sync-tutorial A Dockerfile to build a production-ready Node.js application. It sets up a working directory, installs production dependencies, copies application code, creates a non-root user for security, exposes port 3000, and includes a health check. ```dockerfile FROM node:18-alpine WORKDIR /app # Copy package files COPY package*.json ./ RUN npm ci --only=production # Copy application code COPY . . # Create non-root user RUN addgroup -g 1001 -S nodejs RUN adduser -S nodejs -u 1001 # Change ownership and switch to non-root user RUN chown -R nodejs:nodejs /app USER nodejs EXPOSE 3000 # Health check HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD curl -f http://localhost:3000/health || exit 1 CMD ["node", "server.js"] ``` -------------------------------- ### Fetch and Sync Orders with Quickbutik API (Python) Source: https://quickbutik.dev/api-v1/guides/order-sync-tutorial This Python snippet shows how to fetch order details from Quickbutik and prepare them for synchronization. It uses asyncio and aiohttp for asynchronous operations and includes a retry mechanism for API calls, similar to the Node.js example. ```python import asyncio import aiohttp import json from typing import Dict, List, Optional from quickbutik_api import QuickbutikAPI # From previous tutorial class OrderSyncService: def __init__(self, api_key: str): self.api = QuickbutikAPI(api_key) self.retry_attempts = 3 self.retry_delay = 1 # seconds async def handle_new_order(self, order_id: str): try: # Fetch complete order details orders = await self.retry_api_call( lambda: self.api.get_orders( order_id=order_id, include_details=True, apps_load=True ) ) if not orders: raise Exception(f'Order {order_id} not found') order = orders[0] ``` -------------------------------- ### Test Webhook Endpoint with Curl Source: https://quickbutik.dev/webhooks/setup A command-line utility to test if your webhook endpoint is publicly accessible and receiving requests. This helps in diagnosing connectivity issues and verifying the endpoint's basic functionality. ```bash curl "https://your-domain.com/webhooks/quickbutik?event_type=test" ``` -------------------------------- ### Example Error Response Source: https://quickbutik.dev/api-v1/introduction This JSON object illustrates an error response from the Quickbutik API. It includes an error code and a descriptive message, helping developers understand and resolve issues. This format is used for various error conditions. ```json { "code": 404, "error": "Resource not found" } ``` -------------------------------- ### POST /v1/products Source: https://quickbutik.dev/api-v1/products/create-products This endpoint allows you to create new products and add them to your Quickbutik store. You can specify details like SKU, title, description, price, stock, and more. ```APIDOC ## POST /v1/products ### Description Create and add products to store. ### Method POST ### Endpoint /v1/products ### Parameters #### Request Body - **sku** (string) - Optional - Article Number (SKU) - **title** (string) - Required - Product title - **description** (string) - Optional - Product description. Accepts HTML - **price** (integer) - Optional - Price - **before_price** (integer) - Optional - Compare price - **purchase_price** (integer) - Optional - Purchase price (excl. vat) - **tax_rate** (integer) - Optional - VAT percent (%) - **weight** (number) - Optional - Weight (in grams) - **stock** (integer) - Optional - Stock quantity - **disable_minusqty** (string) - Optional - Stock: Disable minus quantity? - **gtin** (string) - Optional - EAN-number / GTN (Global Trade Item Number) - **headcategory_id** (integer) - Optional - Optional: Category id if a product should be placed into a specific category - **headcategory_name** (string) - Optional - Optional: Category name if product should be placed into a new category - **visible** (integer) - Optional - Visibility in store - **images** (object) - Optional - Product images - **metadata** (object) - Optional - Custom metadata for the product - **permanent_redirect_from_url** (string) - Optional - URL to create a permanent redirect from (for SEO purposes) - **skipIfDuplicate** (boolean) - Optional - Skip creation if product with same SKU already exists - **variants** (object) - Optional - Product variants configuration - **sync** (array) - Optional - Variants to sync (replaces all existing variants) - **variant_option1_name** (string) - Required - First variant option name (e.g., Color, Size) - **variant_option1_value** (string) - Required - First variant option value - **variant_option2_name** (string) - Optional - Second variant option name - **variant_option2_value** (string) - Optional - Second variant option value ### Request Example ```json { "sku": "T-SHIRT123", "title": "My white tee!", "description": "

This is so so cool! Heee

", "price": 299, "before_price": 399, "purchase_price": 69, "tax_rate": 25, "weight": 400, "stock": 1, "disable_minusqty": "1", "gtin": "1234567890123", "headcategory_id": 10, "headcategory_name": "T-shirts", "visible": 1, "images": {}, "metadata": { "key1": "value1" }, "permanent_redirect_from_url": "http://example.com/old-product", "skipIfDuplicate": false, "variants": { "sync": [ { "variant_option1_name": "Color", "variant_option1_value": "Red", "variant_option2_name": "Size", "variant_option2_value": "Large" } ] } } ``` ### Response #### Success Response (200) - **id** (integer) - Product ID - **sku** (string) - Article Number (SKU) - **title** (string) - Product title - **description** (string) - Product description. Accepts HTML - **price** (integer) - Price - **before_price** (integer) - Compare price - **purchase_price** (integer) - Purchase price (excl. vat) - **tax_rate** (integer) - VAT percent (%) - **weight** (number) - Weight (in grams) - **stock** (integer) - Stock quantity - **disable_minusqty** (string) - Stock: Disable minus quantity? - **gtin** (string) - EAN-number / GTN (Global Trade Item Number) - **headcategory_id** (integer) - Category ID - **headcategory_name** (string) - Category name - **visible** (integer) - Visibility in store - **images** (object) - Product images - **metadata** (object) - Custom metadata for the product - **permanent_redirect_from_url** (string) - URL to create a permanent redirect from (for SEO purposes) - **created_at** (string) - Creation timestamp - **updated_at** (string) - Update timestamp #### Response Example ```json { "id": 1, "sku": "T-SHIRT123", "title": "My white tee!", "description": "

This is so so cool! Heee

", "price": 299, "before_price": 399, "purchase_price": 69, "tax_rate": 25, "weight": 400, "stock": 1, "disable_minusqty": "1", "gtin": "1234567890123", "headcategory_id": 10, "headcategory_name": "T-shirts", "visible": 1, "images": {}, "metadata": { "key1": "value1" }, "permanent_redirect_from_url": "http://example.com/old-product", "created_at": "2023-01-01T12:00:00Z", "updated_at": "2023-01-01T12:00:00Z" } ``` ``` -------------------------------- ### Set Up Quickbutik Webhook Endpoint (Express.js & Flask) Source: https://quickbutik.dev/api-v1/guides/order-sync-tutorial This snippet demonstrates how to create a webhook endpoint to receive order notifications from Quickbutik. It includes immediate acknowledgment of the webhook and asynchronous processing of the order events. Ensure your endpoint responds within 10 seconds to prevent retries. Dependencies include Express.js for Node.js or Flask for Python. ```javascript const express = require('express'); const crypto = require('crypto'); const app = express(); app.use(express.json()); app.use(express.urlencoded({ extended: true })); // Webhook endpoint for order notifications app.post('/webhooks/quickbutik', async (req, res) => { try { const { event_type, order_id } = req.query; console.log(`Received webhook: ${event_type} for order ${order_id}`); // Acknowledge webhook immediately res.status(200).send('OK'); // Process webhook asynchronously await processOrderWebhook(event_type, order_id); } catch (error) { console.error('Webhook processing error:', error); res.status(500).send('Error processing webhook'); } }); async function processOrderWebhook(eventType, orderId) { switch (eventType) { case 'order.new': await handleNewOrder(orderId); break; case 'order.done': await handleOrderShipped(orderId); break; case 'order.cancelled': await handleOrderCancelled(orderId); break; default: console.log(`Unhandled event type: ${eventType}`); } } app.listen(3000, () => { console.log('Webhook server running on port 3000'); }); ``` ```python from flask import Flask, request, jsonify import asyncio import logging app = Flask(__name__) logging.basicConfig(level=logging.INFO) @app.route('/webhooks/quickbutik', methods=['POST']) def quickbutik_webhook(): try: event_type = request.args.get('event_type') order_id = request.args.get('order_id') app.logger.info(f'Received webhook: {event_type} for order {order_id}') # Acknowledge webhook immediately response = jsonify({'status': 'received'}) # Process webhook asynchronously (in production, use a task queue) asyncio.create_task(process_order_webhook(event_type, order_id)) return response, 200 except Exception as error: app.logger.error(f'Webhook processing error: {error}') return jsonify({'error': 'Error processing webhook'}), 500 async def process_order_webhook(event_type, order_id): try: if event_type == 'order.new': await handle_new_order(order_id) elif event_type == 'order.done': await handle_order_shipped(order_id) elif event_type == 'order.cancelled': await handle_order_cancelled(order_id) else: app.logger.info(f'Unhandled event type: {event_type}') except Exception as error: app.logger.error(f'Error processing webhook: {error}') if __name__ == '__main__': app.run(debug=True, port=3000) ``` -------------------------------- ### GET /v1/categories Source: https://quickbutik.dev/api-v1/categories/get-categories Fetch store categories. Optionally, filter by a specific category ID. ```APIDOC ## GET /v1/categories ### Description Fetch store categories. Optionally, filter by a specific category ID. ### Method GET ### Endpoint /v1/categories ### Parameters #### Query Parameters - **category_id** (string) - Optional - Optional. Enter if you would like to fetch data from a specific category_id ### Request Example (No request body for GET requests) ### Response #### Success Response (200) - **results** (Category) - Contains category information. #### Response Example { "results": [ { "category_id": 14, "uri": "sulor", "url": "/herr/skor/sulor", "name": "Sulor", "name_path": "Herr > Skor > Sulor", "description1": null, "description2": null, "parent_id": 13 } ] } #### Error Response (401) - **code** (integer) - Error code. - **error** (string) - Error message. #### Error Response Example { "code": 401, "error": "Unauthorized - Invalid or missing authentication" } #### Error Response (404) - **code** (integer) - Error code. - **error** (string) - Error message. #### Error Response Example { "code": 404, "error": "Resource not found" } ``` -------------------------------- ### Fetch and Sync Orders with Quickbutik API (Node.js) Source: https://quickbutik.dev/api-v1/guides/order-sync-tutorial This Node.js snippet demonstrates how to fetch complete order details from Quickbutik, validate the data, and sync it to an external system. It includes a robust retry mechanism for API calls and handles potential synchronization failures. ```javascript const QuickbutikAPI = require('./quickbutik-api'); // From our previous tutorial class OrderSyncService { constructor(apiKey) { this.api = new QuickbutikAPI(apiKey); this.retryAttempts = 3; this.retryDelay = 1000; // 1 second } async handleNewOrder(orderId) { try { // Fetch complete order details const orders = await this.retryAPICall(() => this.api.getOrders({ order_id: orderId, include_details: true, apps_load: true }) ); if (!orders || orders.length === 0) { throw new Error(`Order ${orderId} not found`); } const order = orders[0]; // Validate order data if (!this.validateOrder(order)) { throw new Error(`Invalid order data for order ${orderId}`); } // Sync to external system await this.syncOrderToExternalSystem(order); // Log success console.log(`Successfully synced order ${orderId} to external system`); } catch (error) { console.error(`Failed to process new order ${orderId}:`, error); // Add to retry queue or send alert await this.handleOrderSyncFailure(orderId, error); } } async retryAPICall(apiCall, attempt = 1) { try { return await apiCall(); } catch (error) { if (attempt < this.retryAttempts) { console.log(`API call failed, retrying in ${this.retryDelay}ms (attempt ${attempt}/${this.retryAttempts})`); await new Promise(resolve => setTimeout(resolve, this.retryDelay * attempt)); return this.retryAPICall(apiCall, attempt + 1); } throw error; } } validateOrder(order) { return order.order_id && order.total_amount && order.customer && order.customer.email; } async syncOrderToExternalSystem(order) { // Transform Quickbutik order to your system's format const externalOrder = this.transformOrder(order); // Make API call to your external system const response = await fetch('https://your-system.com/api/orders', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${process.env.EXTERNAL_API_TOKEN}` }, body: JSON.stringify(externalOrder) }); if (!response.ok) { throw new Error(`External API error: ${response.status} ${response.statusText}`); } return response.json(); } transformOrder(quickbutikOrder) { return { external_order_id: quickbutikOrder.order_id, customer_email: quickbutikOrder.customer.email, total_amount: parseFloat(quickbutikOrder.total_amount), currency: quickbutikOrder.payment?.currency || 'SEK', items: quickbutikOrder.products?.map(product => ({ sku: product.sku, quantity: product.qty || 1, price: parseFloat(product.price || 0) })) || [], shipping_address: quickbutikOrder.customer.shipping_details, billing_address: quickbutikOrder.customer.billing_details, created_at: quickbutikOrder.date_created }; } async handleOrderSyncFailure(orderId, error) { // In production, you might: // 1. Add to a retry queue (Redis, SQS, etc.) // 2. Send alerts to monitoring system // 3. Log to error tracking service console.error(`Order sync failed for ${orderId}:`, error.message); // Example: Add to retry queue // await this.addToRetryQueue({ orderId, error: error.message, timestamp: new Date() }); } } // Usage const orderSync = new OrderSyncService(process.env.QUICKBUTIK_API_KEY); async function handleNewOrder(orderId) { await orderSync.handleNewOrder(orderId); } ``` -------------------------------- ### GET /v1/metadata/{scope}/{id} Source: https://quickbutik.dev/api-v1/metadata/get-metadata Retrieves metadata for a specified scope (order, product, or customer) and its corresponding ID. ```APIDOC ## GET /v1/metadata/{scope}/{id} ### Description Retrieves metadata for a specified scope (order, product, or customer) and its corresponding ID. ### Method GET ### Endpoint /v1/metadata/{scope}/{id} ### Parameters #### Path Parameters - **scope** (string) - Required - Enum: order, product, customer. The scope for which to retrieve metadata. - **id** (string) - Required - The ID of the selected scope. For example, when scope is 'product' and id is '1', metadata for product with ID '1' will be returned. ### Request Example ```json { "example": "Not applicable for GET requests" } ``` ### Response #### Success Response (200) - **additionalProperties** (object) - Key-value pairs of metadata. - **type** (string) - The data type of the metadata value. - **description** (string) - A description of the metadata value. #### Response Example ```json { "example": "{\"meta_key_1\": \"meta_value_1\", \"meta_key_2\": \"meta_value_2\"}" } ``` #### Error Responses - **400** - Bad Request: Indicates an issue with the request parameters. - **401** - Unauthorized: Indicates invalid or missing authentication credentials. - **404** - Not Found: Indicates that the requested resource could not be found. ``` -------------------------------- ### Mustache Variable Output Examples Source: https://quickbutik.dev/theme-development/mustache-basics Demonstrates basic variable output in Mustache templates, including product and store information. This is fundamental for displaying dynamic content on Quickbutik storefronts. ```mustache

{{product.title}}

Price: {{product.price}} {{product.currency}}

SKU: {{product.sku}}

``` -------------------------------- ### Get Metadata by Scope and ID (OpenAPI) Source: https://quickbutik.dev/api-v1/metadata/get-metadata This OpenAPI specification defines the GET /v1/metadata/{scope}/{id} endpoint for retrieving metadata. It requires 'scope' (order, product, customer) and 'id' as path parameters. Successful requests return metadata in JSON format, while errors return standardized error responses. ```yaml openapi: 3.1.0 info: title: Quickbutik API version: 1.0.0 description: >- Use the Quickbutik API to access and manage stores, products, orders, and more. contact: name: Quickbutik API Support url: https://quickbutik.com/support license: name: Proprietary x-fiddle-import-file: true servers: - url: https://api.quickbutik.com description: Production server security: - BasicAuth: [] tags: - name: Orders description: Order management operations - name: Products description: Product catalog management - name: Categories description: Product category management - name: Payment Methods description: Available payment methods - name: Shipping Methods description: Available shipping methods - name: Metadata description: Custom metadata management - name: Scripts description: Storefront script management paths: /v1/metadata/{scope}/{id}: get: tags: - Metadata summary: Get metadata description: Get metadata for selected scope and id operationId: get-metadata parameters: - $ref: '#/components/parameters/MetadataScope' - $ref: '#/components/parameters/MetadataId' responses: '200': $ref: '#/components/responses/MetadataSuccess' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' components: parameters: MetadataScope: name: scope in: path required: true schema: type: string enum: - order - product - customer description: order|product|customer MetadataId: name: id in: path required: true schema: type: string description: >- Id of the selected scope. E.g when scope is product and id is 1, metadata for product with id 1 will be returned responses: MetadataSuccess: description: Metadata retrieved successfully content: application/json: schema: type: object additionalProperties: type: string description: Key-value pairs of metadata BadRequest: description: Bad Request content: application/json: schema: $ref: '#/components/schemas/Error' Unauthorized: description: Unauthorized - Invalid or missing authentication content: application/json: schema: $ref: '#/components/schemas/Error' NotFound: description: Resource not found content: application/json: schema: $ref: '#/components/schemas/Error' schemas: Error: type: object properties: code: type: integer example: 404 error: type: string example: Resource not found securitySchemes: BasicAuth: type: http scheme: basic description: > **Basic Authentication with API Keys** The Quickbutik API uses Basic Authentication where you use your API key as both the username and password. **How it works:** 1. Format your credentials as `api_key:api_key` (using the SAME API key for both username and password) 2. Base64 encode the formatted string 3. Include in the Authorization header as: `Authorization: Basic ENCODED_STRING` **Example:** - API Key: `sk_live_abc123` - Formatted: `sk_live_abc123:sk_live_abc123` - Base64 Encoded: `c2tfbGl2ZV9hYmMxMjM6c2tfbGl2ZV9hYmMxMjM=` - Header: `Authorization: Basic c2tfbGl2ZV9hYmMxMjM6c2tfbGl2ZV9hYmMxMjM=` **cURL Example:** ```bash curl https://api.quickbutik.com/v1/orders -u your_api_key:your_api_key ``` All API requests must be made over HTTPS. Requests made over HTTP will be rejected. API keys can be generated in the Quickbutik Control Panel under Settings → API. ``` -------------------------------- ### Generic Static Page Example (Mustache) Source: https://quickbutik.dev/theme-development/pages/static A comprehensive HTML template for rendering generic static pages. It includes basic SEO meta tags, header, main content area with breadcrumbs, and a footer. This template uses Mustache for dynamic content. ```mustache {{page.title}} - {{shop.name}}
{{&page.content}}
```