Guides
Guide: sync sales from a shop or POS
Send each order to Quilo once, linked to the right client, with a nightly or real-time job.
Approach#
For each order in your shop or point-of-sale system:
- Find the client by email (
GET /clients?email=) or your customer number (GET /clients?external_code=); create it if missing. - Create the sale with
receipt_no= your order number, andIdempotency-Key=order-<number>. - A
409 conflictmeans the sale is already in Quilo: skip it.
Shopify stores can use the built-in Shopify integration instead (Settings → Integrations & Shopify); use the API for other systems.
Python script (run nightly with cron)#
Python
import os, requests
API = f"{os.environ['QUILO_URL']}/api/v1"
S = requests.Session()
S.headers.update({"Authorization": f"Bearer {os.environ['QUILO_API_KEY']}", "Content-Type": "application/json"})
BRAND = os.environ["QUILO_BRAND_ID"]
def client_for(order):
r = S.get(f"{API}/clients", params={"email": order["email"], "limit": 1}, timeout=30)
r.raise_for_status()
if r.json()["data"]:
return r.json()["data"][0]["id"]
r = S.post(f"{API}/clients", json={
"brand_id": BRAND, "first_name": order["first_name"], "last_name": order["last_name"],
"email": order["email"], "external_code": order["customer_no"], "tags": ["shop"],
}, headers={"Idempotency-Key": f"customer-{order['customer_no']}"}, timeout=30)
r.raise_for_status()
return r.json()["id"]
def push(order):
r = S.post(f"{API}/sales", json={
"brand_id": BRAND, "client_id": client_for(order), "receipt_no": order["number"],
"purchased_on": order["date"], # YYYY-MM-DD
"items": ", ".join(i["title"] for i in order["items"])[:2000],
"total": round(order["total"], 2), "channel": "website",
}, headers={"Idempotency-Key": f"order-{order['number']}"}, timeout=30)
if r.status_code == 409:
return "already in Quilo"
r.raise_for_status()
return r.json()["id"]
for order in load_orders_since_yesterday(): # your shop's export
print(order["number"], push(order))Tips#
- Use one key per system (
Shop sync,POS Zurich), so the API keys page shows which system did what. - Totals are in the brand currency; convert before sending if your shop sells in several currencies.
- To correct a sale,
PATCH /sales/{id}; to remove it,DELETE /sales/{id}(owners, admins, managers). - Use the rate-limit helper for large back-fills.