Skip to main content

Product Synchronization

Every product must be known to Paxon before it can be delivered to a warehouse or ordered. Your application, such as a webshop or ERP, is leading for the product details: create new products in Paxon and update the ones that changed. Paxon is leading for the stock, which is described in Stock Level Synchronization.

The sku identifies a product in both systems. Paxon also gives every product its own id, which you need to update the product. Store this id with the product in your application, so you don't have to look it up every time.

All examples below leave out the Authorization header, which is required on every request. See Authenticating.

Creating and updating products​

When a product is created or changed in your application, check whether Paxon already knows it. If not, create it; if so, update it.

Looking up products​

Use GET v3/products with a filter on sku to find out whether products exist. The filter accepts several comma-separated SKUs, so you can check a batch of products in one request. Each SKU must be URL encoded, because a comma inside a SKU would otherwise split it in two.

GET {host}/v3/products?filter[sku][in]=VDB-400,TSH-000-S HTTP/1.1
Accept: application/json

The response contains a product resource for every SKU that exists. A SKU that's missing from data doesn't exist yet:

{
"data": [
{
"id": 540935,
"type": "product",
"attributes": {
"sku": "VDB-400",
"status": "AVAILABLE",
"stockLevelType": "AVAILABLE",
"name": "Van Dyke Brown - 400ml tube",
"hasBarcode": true,
"barcode": "8719558651276"
},
"links": {
"self": "https://shopapi.activeants.nl/v3/products/540935"
}
}
],
"links": {
"self": "https://shopapi.activeants.nl/v3/products?filter[sku][in]=VDB-400,TSH-000-S"
}
}

The example is shortened; the full set of attributes is described in GET v3/products. If you already stored the id of a product, you can skip the lookup and update it right away.

Creating a product​

Create a product that doesn't exist yet with POST v3/products:

POST {host}/v3/products HTTP/1.1
Content-Type: application/json
Accept: application/json

{
"data": {
"type": "product",
"attributes": {
"sku": "TSH-000-S",
"status": "AVAILABLE",
"stockLevelType": "ECONOMIC",
"name": "Dog Shampoo 100ml",
"description": "Gentle shampoo for dogs, with natural ingredients.",
"hasBarcode": true,
"barcode": "8719558651306",
"hasLotNumber": true,
"hasSerialNumber": false,
"hasExpirationDate": false,
"countryOfOrigin": "CN",
"hsCodes": [
{ "country": "XX", "hsCode": "33079011" }
]
}
}
}

The server responds with 201 Created and the new product, including its id. Store the id in your application.

Keep the following in mind:

  • The sku and barcode must be unique, and can't have been used before for another product. A duplicate results in 409 Conflict.
  • stockLevelType sets which stock level you use to synchronize the stock of this product: ECONOMIC or AVAILABLE. See Stock Level Synchronization.
  • The weight, length, width and height are measured when the product is first received in a warehouse, and can't be set through the API.

Updating a product​

Update an existing product with PUT v3/products/:id, using the id from Paxon:

PUT {host}/v3/products/1267734 HTTP/1.1
Content-Type: application/json
Accept: application/json

{
"data": {
"id": 1267734,
"type": "product",
"attributes": {
"sku": "TSH-000-S",
"status": "AVAILABLE",
"stockLevelType": "ECONOMIC",
"name": "Dog Shampoo 100ml - Sensitive Skin",
"description": "Gentle shampoo for dogs with sensitive skin, with natural ingredients.",
"hasBarcode": true,
"barcode": "8719558651306",
"hasLotNumber": true,
"hasSerialNumber": false,
"hasExpirationDate": false,
"countryOfOrigin": "CN",
"hsCodes": [
{ "country": "XX", "hsCode": "33079011" }
]
}
}
}

PUT replaces the product: always send all attributes, because attributes you leave out may be erased. Some attributes can't be changed and result in 409 Conflict:

  • The sku can never be changed.
  • The barcode can only be changed as long as there's no stock of the product.
  • The weight, length, width and height are determined by the warehouse.

Retrieving all products​

To check that both systems contain the same products, for example during the initial setup or a periodic check, retrieve all your products with GET v3/products. This endpoint uses cursor-based pagination and returns at most 100 products per page, ordered by id.

Start with the first page:

GET {host}/v3/products?page[size]=100 HTTP/1.1
Accept: application/json

The response contains the products and a next link to the following page:

{
"data": [
/** up to 100 products **/
],
"links": {
"self": "https://shopapi.activeants.nl/v3/products?page[size]=100",
"first": "https://shopapi.activeants.nl/v3/products?page[cursor]=0&page[size]=100",
"next": "https://shopapi.activeants.nl/v3/products?page[cursor]=540938&page[size]=100"
}
}

Request the next link to get the following page, and repeat this until a page contains fewer products than the page[size], or has no next link. Use the links as they are, and don't build the cursor yourself:

let url = `${host}/v3/products?page[size]=100`;
while (url) {
const page = await get(url);
for (const product of page.data) {
// Compare with your application, and store the id by sku
}
url = page.data.length < 100 ? null : page.links?.next;
}

Rate limits​

The endpoints are rate limited, and exceeding a limit results in 429 Too Many Requests. The current limits are listed with each endpoint: GET v3/products, POST v3/products and PUT v3/products/:id. To stay within the limits:

  • Store the id of each product, so you don't need a lookup before every update.
  • Look up products in batches with filter[sku][in], instead of one request per product.
  • Only send products that changed in your application.