Resources
1. Category
1.1 List Categories
Use GET /category/ to retrieve a full list of Category IDs.
{
"categories": [
{
"id": "12345",
"name": "Category One",
"parent": "0",
"sequence": "1",
"description": true,
"hidden": false,
"image": "category_one.png",
"seo": {
"custom_url": null,
"title": null,
"keywords": null,
"description": null
}
},
{
"id": "12346",
"name": "Category Two ",
"parent": "0",
"sequence": "2",
"description": true,
"hidden": false,
"image": "category_two.png",
"seo": {
"custom_url": "category-two",
"title": null,
"keywords": null,
"description": null
}
}
]
}
1.2 Get Category
Use GET /category/{id} to retrieve a single category by ID.
{
"id": "12345",
"name": "Category One",
"parent": "0",
"sequence": "1",
"description": true,
"hidden": false,
"image": "category_one.png",
"seo": {
"customUrl": null,
"title": null,
"keywords": null,
"description": null
}
}
1.3 Create Category
Use POST /category/ to create a new category.
Request: {
"name": "New Category",
"parent": "0",
"sequence": 1,
"hidden": false,
"image": "category_image.png",
"googleCategory": "Apparel & Accessories",
"seo": {
"customUrl": "new-category",
"title": "New Category Title",
"keywords": "category, new",
"description": "Category description for SEO"
}
}
200: {
"message": "Category Created",
"categoryId": "12347"
}
400: {
"message": "Bad Request: Category name is required"
}
Required fields: name. All other fields are optional.
1.4 Update Category
Use PUT /category/{id} to update an existing category.
All fields are optional. Send only the data you wish to change.
Request: {
"name": "Updated Category Name",
"hidden": true
}
200: {
"message": "Category Updated",
"categoryId": "12345"
}
404: {
"message": "Category not found"
}
1.5 Delete Category
Use DELETE /category/{id} to delete an existing category.
200: {
"message": "Category deleted"
}
404: {
"message": "Category not found"
}
2. Product
2.1 List Products
Use GET /product/ to retrieve a full list of products.
{
"products": {
"found": 10,
"nextToken": "20330401", //pass in URL to page through the results
"list": [
{
"id": "8329129",
"productType": "physical",
"sku": "XF2702004",
"name": "Grand Prix .177 used TT Racecar",
"abstract": "Short description here - plaintext only. 100 to 1500 characters",
"created": "2020-02-27T13:37:10.405Z",
"updated": "2023-06-28T13:15:08.999Z",
"condition": "used",
"image": {
"filename": "1582810553015_img_20200227_132824.jpg"
},
"price": 25,
"categoryId": "4666041",
"pricing": {
"baseprice": 25
},
"brand": "Brocock",
"published": true,
"locked": false,
"score": 85,
"sold": 1,
"stock": 0
},
...
]
}
Optional parameters: per_page (int), sort (str - any attribute name), sort_order (str -
'asc'|'desc'), start (int), categoryId (int)
2.2 Get Product
Use GET /product/{id} to get the detail for a specific product
{
"core": {
"id": "45258783",
"productType": "physical",
"sku": "IFJoAKW",
"name": "T-Shirt",
"abstract": "Colourful t-shirts to brighten the day of everyone in your office. Dazzle new customers with your go-to wardrobe item for the summer. Shine on! My money don't jiggle, jiggle. It folds honey!",
"created": "2023-04-05T14:45:18.694Z",
"updated": "2023-06-21T13:35:25.05Z",
"condition": "new",
"image": {
"filename": "red_1680705873605.jpg"
},
"price": 6.99,
"categoryId": "272237",
"pricing": {
"baseprice": 9.99,
"discount": {
"type": "price",
"value": 6.99
}
},
"url": "t-shirtv1",
"seo": {
"title": "T-Shirt",
"desc": "Colourful t-shirts to brighten the day of everyone in your office. Dazzle new customers with your go-to wardrobe item for the summer. Shine on!",
"keywords": [
"T-Shirt",
"T-Shirts"
]
},
"brand": "Bond Street",
"published": true,
"featured": true,
"weight": {
"value": 80.0,
"weightType": "oz"
},
"width": {
"value": 0.0,
"lengthType": "mm"
},
"height": {
"value": 0.0,
"lengthType": "mm"
},
"depth": {
"value": 0.0,
"lengthType": "mm"
},
"stock": 40,
"score": 130.0,
"variant_count": 12,
"sold": 0,
"offer_type": "price",
"minQty": 1,
"maxQty": -1,
"countryOfOrigin": "China",
"randomId": "is_gPPfOD"
},
"variants": [
{
"uvid": "720ZxR",
"key": "Color:Green;#Size:Large;",
"sku": "g33qH3t",
"image": {
"filename": "green_1680705873574.jpg"
},
"weight": {
"value": 0.0,
"weightType": "g"
},
"width": {
"value": 0.0,
"lengthType": "mm"
},
"height": {
"value": 0.0,
"lengthType": "mm"
},
"depth": {
"value": 0.0,
"lengthType": "mm"
},
"stock": 3,
"low_stock_level": 0,
"condition": "New",
"sequence": 8,
"label": "Color:Green;#Size:Large;"
},
{
"uvid": "KX9jTq",
"key": "Color:Green;#Size:Medium;",
"sku": "PybJbzr",
"image": {
"filename": "green_1680705873574.jpg"
},
"weight": {
"value": 0.0,
"weightType": "g"
},
"width": {
"value": 0.0,
"lengthType": "mm"
},
"height": {
"value": 0.0,
"lengthType": "mm"
},
"depth": {
"value": 0.0,
"lengthType": "mm"
},
"stock": 3,
"low_stock_level": 0,
"condition": "New",
"sequence": 7,
"label": "Color:Green;#Size:Medium;"
},
{
"uvid": "ssbwww",
"key": "Color:Green;#Size:Small;",
"sku": "U69Hocp",
"image": {
"filename": "green_1680705873574.jpg"
},
"weight": {
"value": 0.0,
"weightType": "oz"
},
"width": {
"value": 0.0,
"lengthType": "mm"
},
"height": {
"value": 0.0,
"lengthType": "mm"
},
"depth": {
"value": 0.0,
"lengthType": "mm"
},
"stock": 3,
"low_stock_level": 0,
"condition": "New",
"sequence": 6,
"label": "Color:Green;#Size:Small;"
},
{
"uvid": "qgim2U",
"key": "Color:Purple;#Size:Large;",
"sku": "qHR97zG",
"image": {
"filename": "purple_1680705873599.jpg"
},
"weight": {
"value": 0.0,
"weightType": "oz"
},
"width": {
"value": 0.0,
"lengthType": "mm"
},
"height": {
"value": 0.0,
"lengthType": "mm"
},
"depth": {
"value": 0.0,
"lengthType": "mm"
},
"stock": 3,
"low_stock_level": 0,
"condition": "New",
"sequence": 5,
"label": "Color:Purple;#Size:Large;"
},
{
"uvid": "OVjKAc",
"key": "Color:Purple;#Size:Medium;",
"sku": "9mGVTAd",
"image": {
"filename": "purple_1680705873599.jpg"
},
"weight": {
"value": 0.0,
"weightType": "oz"
},
"width": {
"value": 0.0,
"lengthType": "mm"
},
"height": {
"value": 0.0,
"lengthType": "mm"
},
"depth": {
"value": 0.0,
"lengthType": "mm"
},
"stock": 3,
"low_stock_level": 0,
"condition": "New",
"sequence": 4,
"label": "Color:Purple;#Size:Medium;"
},
{
"uvid": "IRfGSJ",
"key": "Color:Purple;#Size:Small;",
"sku": "Pk0xiTd",
"image": {
"filename": "purple_1680705873599.jpg"
},
"weight": {
"value": 0.0,
"weightType": "oz"
},
"width": {
"value": 0.0,
"lengthType": "mm"
},
"height": {
"value": 0.0,
"lengthType": "mm"
},
"depth": {
"value": 0.0,
"lengthType": "mm"
},
"stock": 3,
"low_stock_level": 0,
"condition": "New",
"sequence": 3,
"label": "Color:Purple;#Size:Small;"
},
{
"uvid": "xJdzV7",
"key": "Color:Red;#Size:Large;",
"sku": "v3wW5Cj",
"image": {
"filename": "red_1680705873605.jpg"
},
"weight": {
"value": 0.0,
"weightType": "g"
},
"width": {
"value": 0.0,
"lengthType": "mm"
},
"height": {
"value": 0.0,
"lengthType": "mm"
},
"depth": {
"value": 0.0,
"lengthType": "mm"
},
"stock": 3,
"low_stock_level": 0,
"condition": "New",
"sequence": 2,
"label": "Color:Red;#Size:Large;"
},
{
"uvid": "sUN4Go",
"key": "Color:Red;#Size:Medium;",
"sku": "7HMmN3K",
"weight": {
"value": 0.0,
"weightType": "g"
},
"width": {
"value": 0.0,
"lengthType": "mm"
},
"height": {
"value": 0.0,
"lengthType": "mm"
},
"depth": {
"value": 0.0,
"lengthType": "mm"
},
"stock": 3,
"low_stock_level": 0,
"condition": "New",
"sequence": 1,
"label": "Color:Red;#Size:Medium;"
},
{
"uvid": "enqXYH",
"key": "Color:Red;#Size:Small;",
"sku": "IPHupPD",
"weight": {
"value": 0.0,
"weightType": "oz"
},
"width": {
"value": 0.0,
"lengthType": "mm"
},
"height": {
"value": 0.0,
"lengthType": "mm"
},
"depth": {
"value": 0.0,
"lengthType": "mm"
},
"stock": 3,
"low_stock_level": 0,
"condition": "New",
"sequence": 0,
"label": "Color:Red;#Size:Small;"
},
{
"uvid": "vCzXPf",
"key": "Color:Yellow;#Size:Large;",
"sku": "5wy40oV",
"image": {
"filename": "yellow_1680705873612.jpg"
},
"weight": {
"value": 0.0,
"weightType": "g"
},
"width": {
"value": 0.0,
"lengthType": "mm"
},
"height": {
"value": 0.0,
"lengthType": "mm"
},
"depth": {
"value": 0.0,
"lengthType": "mm"
},
"price": 2.5,
"stock": 5,
"low_stock_level": 0,
"condition": "New",
"sequence": 11,
"label": "Color:Yellow;#Size:Large;"
},
{
"uvid": "CojZbF",
"key": "Color:Yellow;#Size:Medium;",
"sku": "LFNg6ml",
"image": {
"filename": "yellow_1680705873612.jpg"
},
"weight": {
"value": 0.0,
"weightType": "g"
},
"width": {
"value": 0.0,
"lengthType": "mm"
},
"height": {
"value": 0.0,
"lengthType": "mm"
},
"depth": {
"value": 0.0,
"lengthType": "mm"
},
"price": 2.5,
"stock": 5,
"low_stock_level": 0,
"condition": "New",
"sequence": 10,
"label": "Color:Yellow;#Size:Medium;"
},
{
"uvid": "plzzhz",
"key": "Color:Yellow;#Size:Small;",
"sku": "nS54tJM",
"image": {
"filename": "yellow_1680705873612.jpg"
},
"weight": {
"value": 0.0,
"weightType": "oz"
},
"width": {
"value": 0.0,
"lengthType": "mm"
},
"height": {
"value": 0.0,
"lengthType": "mm"
},
"depth": {
"value": 0.0,
"lengthType": "mm"
},
"price": 2.5,
"stock": 3,
"low_stock_level": 0,
"condition": "New",
"sequence": 9,
"label": "Color:Yellow;#Size:Small;"
}
],
"extraimages": [
{
"filename": "purple_1680705873599.jpg",
"alt": "null"
},
{
"filename": "green_1680705873574.jpg",
"alt": ""
},
{
"filename": "yellow_1680705873612.jpg",
"alt": ""
}
],
"extracategories": [
{
"categoryId": "853431"
}
],
"google": {
"google_eligible": 1
}
}
2.3 Create Product
Use POST to /product/ to create a new Product
{
"core": {
"productType": "physical",
"sku": "IFJoAKW",
"name": "T-Shirt",
"abstract": "Colourful t-shirts to brighten the day of everyone in your office. Dazzle new customers with your go-to wardrobe item for the summer. Shine on! My money don't jiggle, jiggle. It folds honey!",
"created": "2023-04-05T14:45:18.694Z",
"updated": "2023-06-21T13:35:25.05Z",
"condition": "new",
"image": {
"filename": "red_1680705873605.jpg"
},
"price": 6.99,
"categoryId": "272237",
"pricing": {
"baseprice": 9.99,
"discount": {
"type": "price",
"value": 6.99
}
},
"url": "t-shirtv1",
"seo": {
"title": "T-Shirt",
"desc": "Colourful t-shirts to brighten the day of everyone in your office. Dazzle new customers with your go-to wardrobe item for the summer. Shine on!",
"keywords": [
"T-Shirt",
"T-Shirts"
]
},
"brand": "Bond Street",
"published": true,
"featured": true,
"stock": 40,
"score": 130.0,
"variant_count": 12,
"sold": 0,
"offer_type": "price",
"minQty": 1,
"maxQty": -1,
"countryOfOrigin": "China",
"randomId": "is_gPPfOD"
},
"variants": [
{
"key": "Color:Green;#Size:Large;",
"sku": "g33qH3t",
"image": {
"filename": "green_1680705873574.jpg"
},
"stock": 3,
"low_stock_level": 0,
"condition": "New",
"sequence": 8,
"label": "Color:Green;#Size:Large;"
},
{
"key": "Color:Green;#Size:Medium;",
"sku": "PybJbzr",
"image": {
"filename": "green_1680705873574.jpg"
},
"stock": 3,
"low_stock_level": 0,
"condition": "New",
"sequence": 7,
"label": "Color:Green;#Size:Medium;"
},
{
"key": "Color:Green;#Size:Small;",
"sku": "U69Hocp",
"image": {
"filename": "green_1680705873574.jpg"
},
"stock": 3,
"low_stock_level": 0,
"condition": "New",
"sequence": 6,
"label": "Color:Green;#Size:Small;"
},
{
"key": "Color:Purple;#Size:Large;",
"sku": "qHR97zG",
"image": {
"filename": "purple_1680705873599.jpg"
},
"stock": 3,
"low_stock_level": 0,
"condition": "New",
"sequence": 5,
"label": "Color:Purple;#Size:Large;"
},
{
"key": "Color:Purple;#Size:Medium;",
"sku": "9mGVTAd",
"image": {
"filename": "purple_1680705873599.jpg"
},
"stock": 3,
"low_stock_level": 0,
"condition": "New",
"sequence": 4,
"label": "Color:Purple;#Size:Medium;"
},
{
"key": "Color:Purple;#Size:Small;",
"sku": "Pk0xiTd",
"image": {
"filename": "purple_1680705873599.jpg"
},
"stock": 3,
"low_stock_level": 0,
"condition": "New",
"sequence": 3,
"label": "Color:Purple;#Size:Small;"
},
{
"key": "Color:Red;#Size:Large;",
"sku": "v3wW5Cj",
"image": {
"filename": "red_1680705873605.jpg"
},
"stock": 3,
"low_stock_level": 0,
"condition": "New",
"sequence": 2,
"label": "Color:Red;#Size:Large;"
},
{
"key": "Color:Red;#Size:Medium;",
"sku": "7HMmN3K",
"stock": 3,
"low_stock_level": 0,
"condition": "New",
"sequence": 1,
"label": "Color:Red;#Size:Medium;"
},
{
"key": "Color:Red;#Size:Small;",
"sku": "IPHupPD",
"stock": 3,
"low_stock_level": 0,
"condition": "New",
"sequence": 0,
"label": "Color:Red;#Size:Small;"
},
{
"key": "Color:Yellow;#Size:Large;",
"sku": "5wy40oV",
"image": {
"filename": "yellow_1680705873612.jpg"
},
"price": 2.5,
"stock": 5,
"low_stock_level": 0,
"condition": "New",
"sequence": 11,
"label": "Color:Yellow;#Size:Large;"
},
{
"key": "Color:Yellow;#Size:Medium;",
"sku": "LFNg6ml",
"image": {
"filename": "yellow_1680705873612.jpg"
},
"price": 2.5,
"stock": 5,
"low_stock_level": 0,
"condition": "New",
"sequence": 10,
"label": "Color:Yellow;#Size:Medium;"
},
{
"key": "Color:Yellow;#Size:Small;",
"sku": "nS54tJM",
"image": {
"filename": "yellow_1680705873612.jpg"
},
"price": 2.5,
"stock": 3,
"low_stock_level": 0,
"condition": "New",
"sequence": 9,
"label": "Color:Yellow;#Size:Small;"
}
],
"extraimages": [
{
"filename": "purple_1680705873599.jpg",
"alt": "null"
},
{
"filename": "green_1680705873574.jpg",
"alt": ""
},
{
"filename": "yellow_1680705873612.jpg",
"alt": ""
}
],
"extracategories": [
{
"categoryId": "853431"
}
]
}
200: {
"message":"Product Created",
"productId":11111111
}
400: {
"errors":[{
"message":"The property [price] does not exist"
},
...
],
"type":"ProductValidationException",
"count":2
}
403: {
"Forbidden - "
}
2.4 Update Product
Use PUT to /product/{id} to update an existing Product
All Fields Are Optional. Send just the data you wish to change
Collections (variants, options/add-ons, related products, additional images) are replace-on-send. If you include a collection in an update you must pass ALL of its items — any item you leave out is removed. To change part of a product without affecting a collection, simply omit that collection from the request and it is left untouched.
Preserve identity fields when echoing a collection back. Variants are matched by key (and uvid) and options by key — these are how the API recognises an existing item. Keep them intact so items are updated in place rather than deleted and recreated. See Best Practices for the recommended read-modify-write pattern.
Stock Updates: For simple products without variants, you can update stock via {"core":{"stock":100}}. For products with variants, you cannot update the base product stock - you must update each variant's stock individually by including all variants in the update with their stock values.
If a stock change is requested but fails (for example, setting base stock on a product that has variants), the response is 422 with {"stockUpdated": false, "stockError": ...}. Any other fields in the same request are still applied — only the stock change was rejected. A normal update returns 200 with "Product Updated".
Tax rate (core.taxrate): set a fixed rate with {"core":{"taxrate":20}} (20%), make a product tax-free with {"core":{"taxrate":0}} (0%), or send {"core":{"taxrate":-1}} to clear any override and use the store's default tax rate. Omitting taxrate leaves the current setting unchanged.
Request: {
"core" : { "stock" : 125, "sku" : "ABC001" }
}
200: {
"message":"Product Updated",
"productId":11111111
}
400: {
"errors":[{
"message":"The property [price] does not exist"
},
{
"message":"The property [category.primary] does not exist"
}],
"type":"ProductValidationException",
"count":2
}
403: {
"Forbidden - "
}
2.5 Delete Product
Use DELETE /product/{id} to delete an existing product.
200: {
"message": "Product deleted"
}
404: {
"message": "Product not found"
}
2.6 Search Products
Use GET /product/search to search products using CloudSearch.
GET /product/search?q=shirt&limit=20&start=0
Query parameters:
- q (required) - Search query
- limit (optional) - Results per page (default 50)
- start (optional) - Pagination offset (default 0)
200: {
"query": "shirt",
"results": [
{
"id": "12345",
"name": "Blue T-Shirt",
"sku": "TSHIRT-BLU",
"price": 19.99,
"stock": 45
}
]
}
400: {
"message": "Bad Request: Search query 'q' is required"
}
2.7 Low Stock Products
Use GET /product/low-stock to retrieve products sorted by stock level (lowest first).
GET /product/low-stock?limit=20
Query parameters:
- limit (optional) - Results per page
- start (optional) - Pagination offset
200: {
"products": {
"found": 50,
"list": [
{
"id": "12345",
"name": "Popular Item",
"sku": "POP-001",
"stock": 2
},
{
"id": "12346",
"name": "Another Item",
"sku": "ANO-002",
"stock": 5
}
]
}
}
Useful for inventory management and restock alerts.
2.8 Stock History
Use GET /product/{id}/stock to retrieve the stock audit trail for a product.
200: {
"productId": "12345",
"stockHistory": [
{
"datetime": "2026-02-01T10:30:00Z",
"change": -1,
"newLevel": 44,
"reason": "Order #1001",
"origin": "SALE"
},
{
"datetime": "2026-01-28T14:00:00Z",
"change": 50,
"newLevel": 45,
"reason": "Restock",
"origin": "API"
}
]
}
404: {
"message": "Product not found"
}
Shows all stock changes including sales, returns, and manual adjustments.
2.9 Advanced Search
Use POST /product/search for advanced filtered product searches.
POST /product/search
Request Body:
{
"filters": {
"categoryId": "12345",
"minPrice": 10,
"maxPrice": 100
}
}
200: {
"results": [
{
"id": "12345",
"name": "Product Name",
"sku": "SKU-001",
"price": 29.99
}
]
}
Allows complex filtering beyond simple text search.
2.10 Featured Products
Use GET /product/featured to retrieve products marked as featured.
GET /product/featured?limit=10
200: {
"products": {
"found": 5,
"list": [
{
"id": "12345",
"name": "Featured Product",
"sku": "FEAT-001",
"price": 49.99,
"featured": true
}
]
}
}
Optional parameters: limit (default 50), start (pagination token).
2.11 Products on Sale
Use GET /product/offers to retrieve products with active sale prices.
GET /product/offers?limit=20
200: {
"products": {
"found": 12,
"list": [
{
"id": "12345",
"name": "Sale Item",
"sku": "SALE-001",
"price": 29.99,
"salePrice": 19.99
}
]
}
}
Returns products that have sale/offer pricing set. Useful for promotions.
2.12 New Products
Use GET /product/new to retrieve recently added products.
GET /product/new?limit=10
200: {
"products": {
"found": 8,
"list": [
{
"id": "12345",
"name": "New Arrival",
"sku": "NEW-001",
"price": 39.99,
"created": "2026-02-01T10:00:00Z"
}
]
}
}
Products sorted by creation date (newest first).
2.13 Full Stock History
Use GET /product/{id}/stock/all to retrieve complete stock history including all variants.
GET /product/12345/stock/all
200: {
"productId": "12345",
"stockHistory": [
{
"variantId": "var-001",
"variantName": "Size: Large",
"datetime": "2026-02-01T10:30:00Z",
"change": -1,
"newLevel": 22,
"reason": "Order #1001",
"origin": "SALE"
},
{
"variantId": null,
"datetime": "2026-01-28T14:00:00Z",
"change": 50,
"newLevel": 45,
"reason": "Restock",
"origin": "API"
}
]
}
404: {
"message": "Product not found"
}
Unlike /stock, this includes variant-level stock changes.
2.14 Copy Product
Use POST /product/{id}/copy to create a duplicate of an existing product.
POST /product/12345/copy
Optional Request Body:
{
"name": "New Product Name (Copy)"
}
200: {
"message": "Product copied",
"sourceProductId": "12345",
"newProductId": "67890"
}
404: {
"message": "Product not found"
}
Creates a new product with the same attributes as the source. Useful for creating product variations.
3. Order
3.1 List Orders
Use GET /orders/ to retrieve a full list of Orders.
"orders": [
{
"id": "12345",
"created": "2013-08-15T13:40:06.997Z",
"orderno": "1001",
"status": 1,
"method": "PayPal",
"deliveryname": "",
"tags": [
""
],
"net": "2.8405",
"discount": "0.0",
"tax": "0.0",
"postage": "1.0",
"postagetax": "0.0",
"total": "3.84",
"trackingcodes": [
""
],
"deleted": false,
"customerId": "12345",
"isnew": false,
"isstarred": null,
"isuploadedtokashflow": false,
"isdispatched": false,
"updatedon": null,
"flux": null
}
]
Optional parameters: limit (int), status (str -
"all"|"open"|"closed"|"problem"|"openproblem"|"new"|"starred"|"cart"|"canceled"|"cancelled"),
sort (str - "created"|"createddesc"|"orderno"|"ordernodesc"), tags (str - comma separated list),
startdate (str - Zulu format timestamp),
enddate (str - Zulu format timestamp), offset (int), fields (str - comma separated list of optional
fields - valid values: "customer","tags")
eg. /orders/?offset=0&limit=10&status=new
3.2 Show Order Details
Use GET /orders/{orderID} to obtain the details for a specific order.
{
"storeid": "12345",
"id": "12345",
"customerId": "12345",
"email": "user@domain.com",
"orderNo": 1001,
"created": "2013-08-15T13:40:06.997+00:00",
"net": 2.8405,
"tax": 0,
"postage": 1,
"postage_tax": 0,
"discount": 0,
"tax_rate": 0,
"paybyotherid": -1,
"paymentmethod": "PayPal",
"instructions": "Please leave the parcel by the front door",
"reference": "abcdefg123",
"ip": "1.2.3.4",
"order_status": 1,
"order_details": [
{
"productId": "12345",
"productName": "Product One",
"sku": "PROD1",
"description": "Product One Description",
"net": 2.8405,
"tax": 0,
"quantity": 1,
"options": [
{
"choiceId": "12345",
"net": 0,
"tax": 0
}
]
}
],
"postage_audit": {
"ruleId": -1,
"method": 0,
"totalWeight": 0,
"net": 0,
"tax": 0
}
}
Note: fields with no value are omitted from the response entirely, so the exact
shape varies per order. In particular:
instructions — the note your customer typed at checkout (e.g. delivery
instructions). Only present when the customer left one. On some older orders this value is stored
URL-encoded, so we recommend running it through a URL-decode before use.
notes — the array of order notes added by you (or your integrations) via the
control panel or POST /orders/{orderID}/notes.
billing_address / delivery_address — the customer's
addresses for this order, present when captured at checkout.
Notes you keep against a customer's record (the "Customer Notes" panel in the control panel) are
returned separately as the notes field on
GET /customers/{customerID}.
These fields are only returned by this single-order endpoint — the GET /orders
list endpoint returns a summary per order and does not include them.
3.3 Update Order Status
Use PUT /orders/{orderID}/status to update the status of an order.
Request: {
"status": 2
}
200: {
"message": "Order status updated",
"orderId": "12345"
}
400: {
"message": "Bad Request: '10' is not a settable order status. Allowed values: 1 (Open), 2 (Closed), 3 (Problem), 4 (Pending). Refunds and cancellations cannot be set via this endpoint."
}
404: {
"message": "Order not found"
}
Settable Status Codes (the same states the control panel's status buttons set):
- 1 - Open — the order is live and awaiting fulfilment. Shown as Open in the control panel.
- 2 - Closed — the order is complete. Shown as Closed.
- 3 - Problem — the order needs attention. Shown as Problem.
- 4 - Pending — the order is in progress (e.g. handed to a shipper, payment settling). Shown as Pending.
Any other value is rejected with a 400. Orders you read back can carry additional
status codes set by payment flows — e.g. 0 (pre-checkout), 13 (Refunded),
46 (Canceled), 47 (Awaiting Payment) and various gateway-specific error states, which the
control panel displays as Problem. Those states can only be set by the payment and
refund flows themselves, never through this endpoint.
Canceled orders (status 46) are terminal: attempting to change their status returns
409 Conflict. Don't retry — the order can only be deleted via the
control panel.
3.4 Add Tracking
Use POST /orders/{orderID}/tracking to add tracking information to an order.
Request: {
"trackingNumber": "1Z999AA10123456784",
"courier": "UPS"
}
200: {
"message": "Tracking information added",
"orderId": "12345"
}
400: {
"message": "Bad Request: Tracking number is required"
}
404: {
"message": "Order not found"
}
Required fields: trackingNumber. The courier field is optional.
3.5 Mark Dispatched
Use PUT /orders/{orderID}/dispatched to mark an order as dispatched.
200: {
"message": "Order marked as dispatched",
"orderId": "12345"
}
404: {
"message": "Order not found"
}
No request body required.
3.6 Add Note
Use POST /orders/{orderID}/notes to add a note to an order.
Request: {
"note": "Customer requested gift wrapping"
}
200: {
"message": "Note added to order",
"orderId": "12345"
}
400: {
"message": "Bad Request: Note text is required"
}
404: {
"message": "Order not found"
}
3.7 Get Order Counts
Use GET /orders/counts to retrieve order counts grouped by status.
200: {
"counts": {
"new": 5,
"processing": 12,
"shipped": 8,
"complete": 156,
"cancelled": 3,
"problem": 2,
"total": 186
}
}
No parameters required.
3.8 Mark as Read
Use PUT /orders/{orderID}/read to mark an order as read (removes the "new" flag).
200: {
"message": "Order marked as read",
"orderId": "12345"
}
404: {
"message": "Order not found"
}
No request body required.
3.9 Abandoned Orders
Use GET /orders/abandoned to retrieve abandoned checkout orders with error details.
{
"abandoned": [
{
"id": "12345",
"email": "customer@example.com",
"created": "2025-01-20T14:30:00Z",
"total": 89.99,
"currency": "GBP",
"items": 3,
"error": "Payment declined",
"paymentMethod": "stripe"
}
]
}
Optional parameters:
limit (int) - Maximum number of records to return
offset (int) - Number of records to skip for pagination
startdate (string) - Filter by start date (ISO format)
enddate (string) - Filter by end date (ISO format)
3.10 Add Order Tag
Use PUT /orders/{orderId}/tags/{tagId} to add a user-defined tag to an order. Returns 200 { "message": "Tag added", "orderId", "tagId" }. System-reserved tags are rejected with 403 — the platform sets those itself (shipping-label, accounting, and order-attribute tags such as promotion, taxfree, freeshipping, *-SL, acct_*).
3.11 Remove Order Tag
Use DELETE /orders/{orderId}/tags/{tagId} to remove a user-defined tag from an order. Returns 200 { "message": "Tag removed", "orderId", "tagId" }. System-reserved tags are rejected with 403.
3.12 Get Invoice / Credit Note (PDF)
Use GET /orders/{orderId}/invoice to retrieve the order's invoice PDF. Query param (optional): type = INVOICE (default) or CREDITNOTE. The PDF is returned base64-encoded inside a JSON envelope so no binary handling is needed:
{ "filename": "order_123.pdf", "contentType": "application/pdf", "sizeBytes": 51234, "base64": "JVBERi0xLjQ..." }
Decode the base64 field to obtain the PDF. Documents over ~4.5 MB return 413.
4. Customer
4.1 List Customers
Use GET /customers/ to retrieve a full list of Customers.
{
"customers": [
{
"shopkeeper": 12345,
"id": 1234567,
"email": "user1@domain.com",
"forename": "FirstName",
"surname": "Surname",
"account_type": 0,
"created": "2019-03-26T08:03:18.988Z",
"lastlogin": "0001-01-01T00:00:00+00:00",
"companyname": "COMPANY_NAME",
"deleted": 0,
"total_order_count": 1,
"total_order_value": 15,
"addresses": null,
"orders": null,
"reviews": null,
"messages": null,
"newsletter": null,
"paypalInfo": null,
"mash": null,
"notes": null
},
{
"shopkeeper": 12345,
"id": 1234568,
"email": "#####@#######.###",
"forename": "########",
"surname": "########",
"account_type": 0,
"created": "0001-01-01T00:00:00.000Z",
"lastlogin": "0001-01-01T00:00:00+00:00",
"companyname": "########",
"deleted": 0,
"total_order_count": 0,
"total_order_value": 0,
"addresses": null,
"orders": null,
"reviews": null,
"messages": null,
"newsletter": null,
"paypalInfo": null,
"mash": null,
"notes": null
}
]
}
Optional parameters:
limit (int) default 100,
includedeleted (str - true (default) | false)
sort (str - "created" | "createddesc" | "companyname" | "companynamedesc" | "email" | "emaildesc" |
"forename" | "forenamedesc" | "surname" | "surnamedesc" | "total_orders" | "total_ordersdesc" |
"total_sales" | "total_salesdesc"),
eg. /customers/?limit=10&sort=createddesc&includedeleted=false
4.2 Get Customers
Use GET /customers/{customerID} to retrieve a single Customer.
{
"shopkeeper": 12345,
"id": 1234567,
"email": "user@domain.com",
"forename": "FirstName",
"surname": "Surname",
"account_type": 0,
"created": "2017-05-22T16:13:34.315Z",
"lastlogin": "0001-01-01T00:00:00+00:00",
"companyname": null,
"deleted": 0,
"total_order_count": 1,
"total_order_value": 112.99,
"addresses": [
{
"id": 1234567,
"tag": null,
"country_id": 27,
"forename": "FirstName",
"surname": "Surname",
"primary_billing": false,
"primary_delivery": true,
"created": "2017-05-22T16:13:34.393+00:00",
"city": "City",
"address1": "Address Line 1",
"region_id": -1,
"postcode": "12345",
"county": "County",
"telephone": "1234567890",
"mobile": "",
"address2": "Address Line 2",
"companyname": "",
"deleted": false,
"country": "-1",
"region": "-1",
"lat": "",
"lng": "",
"formatted_address": ""
}
],
"orders": null,
"reviews": [],
"messages": [],
"newsletter": [],
"paypalInfo": {
"id": null,
"clientid": null,
"customerid": null,
"surname": null,
"forename": null,
"add1": null,
"add2": null,
"add3": null,
"city": null,
"county": null,
"country": null,
"postcode": null,
"telephone": null,
"orderid": null,
"deliverynotes": null,
"verified": null,
"postcodev2": null
},
"mash": null,
"notes": null
}
Optional parameters: None
4.3 Create Customer
Use POST /customers/ to create a Customer.
{
"email" : "user@domain.com",
"forename" : "bob",
"surname" : "jim",
"companyname": "bob&jim"
}
Optional parameters: None
4.4 Update Customer
Use PUT /customers/{customerID} to update an existing Customer.
{
"email" : "user1@domain1.com",
"forename" : "Bob",
"surname" : "Jim",
"companyname": "Bob&Jim"
}
Optional parameters: None
4.5 Delete Customer
Use DELETE /customers/{customerID} to update an existing Customer.
Optional parameters: None
4.6 Get Loyalty Points
Use GET /customers/{customerID}/loyalty to get a customer's loyalty point balance.
{
"customerId": "1234567",
"loyalty": {
"balance": 250,
"lifetimeEarned": 1500,
"lifetimeRedeemed": 1250,
"lastUpdated": "2025-01-15T10:30:00Z"
}
}
Optional parameters: None
4.7 Loyalty History
Use GET /customers/{customerID}/loyalty/history to get a customer's loyalty point transaction history.
{
"customerId": "1234567",
"history": [
{
"id": "txn_abc123",
"date": "2025-01-15T10:30:00Z",
"type": "earned",
"points": 50,
"description": "Purchase - Order #12345",
"balance": 250
},
{
"id": "txn_xyz789",
"date": "2025-01-10T14:22:00Z",
"type": "redeemed",
"points": -100,
"description": "Discount applied - Order #12340",
"balance": 200
}
]
}
Optional parameters:
limit (int) - Maximum number of transactions to return
offset (int) - Number of transactions to skip for pagination
4.8 Get Opt-Out Status
Use GET /customers/{email}/optout to read a customer's email-marketing opt-out status. The {email} path segment must be URL-encoded.
4.9 Set Opt-Out
Use POST /customers/{email}/optout to set a customer's email-marketing preference. Send the preference in the JSON body. The {email} path segment must be URL-encoded.
5. Review
5.1 List Reviews
Use GET /reviews to retrieve all reviews for your store.
{
"reviews": [
{
"id": "rev_abc123",
"productId": "12345",
"productName": "Example Product",
"customerName": "John D.",
"rating": 5,
"title": "Great product!",
"comment": "Exactly what I was looking for.",
"approved": true,
"reply": null,
"created": "2025-01-15T10:30:00Z"
}
]
}
Optional parameters:
limit (int) - Maximum number of reviews to return
offset (int) - Number of reviews to skip for pagination
5.2 Pending Reviews
Use GET /reviews/pending to retrieve reviews awaiting moderation.
{
"reviews": [
{
"id": "rev_xyz789",
"productId": "67890",
"productName": "New Product",
"customerName": "Jane S.",
"rating": 4,
"title": "Good quality",
"comment": "Happy with my purchase.",
"approved": false,
"reply": null,
"created": "2025-01-20T14:22:00Z"
}
]
}
Optional parameters:
limit (int) - Maximum number of reviews to return
offset (int) - Number of reviews to skip for pagination
5.3 Product Reviews
Use GET /reviews/product/{productId} to retrieve reviews for a specific product.
{
"productId": "12345",
"reviews": [
{
"id": "rev_abc123",
"customerName": "John D.",
"rating": 5,
"title": "Great product!",
"comment": "Exactly what I was looking for.",
"approved": true,
"reply": "Thank you for your feedback!",
"created": "2025-01-15T10:30:00Z"
}
]
}
Optional parameters:
limit (int) - Maximum number of reviews to return
offset (int) - Number of reviews to skip for pagination
5.4 Get Review
Use GET /reviews/{reviewId} to retrieve a single review by ID.
{
"id": "rev_abc123",
"productId": "12345",
"productName": "Example Product",
"customerName": "John D.",
"rating": 5,
"title": "Great product!",
"comment": "Exactly what I was looking for.",
"approved": true,
"reply": "Thank you for your feedback!",
"created": "2025-01-15T10:30:00Z"
}
Optional parameters: None
5.5 Update Review
Use PUT /reviews/{reviewId} to approve/reject a review or add a reply.
{
"approved": true,
"reply": "Thank you for your feedback!"
}
Request body fields (all optional):
approved (boolean) - Set to true to approve, false to reject
reply (string) - Your reply to the customer's review
5.6 Delete Review
Use DELETE /reviews/{reviewId} to permanently delete a review.
Optional parameters: None
6. Brand
Note: brands are identified by their name — there is no separate numeric id. Use the brand name as {id} in GET/PUT/DELETE /brands/{id} (URL-encode names that contain spaces), and POST /brands returns the name as brandId. The name is stored on the label field.
6.1 List Brands
Use GET /brands to retrieve all brands for your store.
{
"brands": [
{
"label": "Acme Corp",
"description": "Quality products since 1950",
"image": "acme-logo.png"
},
{
"label": "TechBrand",
"description": "Innovative technology solutions",
"image": null
}
]
}
Optional parameters: None
6.2 Get Brand
Use GET /brands/{brandId} to retrieve a single brand by ID.
{
"id": "brand_123",
"name": "Acme Corp",
"description": "Quality products since 1950",
"image": "https://example.com/acme-logo.png",
"productCount": 25,
"seo": {
"title": "Acme Corp Products",
"description": "Browse our collection of Acme Corp products",
"customUrl": "acme-corp"
}
}
Optional parameters: None
6.3 Create Brand
Use POST /brands to create a new brand.
{
"name": "New Brand",
"description": "Brand description here",
"image": "https://example.com/brand-logo.png"
}
Request body fields:
name (string, required) - The brand name
description (string, optional) - Brand description
image (string, optional) - URL to brand logo/image
6.4 Update Brand
Use PUT /brands/{brandId} to update an existing brand.
{
"name": "Updated Brand Name",
"description": "Updated description",
"image": "https://example.com/new-logo.png"
}
Request body fields (all optional):
name (string) - The brand name
description (string) - Brand description
image (string) - URL to brand logo/image
6.5 Delete Brand
Use DELETE /brands/{brandId} to delete a brand.
Optional parameters: None
7. Gift Cards
Note: Gift card endpoints are read-only for security purposes.
8.1 List Gift Cards
Use GET /giftcards to retrieve all gift cards for your store (sorted by balance).
{
"giftCards": [
{
"id": "gc_abc123",
"code": "GIFT-XXXX-XXXX",
"balance": 50.00,
"originalValue": 100.00,
"currency": "GBP",
"status": "active",
"created": "2025-01-01T00:00:00Z",
"expires": "2026-01-01T00:00:00Z"
}
]
}
Optional parameters:
limit (int) - Maximum number of gift cards to return
offset (int) - Number of gift cards to skip for pagination
8.2 Get Gift Card
Use GET /giftcards/{giftCardId} to retrieve a single gift card with its transaction log.
{
"id": "gc_abc123",
"code": "GIFT-XXXX-XXXX",
"balance": 50.00,
"originalValue": 100.00,
"currency": "GBP",
"status": "active",
"created": "2025-01-01T00:00:00Z",
"expires": "2026-01-01T00:00:00Z",
"purchaser": {
"email": "buyer@example.com",
"name": "John Doe"
},
"recipient": {
"email": "recipient@example.com",
"name": "Jane Doe"
},
"transactions": [
{
"id": "txn_001",
"date": "2025-01-15T10:30:00Z",
"type": "redemption",
"amount": -25.00,
"orderId": "12345",
"balance": 75.00
},
{
"id": "txn_002",
"date": "2025-01-20T14:22:00Z",
"type": "redemption",
"amount": -25.00,
"orderId": "12350",
"balance": 50.00
}
]
}
Optional parameters: None
8.3 Create Gift Card
Use POST /giftcards to create, revoke, or adjust a gift card via a ledger event. The JSON body's type field selects the action — e.g. { "type": "CREATE", "amount": 25, "recipientName": "...", "recipientEmail": "...", "expires": "2027-01-01" } to issue a card, or a REVOKE event with the gift id and a reason. The body is forwarded to the internal gift-card service.
8.4 Update Gift Card
Use PUT /giftcards/{giftCardId} to update a gift card's metadata: { "design": "...", "message": "...", "recipientName": "...", "recipientEmail": "..." }.
8.5 Printable Gift Card
Use GET /giftcards/{giftCardId}/printable to retrieve the printable gift card (PDF or HTML), returned base64-encoded in a JSON envelope { "filename", "contentType", "sizeBytes", "base64" } — check contentType and decode base64. Documents over ~4.5 MB return 413.
9. Pages
Manage store pages and content (e.g., About Us, Contact, Terms & Conditions).
9.1 List Pages
Use GET /pages to retrieve all pages for your store.
{
"pages": [
{
"id": "page_abc123",
"title": "About Us",
"slug": "about-us",
"published": true,
"created": "2025-01-01T00:00:00Z",
"updated": "2025-01-15T10:30:00Z"
},
{
"id": "page_def456",
"title": "Contact",
"slug": "contact",
"published": true,
"created": "2025-01-01T00:00:00Z",
"updated": "2025-01-10T08:00:00Z"
},
{
"id": "page_ghi789",
"title": "Terms & Conditions",
"slug": "terms-and-conditions",
"published": true,
"created": "2025-01-01T00:00:00Z",
"updated": "2025-01-01T00:00:00Z"
}
]
}
Optional parameters: None
9.2 Get Page
Use GET /pages/{pageId} to retrieve a single page with its full content.
{
"id": "page_abc123",
"title": "About Us",
"slug": "about-us",
"content": "<h2>Our Story</h2><p>We started in 2010...</p>",
"published": true,
"metaTitle": "About Us | My Store",
"metaDescription": "Learn more about our company and mission.",
"created": "2025-01-01T00:00:00Z",
"updated": "2025-01-15T10:30:00Z"
}
Optional parameters: None
9.3 Create Page
Use POST /pages to create a new page.
Request Body:
{
"title": "About Us",
"pageType": "content",
"slug": "about-us",
"published": true,
"metaTitle": "About Us | My Store",
"metaDescription": "Learn more about our store."
}
For an external navigation link, use pageType: "link" with an externalUrl:
{
"title": "Our Blog",
"pageType": "link",
"externalUrl": "https://blog.example.com"
}
Response:
{
"message": "Page created",
"pageId": "page_xyz789"
}
Required fields: title
pageType: "content" (default), "link", or "faq". Only these types can be created via the API — system and managed pages (Home, Basket, Terms, Privacy, etc.) cannot. Any other value returns 400.
externalUrl: required when pageType is "link".
Optional fields: slug, published, metaTitle, metaDescription
Note: page content (HTML body) is managed separately and is not stored by this call.
9.4 Update Page
Use PUT /pages/{pageId} to update an existing page.
Request Body:
{
"title": "Updated FAQ",
"content": "<h2>Updated Frequently Asked Questions</h2>",
"published": true
}
Response:
{
"message": "Page updated",
"pageId": "page_xyz789"
}
Optional fields: title, content, slug, published, metaTitle, metaDescription. Send only the fields you want to change — omitted fields are preserved.
content is screened by content moderation. If it is rejected (e.g. malicious links or banned content), the API returns 422 with a reason; any other fields in the same request are still applied.
9.5 Delete Page
Use DELETE /pages/{pageId} to delete a page.
Only content, external-link, Instagram and FAQ pages can be deleted via the API. System and managed pages (Home, Basket, Terms, Privacy, Contact, order pages, etc.) cannot be deleted and return 403.
Response:
{
"message": "Page deleted"
}
10. Analytics
10.1 Order Summary
Use GET /analytics/summary to get order statistics summary including total orders, total value, average order value, and daily breakdown.
Query Parameters (all optional):
period - Time period: 7days, 30days, 90days, year, custom (default: 7days)
from - Start date for custom period (YYYY-MM-DD)
to - End date for custom period (YYYY-MM-DD)
Response:
{
"totalOrders": 125,
"totalValue": 12500.00,
"averageOrderValue": 100.00,
"currency": "GBP",
"period": "30days",
"dailyBreakdown": [
{ "date": "2024-01-15", "orders": 5, "value": 500.00 },
{ "date": "2024-01-16", "orders": 8, "value": 750.00 }
]
}
10.2 Product Summary
Use GET /analytics/product-summary to get aggregated product statistics including totals, inventory status, pricing, performance metrics, and alerts. Designed for AI agent consumption and dashboards.
Query Parameters (all optional):
period - Time period for newly added calculation: 7days, 30days, 90days (default: 30days)
includeAlertDetails - Include up to 25 product IDs per alert type: true/false (default: false)
currency - ISO 4217 currency code for pricing (default: GBP)
lowScoreThreshold - Score below this triggers low_score alert (default: 50)
Response:
{
"storeId": "12345",
"generatedAt": "2024-01-15T10:30:00Z",
"totals": {
"all": 500,
"published": 450,
"unpublished": 50,
"physical": 400,
"digital": 100
},
"inventory": {
"inStock": 380,
"lowStock": 45,
"outOfStock": 25
},
"pricing": {
"lowest": 1.99,
"highest": 299.99,
"average": 45.50,
"currency": "GBP"
},
"performance": {
"topSellers": 25,
"zeroSales": 120,
"newlyAdded": 15
},
"alerts": {
"total": 70,
"byType": {
"out_of_stock": 25,
"low_stock": 45
},
"bySeverity": {
"high": 25,
"medium": 45
}
},
"categories": {
"total": 12,
"withProducts": 10
},
"metadata": {
"cached": false,
"processingMs": 125
}
}
10.3 Payment Methods
Use GET /analytics/payment-methods for order count and value broken down by payment method. Query params (optional): period (7days, 30days, 90days, year, custom), from, to (YYYY-MM-DD). Returns the internal analytics payload verbatim.
10.4 Best Periods
Use GET /analytics/best-periods to find the best-performing sales periods (days/hours). Query params (optional): period, from, to.
10.5 Average Order Value
Use GET /analytics/aov for average order value with median and range. Query params (optional): period, from, to.
10.6 Recent Activity
Use GET /analytics/recent for recent order activity. Query param (optional): limit.
10.7 Top Sellers
Use GET /analytics/top-sellers for best-selling products by units and revenue. Query params (optional): period, limit, currency (ISO 4217, default GBP).
10.8 Category Breakdown
Use GET /analytics/category-breakdown for sales split by product category. Query params (optional): period, currency.
10.9 Daily Traffic
Use GET /traffic/daily for daily visitor hits. Query param (optional): days (default 30, max 365).
10.10 Hourly Traffic
Use GET /traffic/hourly for hourly visitor hits. Query param (optional): date (YYYY-MM-DD).
11. Store
11.1 Get Store Details
Use GET /store to retrieve a curated set of your store's details and configuration.
For privacy and security this returns a simplified store object. It deliberately excludes sensitive data (account password, payment-gateway credentials / checkouts), personal data (IP, device, date of birth, login email) and internal onboarding/marketing fields.
Response:
{
"store": {
"id": "12345",
"name": "My Store",
"tagLine": "Welcome to my store",
"email": "contact@mystore.com",
"currency": "GBP",
"country": "GB",
"state": "Lancashire",
"created": "2023-11-16T13:21:22Z",
"thumbnailUrl": "https://.../thumb.png",
"status": 0,
"contact": { },
"seo": { },
"settings": { },
"vat": { },
"tax": { },
"design": { },
"brandkit": { },
"social": { },
"loyalty": { },
"giftCards": { },
"Google": { },
"Facebook": { }
}
}
Returned fields: id, name, tagLine, email, currency, country, state, created, thumbnailUrl, status, contact, seo, settings, vat, tax, ageVerify, invoiceSettings, languages, design, brandkit, social, notifyBar, reviewInvites, giftCards, loyalty, Google, Facebook.
11.2 Get Store Settings
Use GET /store/settings to retrieve your store's configuration settings including SEO, VAT, design, and feature settings.
Response:
{
"settings": {
"seo": {
"metaTitle": "My Store - Best Products Online",
"metaDescription": "Shop the best products..."
},
"vat": {
"enabled": true,
"rate": 20,
"displayIncVat": true
},
"design": {
"theme": "modern",
"primaryColor": "#3498db"
},
"brandKit": {
"primaryColor": "#3498db",
"secondaryColor": "#2ecc71",
"fontFamily": "Roboto"
}
}
}
11.3 Get Store Health
Use GET /store/health to retrieve your store's health score and recommendations for improvements.
Response:
{
"health": {
"score": 85,
"maxScore": 100,
"grade": "A",
"recommendations": [
{
"category": "SEO",
"issue": "Missing meta descriptions on 5 products",
"impact": "medium"
},
{
"category": "Images",
"issue": "3 products have no images",
"impact": "high"
}
]
}
}
11.4 Get Store Usage
Use GET /store/usage to retrieve your store's resource usage statistics.
Response:
{
"usage": {
"products": {
"used": 150,
"limit": 500
},
"images": {
"used": 450,
"limit": 1000
},
"storage": {
"usedMB": 256,
"limitMB": 1024
}
}
}
11.5 Get Slideshow
Use GET /store/slideshow to retrieve your store's homepage slideshow configuration.
Response:
{
"slideshow": {
"enabled": true,
"autoPlay": true,
"interval": 5000,
"slides": [
{
"id": "1",
"imageUrl": "https://...",
"linkUrl": "/category/sale",
"title": "Summer Sale",
"order": 1
},
{
"id": "2",
"imageUrl": "https://...",
"linkUrl": "/category/new",
"title": "New Arrivals",
"order": 2
}
]
}
}
11.6 Get Milestones
Use GET /store/milestones to retrieve your store's achievements and milestones.
Response:
{
"milestones": [
{
"id": "first_sale",
"name": "First Sale",
"achieved": true,
"achievedAt": "2024-01-15T10:30:00Z"
},
{
"id": "100_orders",
"name": "100 Orders",
"achieved": true,
"achievedAt": "2024-03-20T14:00:00Z"
},
{
"id": "1000_orders",
"name": "1000 Orders",
"achieved": false,
"progress": 45
}
]
}
11.7 Get Discounts
Use GET /store/discounts to retrieve your store's automatic discount rules.
Response:
{
"discounts": [
{
"id": "1",
"name": "10% off orders over £50",
"type": "percentage",
"value": 10,
"minOrderValue": 50,
"enabled": true
},
{
"id": "2",
"name": "Free shipping over £30",
"type": "free_shipping",
"minOrderValue": 30,
"enabled": true
}
]
}
13. Webhooks
13.1 How Webhooks Work
Webhooks notify your server when events happen in your store. When an event fires, we send an
HTTP POST with a JSON body to the URL you registered.
Event types:
NewOrder - an order was placed
CancelOrder - an order was cancelled or reversed
OrderDelete - an order was deleted
ProductCreate - a product was created
ProductChange - a product was changed
ProductDelete - a product was deleted
Delivery details worth knowing:
• The order payload is a summary (order id, order number, totals, customer
name/email, line items). Use the id from the payload to fetch the full order via
GET /orders/{orderID} (delivery address, shopper instructions, etc.) and the
customer via GET /customers/{customerID}.
• Deliveries are sent without authentication headers. Your receiving endpoint
must accept unauthenticated POSTs — the long random webhook URL is the shared secret. If your
receiver requires an inbound API key (for example make.com's "API Key authentication" webhook
setting), our deliveries will be rejected and will show as failed in your delivery results.
• A delivery is considered successful on an HTTP 200 response. Failed deliveries are retried
up to 10 times before being dropped.
• Every registered webhook matching the event type receives the event — if you register
two NewOrder webhooks, both fire for every order. Delete registrations you no longer use.
13.2 List Webhooks
Use GET /webhook to list your registered webhooks.
{
"webhooks": [
{
"webhookId": "aB3xY9",
"type": "NewOrder",
"url": "https://example.com/hooks/orders",
"createdAt": "2026-07-16T12:00:00.000Z"
}
]
}
13.3 Create Webhook
Use POST /webhook to register a webhook. Body:
{
"type": "NewOrder",
"url": "https://example.com/hooks/orders"
}
Response:
{
"message": "Webhook created",
"webhookId": "aB3xY9",
"type": "NewOrder",
"url": "https://example.com/hooks/orders",
"createdAt": "2026-07-16T12:00:00.000Z"
}
13.4 Delete Webhook
Use DELETE /webhook/{webhookId} to remove a registration. Deleting an unknown id
still returns 200.
13.5 Delivery Results
Use GET /webhook/results to see recent delivery attempts (newest first).
Optional parameter: limit (default 10, max 100). responseCode is the HTTP status
returned by your endpoint; success is true only for a 200 (OK) response.
{
"results": [
{
"datetime": "2026-07-16T12:59:44.254Z",
"type": "NewOrder",
"url": "https://example.com/hooks/orders",
"responseCode": "OK",
"success": true,
"payload": "{ ...the JSON body that was sent... }"
}
]
}
12. Samples
PHP
12.1 GET Request
PHP sample to get categories from the API, loop through them, and display them in paragraph tags;
<?php
$api_key = "YOUR_API_KEY";
$url = "https://api.freewebstore.com/category"
//Init curl
$ch = curl_init();
//Set the URL to call
curl_setopt($ch, CURLOPT_URL, $url);
//Set the API key as a header
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
"x-api-key:$api_key"
));
//Make sure the result is assigned to the variable as a string
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//Make the call
$output = curl_exec($ch);
if (curl_error($ch)) {
echo curl_error($ch);
} else {
//Parse the JSON result
$result = json_decode($output);
echo "Store Product Categories
";
foreach ($result->categories as $category) {
echo $category->{'id'}; //category id
echo " -> ";
echo $category->{'name'}; //category name
echo "
";
}
}
//Close the connection
curl_close($ch);
12.2 POST Request
PHP sample to create a new product with the minimum data required;
<?php
$api_key = "YOUR_API_KEY";
$url = "https://api.freewebstore.com/product";
$data = json_encode(
array(
'core' => array(
'name' => "My Product API Test",
'sku' => "API_TEST",
'stock' => "250",
'image' => array(
'filename' => "my_product_image.png",
),
'pricing' => array(
'baseprice' => "9.00",
)
)
)
);
//Init curl
$ch = curl_init();
//Set the URL to call
curl_setopt($ch, CURLOPT_URL, $url);
//Set the POST data
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
//Set the API key as a header
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
"x-api-key:$api_key"
));
//Make sure the result is assigned to the variable as a string
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//Make the call
$output = curl_exec($ch);
//Parse the JSON result
$result = json_decode($output);
print_r($result);
//Close the connection
curl_close($ch);
12.3 PUT Request
PHP sample to update an existing product;
<?php
$api_key = "YOUR_API_KEY";
$url = "https://api.freewebstore.com/product/11111111";
$data = json_encode(
array(
'core' => array(
'stock' => 113,
'image' => array(
'filename' => "myproductimage2.png",
),
'pricing' => array(
'baseprice' => "13.00",
)
)
)
);
//Init curl
$ch = curl_init();
//Set the URL to call
curl_setopt($ch, CURLOPT_URL, $url);
//Set as a PUT request
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
//Set the POST data
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
//Set the API key as a header
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
"x-api-key:$api_key"
));
//Make sure the result is assigned to the variable as a string
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//Make the call
$output = curl_exec($ch);
//Parse the JSON result
$result = json_decode($output);
print_r($result);
//Close the connection
curl_close($ch);
12.4 DELETE Request
PHP sample to delete an existing customer record
<?php
$api_key = "YOUR_API_KEY";
$url = "https://api.freewebstore.com/customers/1111111";
//Init curl
$ch = curl_init();
//Set the URL to call
curl_setopt($ch, CURLOPT_URL, $url);
//Set as a DELETE request
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
//Set the API key as a header
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
"x-api-key:$api_key"
));
//Make sure the result is assigned to the variable as a string
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//Make the call
$output = curl_exec($ch);
//Parse the JSON result
$result = json_decode($output);
print_r($result);
//Close the connection
curl_close($ch);
cURL
12.5 cURL (all verbs)
# Get a product
curl https://api.freewebstore.com/product/123456 \
-H "x-api-key: YOUR_API_KEY"
# Partial update - change ONLY the price (other fields untouched)
curl -X PUT https://api.freewebstore.com/product/123456 \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "core": { "price": 24.99 } }'
# Create a category
curl -X POST https://api.freewebstore.com/category \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "Summer Collection" }'
# Delete a product
curl -X DELETE https://api.freewebstore.com/product/123456 \
-H "x-api-key: YOUR_API_KEY"
JavaScript (Node.js 18+)
12.6 JavaScript
const API_KEY = "YOUR_API_KEY";
const BASE = "https://api.freewebstore.com";
async function api(method, path, body) {
const res = await fetch(BASE + path, {
method,
headers: {
"x-api-key": API_KEY,
...(body ? { "Content-Type": "application/json" } : {})
},
body: body ? JSON.stringify(body) : undefined
});
if (!res.ok) throw new Error(res.status + ": " + (await res.text()));
return res.json();
}
// List orders
const orders = await api("GET", "/orders");
// Partial update - change only the price
await api("PUT", "/product/123456", { core: { price: 24.99 } });
Python
12.7 Python (requests)
import requests
API_KEY = "YOUR_API_KEY"
BASE = "https://api.freewebstore.com"
HEADERS = {"x-api-key": API_KEY, "Content-Type": "application/json"}
# Get a product
product = requests.get(f"{BASE}/product/123456", headers=HEADERS).json()
# Partial update - change only the stock of a simple product
r = requests.put(
f"{BASE}/product/123456",
headers=HEADERS,
json={"core": {"stock": 100}},
)
r.raise_for_status()
print(r.json())
Worked Example
12.8 Safe variant stock update (read-modify-write)
The correct way to change one variant without disturbing the others: read the product, edit the variant in place, and send the whole variants array back with every key/uvid preserved. Omit everything you are not changing.
import requests
API_KEY = "YOUR_API_KEY"
BASE = "https://api.freewebstore.com"
HEADERS = {"x-api-key": API_KEY, "Content-Type": "application/json"}
# 1) Read the product
product = requests.get(f"{BASE}/product/123456", headers=HEADERS).json()
variants = product.get("variants", [])
# 2) Change ONE variant's stock, leaving every key/uvid intact
for v in variants:
if v.get("sku") == "RED-LARGE":
v["stock"] = 42
# 3) Send the WHOLE variants array back (replace-on-send).
# We omit core, options, etc. - they are left untouched.
r = requests.put(f"{BASE}/product/123456", headers=HEADERS, json={"variants": variants})
r.raise_for_status()
Appendix
Resource and URI Reference
| URI |
Method |
Resource |
Operation |
| /category |
GET |
Category |
Retrieves list of categories |
| /category/{id} |
GET |
Category |
Retrieves a single category by ID |
| /category |
POST |
Category |
Creates a new category |
| /category/{id} |
PUT |
Category |
Updates an existing category |
| /category/{id} |
DELETE |
Category |
Deletes a category |
| /product |
GET |
Product |
Retrieves list of products. Optional parameters: per_page, sort, sort_order, start, categoryId |
| /product/{id} |
GET |
Product |
Retrieves a single product with full details including variants |
| /product |
POST |
Product |
Creates a new product |
| /product/{id} |
PUT |
Product |
Updates an existing product (including stock) |
| /product/{id} |
DELETE |
Product |
Deletes a product |
| /product/search |
GET |
Product |
Searches products using CloudSearch. Required: q. Optional: limit, start |
| /product/low-stock |
GET |
Product |
Retrieves products sorted by stock level (lowest first) |
| /product/{id}/stock |
GET |
Product |
Retrieves stock audit trail for a product |
| /product/search |
POST |
Product |
Advanced product search with filters |
| /product/featured |
GET |
Product |
Retrieves featured products. Optional: limit, start |
| /product/offers |
GET |
Product |
Retrieves products on sale. Optional: limit, start |
| /product/new |
GET |
Product |
Retrieves recently added products. Optional: limit, start |
| /product/{id}/stock/all |
GET |
Product |
Retrieves full stock history including all variants |
| /product/{id}/copy |
POST |
Product |
Creates a duplicate of an existing product |
| /orders |
GET |
Orders |
Retrieves list of orders. Optional parameters: limit, status, sort, tags, startdate, enddate, offset, fields |
| /orders/{id} |
GET |
Order |
Retrieves order details for a single order |
| /orders/{id}/status |
PUT |
Order |
Updates the status of an order |
| /orders/{id}/tracking |
POST |
Order |
Adds tracking information to an order |
| /orders/{id}/dispatched |
PUT |
Order |
Marks an order as dispatched |
| /orders/{id}/notes |
POST |
Order |
Adds a note to an order |
| /orders/counts |
GET |
Order |
Retrieves order counts grouped by status |
| /orders/{id}/read |
PUT |
Order |
Marks an order as read |
| /orders/abandoned |
GET |
Order |
Retrieves abandoned checkout orders. Optional: limit, offset, startdate, enddate |
| /customers |
GET |
Customers |
Retrieves list of customers. Optional parameters: limit, sort, includedeleted |
| /customers/{id} |
GET |
Customer |
Retrieves a single customer with full details |
| /customers |
POST |
Customer |
Creates a new customer |
| /customers/{id} |
PUT |
Customer |
Updates an existing customer |
| /customers/{id} |
DELETE |
Customer |
Deletes a customer |
| /customers/{id}/loyalty |
GET |
Customer |
Retrieves customer loyalty point balance |
| /customers/{id}/loyalty/history |
GET |
Customer |
Retrieves loyalty point transaction history. Optional: limit, offset |
| /giftcards |
GET |
Gift Card |
Retrieves list of gift cards. Optional: limit, offset |
| /giftcards/{id} |
GET |
Gift Card |
Retrieves gift card details with transaction log |
| /reviews |
GET |
Review |
Retrieves list of all reviews. Optional: limit, offset |
| /reviews/pending |
GET |
Review |
Retrieves reviews awaiting moderation. Optional: limit, offset |
| /reviews/product/{id} |
GET |
Review |
Retrieves reviews for a specific product. Optional: limit, offset |
| /reviews/{id} |
GET |
Review |
Retrieves a single review by ID |
| /reviews/{id} |
PUT |
Review |
Updates a review (approve/reject, add reply) |
| /reviews/{id} |
DELETE |
Review |
Deletes a review |
| /brands |
GET |
Brand |
Retrieves list of all brands |
| /brands/{id} |
GET |
Brand |
Retrieves a single brand by ID |
| /brands |
POST |
Brand |
Creates a new brand |
| /brands/{id} |
PUT |
Brand |
Updates an existing brand |
| /brands/{id} |
DELETE |
Brand |
Deletes a brand |
| /pages |
GET |
Page |
Retrieves list of all pages |
| /pages/{id} |
GET |
Page |
Retrieves a single page with content |
| /pages |
POST |
Page |
Creates a new page |
| /pages/{id} |
PUT |
Page |
Updates an existing page |
| /pages/{id} |
DELETE |
Page |
Deletes a page |
| /check_key |
GET |
API Key |
Validates API key and returns associated storeId |
| /stats |
GET |
Statistics |
Retrieves API usage statistics |