API v1.1

QuickShopPublic API

Full REST API for integrating with QuickShop stores.
Orders, products, inventory, customers, Storefront and mobile - all available via API.

Base URL
https://my-quickshop.com/api/v1

Quick start

1

Create an API key

In the merchant admin go to Settings → API Keys and create a new key with the scopes you need.

2

Add the auth header

Every request requires an X-API-Key header containing your key.

3

Start building

Read the reference below and start shipping integrations.

Example Request
curl -X GET "https://my-quickshop.com/api/v1/orders" \
  -H "X-API-Key: qs_live_xxxxxxxxxxxxxxxxxxxx"

Authentication

Every call requires an API key

Available scopes

orders:read
Read orders
orders:write
Update orders
products:read
Read products and categories
products:write
Edit products and categories
customers:read
Read customers
inventory:read
Read inventory
inventory:write
Update inventory
discounts:read
Read discounts and coupons
discounts:write
Manage discounts and coupons
analytics:read
Read analytics
webhooks:read
Read webhooks
webhooks:write
Manage webhooks
storefront:read
Storefront API access (products, categories, config)
customer:read
Customer data access (orders, addresses, wishlist)
customer:write
Update customer profile and wishlist
mobile:write
Register devices and notifications

Rate limiting

  • 100 requests/minute per API key
  • • Header X-RateLimit-Remaining - calls left in the current window
  • • Header X-RateLimit-Reset - when the window resets

Common errors

401unauthorized- Missing or invalid API key
403forbidden- Missing scope for this resource
404not_found- Resource not found
400invalid_request- Bad request payload
429rate_limited- Rate limit exceeded

Endpoints

Orders

GET/api/v1/ordersList orders
GET/api/v1/orders/{id}Get order details
PATCH/api/v1/orders/{id}Update order
POST/api/v1/orders/{id}/edit-itemsEdit order line items
POST/api/v1/orders/{id}/fulfillMark order as fulfilled
POST/api/v1/orders/{id}/cancelCancel order

Products

GET/api/v1/productsList products
POST/api/v1/productsCreate product
GET/api/v1/products/{id}Get product details
PATCH/api/v1/products/{id}Update product

Categories

GET/api/v1/categoriesList categories
POST/api/v1/categoriesCreate category
GET/api/v1/categories/{id}Get category details
PATCH/api/v1/categories/{id}Update category
DELETE/api/v1/categories/{id}Delete category

Inventory

GET/api/v1/inventory/{id}Get inventory level
PATCH/api/v1/inventory/{id}Adjust inventory

Customers

GET/api/v1/customersList customers

Discounts

GET/api/v1/discountsList discounts and coupons
POST/api/v1/discountsCreate discount/coupon
GET/api/v1/discounts/{id}Get discount details
PATCH/api/v1/discounts/{id}Update discount
DELETE/api/v1/discounts/{id}Delete discount

Analytics

GET/api/v1/analyticsAggregated stats and reports

Webhooks

GET/api/v1/webhooksList webhooks
POST/api/v1/webhooksCreate webhook
GET/api/v1/webhooks/{id}Get webhook details
PATCH/api/v1/webhooks/{id}Update webhook
DELETE/api/v1/webhooks/{id}Delete webhook
GET/api/v1/webhooks/{id}/deliveriesDelivery history (status, response, errors)

Outbound webhook deliveries

What we POST to the URL configured via POST /api/v1/webhooks when an event fires in the store.

Body structure (JSON)

QuickShop sends a POST with Content-Type: application/json. The top-level field is always event (not type), along with a timestamp and a data object whose contents depend on the event type.

{
  "event": "order.created",
  "timestamp": "2026-04-23T12:00:00.000Z",
  "data": {
    /* fields per event type - see table below */
  }
}

Headers

  • Content-Type: application/json
  • • Custom headers configured on the webhook are merged into the request.
  • • If a secret is configured, we also send X-Webhook-Signature: sha256=<hmac> (HMAC-SHA256 of the raw body using the secret - verify it on your end).
  • • Test deliveries (the “Test” button in the dashboard) include X-Webhook-Event: <event> and X-Webhook-Test: true, and the body has "test": true at the top level.

Integration testing: the Webhooks page in the merchant admin has a Test ▾ dropdown listing every event the webhook is subscribed to. Picking an event POSTs a synthetic payload that matches production exactly (including the HMAC signature) - so you can verify your endpoint, parser, and signature check without making a real sale. The only difference is the "test": true flag.

Delivery logs: GET /api/v1/webhooks/{id}/deliveries returns recent delivery attempts. Each entry includes: request_body (the exact JSON we POSTed), status_code, response_body, error, duration_ms, and event_type - so you can verify exactly what was sent without merchant dashboard access.

data fields per event (primary)

data is not the full REST model of the order or product - for full details (line items, addresses, etc.) call the API with your X-API-Key, e.g. GET /api/v1/orders/{id} once you have the order id.

eventprimary data fields
order.createdorderId, orderNumber, customerEmail, customerName, total, itemCount, couponCode (optional), timestamp
order.paidAll fields from order.created plus paymentMethod. Fired after a successful checkout, manual “Mark as paid” from the dashboard, or remaining-balance collection.
order.updatedorderId, orderNumber, changes (map: field{ before, after }), source (admin/api/system), timestamp. Fired on address, status, items, notes, or amount edits - inspect changes to see what moved.
order.cancelledorderId, orderNumber, customerEmail, customerName, cancelReason, timestamp
product.low_stockproductName, inventory
product.out_of_stockproductName, inventory (0)

You can subscribe to all events with *in the webhook's events array (via the admin UI or the API).

Verifying the signature

Compute HMAC-SHA256 over the raw request body using the webhook secret. Compare it (constant-time) against the value in X-Webhook-Signature after the sha256= prefix.

// Node.js (Express)
import crypto from 'node:crypto';

app.post('/quickshop/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const sig = req.header('X-Webhook-Signature') || '';
  const expected = 'sha256=' + crypto
    .createHmac('sha256', process.env.QUICKSHOP_WEBHOOK_SECRET)
    .update(req.body)              // raw Buffer, NOT JSON.stringify
    .digest('hex');

  if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) {
    return res.status(401).end('bad signature');
  }

  const payload = JSON.parse(req.body.toString('utf8'));
  if (payload.test === true) {
    // synthetic test delivery - ack but skip side-effects
    return res.status(200).end();
  }

  switch (payload.event) {
    case 'order.paid':    /* ... */ break;
    case 'order.updated': /* inspect payload.data.changes */ break;
    case 'order.cancelled': /* ... */ break;
  }
  res.status(200).end();
});
NEW

Storefront & Mobile API

Public endpoints for the storefront and mobile apps. Customer authentication uses a Customer Session.

Storefront Config

GET/api/storefront/{slug}/configStore config (name, logo, colors, currency)
GET/api/storefront/{slug}/app-configMobile app config (JSON)
PUT/api/storefront/{slug}/app-configSave mobile config (Admin)

Storefront Products

GET/api/storefront/{slug}/productsProduct catalog (filter, sort, paginate)
GET/api/storefront/{slug}/products/{productSlug}Product details + variants + images

Storefront Categories

GET/api/storefront/{slug}/categoriesList categories (with product counts)

Customer Orders

GET/api/customer/ordersAuthenticated customer order history
GET/api/customer/orders/{orderNumber}Order details + shipment tracking

Customer Profile

PUT/api/customer/updateUpdate customer profile
GET/api/customer/addressesList saved addresses
POST/api/customer/addressesAdd address
DELETE/api/customer/addressesDelete address

Wishlist

GET/api/customer/wishlistGet wishlist
POST/api/customer/wishlistAdd to wishlist
PUT/api/customer/wishlistToggle (add/remove)
GET/api/customer/wishlist/{productId}Check if product is wishlisted

Mobile Devices

POST/api/mobile/device/registerRegister device for push notifications
GET/api/mobile/notifications/preferencesGet notification preferences
PUT/api/mobile/notifications/preferencesUpdate notification preferences

Customer auth on mobile

The Storefront API uses a Customer Session (email-OTP based) for authenticated customer endpoints. Public endpoints like config, products, and categories require no auth. Customer endpoints (customer/*) require a session token.

Code samples

Node.js
const API_KEY = 'qs_live_xxxx';
const BASE_URL = 'https://my-quickshop.com/api/v1';

async function getOrders() {
  const response = await fetch(`${BASE_URL}/orders`, {
    headers: {
      'X-API-Key': API_KEY,
    },
  });

  const { data, meta } = await response.json();
  return data;
}

async function updateInventory(productId, adjustment) {
  const response = await fetch(`${BASE_URL}/inventory/${productId}`, {
    method: 'PATCH',
    headers: {
      'X-API-Key': API_KEY,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      type: 'product',
      adjustment,
    }),
  });

  return response.json();
}
Python
import requests

API_KEY = 'qs_live_xxxx'
BASE_URL = 'https://my-quickshop.com/api/v1'
HEADERS = {'X-API-Key': API_KEY}

def get_orders(page=1, limit=50):
    response = requests.get(
        f'{BASE_URL}/orders',
        headers=HEADERS,
        params={'page': page, 'limit': limit}
    )
    return response.json()['data']

def update_order_status(order_id, status):
    response = requests.patch(
        f'{BASE_URL}/orders/{order_id}',
        headers=HEADERS,
        json={'status': status}
    )
    return response.json()

Create a product with images

POST /api/v1/products
// Create a new product, optionally downloading images to our CDN
const response = await fetch('https://my-quickshop.com/api/v1/products', {
  method: 'POST',
  headers: {
    'X-API-Key': API_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    name: "Sample product",
    slug: "sample-product",
    description: "Product description",
    price: "99.90",
    compare_price: "149.90",
    inventory: 100,
    track_inventory: true,
    category_ids: ["cat_123"],

    // Images - external URLs
    images: [
      { url: "https://example.com/image1.jpg", alt: "Primary image", is_primary: true },
      { url: "https://example.com/image2.jpg" }
    ],

    // download_images: true => download, convert to WebP, and re-host on Vercel Blob
    // download_images: false (default) => keep the URL as-is
    download_images: true
  })
});

// Response
{
  "success": true,
  "data": {
    "id": "prod_xxx",
    "name": "Sample product",
    "slug": "sample-product",
    "images": [
      { "id": "img_1", "url": "https://xxx.blob.vercel-storage.com/...", "is_primary": true }
    ]
  }
}

💡 With download_images: true, images are fetched, converted to WebP, and uploaded to Vercel Blob.
🎥 Video (media_type: "video") is stored as a URL - any public source works (CDN / R2 / YouTube etc.).

Edit order items

POST /api/v1/orders/{id}/edit-items
// Edit order items: add, remove, or change quantity
const response = await fetch(
  `${BASE_URL}/orders/${orderId}/edit-items`,
  {
    method: 'POST',
    headers: {
      'X-API-Key': API_KEY,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      // Change quantity of an existing item
      update_quantity: [
        { item_id: "order-item-uuid", new_quantity: 3 }
      ],

      // Add a new item to the order
      add: [
        {
          product_id: "product-uuid",
          variant_id: "variant-uuid",     // optional
          name: "Product Name",
          variant_title: "M / Red",       // optional
          quantity: 2,
          price: 49.90
        }
      ],

      // Remove items from the order
      remove: ["order-item-uuid-to-remove"]
    })
  }
);

// Response
{
  "data": {
    "id": "order-uuid",
    "order_number": 1042,
    "old_total": 199.60,
    "new_total": 249.50,
    "price_difference": 49.90,   // positive = charge more, negative = refund
    "subtotal": 259.50,
    "discount_amount": 10.00,    // stays frozen (not recalculated)
    "total": 249.50,
    "line_items": [
      { "id": "...", "name": "...", "quantity": 3, "price": 49.90, "total": 149.70 }
    ]
  }
}

Only unfulfilled orders can be edited. Discounts remain frozen - only item totals change.
Inventory is automatically adjusted (both product and variant levels).

Fetching products from the Storefront API

React Native / Expo
const STORE = 'my-store';
const BASE = 'https://my-quickshop.com/api';

// Fetch store config
const config = await fetch(
  `${BASE}/storefront/${STORE}/config`
).then(r => r.json());

// Fetch products with filters + paging
const products = await fetch(
  `${BASE}/storefront/${STORE}/products?` +
  `page=1&limit=20&sort=newest`
).then(r => r.json());

// Fetch a single product
const product = await fetch(
  `${BASE}/storefront/${STORE}/products/my-product`
).then(r => r.json());
Customer API (with session)
// Add to wishlist
await fetch('/api/customer/wishlist', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Cookie': sessionCookie,
  },
  body: JSON.stringify({
    productId: 'prod_xxx'
  }),
});

// Fetch customer orders
const orders = await fetch(
  '/api/customer/orders?page=1&limit=10',
  { headers: { 'Cookie': sessionCookie } }
).then(r => r.json());

// Update profile
await fetch('/api/customer/update', {
  method: 'PUT',
  headers: {
    'Content-Type': 'application/json',
    'Cookie': sessionCookie,
  },
  body: JSON.stringify({
    firstName: 'Daniel',
    lastName: 'Cohen',
    phone: '+972501234567',
  }),
});

Response format

Success Response
{
  "data": [
    {
      "id": "uuid",
      "order_number": "1001",
      "status": "processing",
      "total": 480.00,
      "created_at": "2026-01-06T10:00:00Z"
    }
  ],
  "meta": {
    "pagination": {
      "page": 1,
      "limit": 50,
      "total": 150,
      "total_pages": 3,
      "has_next": true,
      "has_prev": false
    }
  }
}
Error Response
{
  "error": {
    "code": "not_found",
    "message": "Order not found"
  }
}

Ready to start?

Create a developer account, generate an API key, and start shipping integrations.