Product synchronisation
PUT /api/v1/businesses/{businessId}/sync/products — scope products:write, application tokens only.
{
"products": [{
"externalId": "menu-981",
"name": "Kota — The Works",
"description": "Quarter loaf, chips, polony, cheese, egg",
"category": { "externalId": "cat-12", "name": "Kotas" },
"imageUrl": "https://cdn.example.com/kota.jpg",
"taxClass": "STANDARD",
"type": "STANDARD",
"isActive": true,
"variants": [
{ "externalId": "menu-981", "name": "Default", "sku": "KOTA-WORKS", "price": "65.00", "barcodes": [] }
],
"modifierGroups": [
{ "name": "Extras", "minSelect": 0, "maxSelect": 3, "modifiers": [{ "name": "Extra cheese", "priceDelta": "8.00" }] }
]
}]
}
Up to 200 products per call (pos.products.syncAll batches for you).
Behaviour
- Upsert by external ID. First sight creates the product, its variants and category and records the mappings; later calls update.
- Unchanged is free. Each product's payload is hashed; an identical resend is reported
unchangedand touches nothing. - Per-product transactions. One bad product (say a SKU clash) fails alone; the run is
PARTIALand the rest are saved. - Ownership respected. Fields POS owns are not overwritten; differing values become conflicts. See Connector specification §6.
- Removed variants (no longer in the payload) are archived, never deleted — past sales still reference them.
- Prices are in the business's display basis (VAT-inclusive for most South African businesses).
taxClassisSTANDARD,ZERO_RATEDorEXEMPT; VAT is computed by POS from effective-dated rates. - Events. Each created or updated product emits
product.created/product.updatedwith asourcefield naming your application — ignore events you caused to avoid loops.
Response
{ "data": {
"run": { "id": "…", "status": "SUCCEEDED", "created": 1, "updated": 0, "unchanged": 0, "failed": 0, "conflicts": 0, "errors": [] },
"results": [{ "externalId": "menu-981", "productId": "cm…", "status": "created", "variants": [{ "externalId": "menu-981", "variantId": "cm…" }] }]
} }
Every run is stored as a SyncRun and visible to the business under Integrations and to TechTur in the Control Centre.
Reading back
GET …/products?updatedSince=2026-11-01T00:00:00Z— products changed in POS.GET …/mappings?entityType=variant&externalId=…— resolve one of your IDs.