Placing orders
A Hub order goes: read the catalogue → build a cart of item ids and
quantities → POST the order → track status until it settles. Prices never
travel with the cart — Hub derives them from the synced catalogue on the
server.
-
Read the catalogue
Section titled “Read the catalogue”Browse the community catalogue — member stores, categories and items with modifier groups, as mirrored from each merchant. Use
store_idto fetch a single store’s slice andupdated_sincefor incremental refreshes:Terminal window curl -s "https://hub-api.quiqqy.ai/api/v2/communities/com_4hx7d2/catalogue?store_id=st_8fk2c1p9" \-H "Authorization: Bearer $ACCESS_TOKEN"Item detail lives at
/communities/{communityId}/catalogue/items/{itemId}. Cache catalogue reads briefly and honourmenu-managementavailability — an unavailable item in the cart fails placement. -
Build the cart
Section titled “Build the cart”A cart is a list of lines, each naming the catalogue item, a quantity and any selected modifiers (plus the fulfilling store, recommended for explicitness). Lines may span several stores; Hub will split them into one child order per store.
-
Place the order
Section titled “Place the order”Terminal window curl -s "https://hub-api.quiqqy.ai/api/v2/communities/com_4hx7d2/orders" \-H "Authorization: Bearer $ACCESS_TOKEN" \-H 'Content-Type: application/json' \-H 'Idempotency-Key: 9f2c1e8a-7b6d-4c5e-8f9a-0b1c2d3e4f5a' \-d '{"fulfillment_type": "delivery","customer": {"name": "Anita R.","email": "anita@example.com","phone": "+919812345678"},"delivery_address": {"street_address": "14 Marine Drive, Apt 6C","city": "Kochi","state": "KL","country": "IN","zip": "682031"},"items": [{"item_id": "itm_9f8e7d6c5b4a","store_id": "st_8fk2c1p9","quantity": 2,"modifiers": [{ "modifier_id": "mod_3c4d5e6f7a8b", "quantity": 1 }]},{"item_id": "itm_5c4b3a2d1e0f","store_id": "st_5mq3n7v1","quantity": 2}],"tip": 200,"special_instructions": "Gate code 4471","payment": { "method": "card", "provider": "stripe" }}'const response = await fetch('https://hub-api.quiqqy.ai/api/v2/communities/com_4hx7d2/orders',{method: 'POST',headers: {Authorization: `Bearer ${accessToken}`,'Content-Type': 'application/json','Idempotency-Key': crypto.randomUUID(),},body: JSON.stringify({fulfillment_type: 'delivery',customer: {name: 'Anita R.',email: 'anita@example.com',phone: '+919812345678',},delivery_address: {street_address: '14 Marine Drive, Apt 6C',city: 'Kochi',state: 'KL',country: 'IN',zip: '682031',},items: [{item_id: 'itm_9f8e7d6c5b4a',store_id: 'st_8fk2c1p9',quantity: 2,modifiers: [{ modifier_id: 'mod_3c4d5e6f7a8b', quantity: 1 }],},],tip: 200,payment: { method: 'card', provider: 'stripe' },}),},);const order = await response.json();import uuidimport requestsresponse = requests.post("https://hub-api.quiqqy.ai/api/v2/communities/com_4hx7d2/orders",headers={"Authorization": f"Bearer {access_token}","Idempotency-Key": str(uuid.uuid4()),},json={"fulfillment_type": "delivery","customer": {"name": "Anita R.","email": "anita@example.com","phone": "+919812345678",},"delivery_address": {"street_address": "14 Marine Drive, Apt 6C","city": "Kochi","state": "KL","country": "IN","zip": "682031",},"items": [{"item_id": "itm_9f8e7d6c5b4a","store_id": "st_8fk2c1p9","quantity": 2,"modifiers": [{"modifier_id": "mod_3c4d5e6f7a8b", "quantity": 1}],}],"tip": 200,"payment": {"method": "card", "provider": "stripe"},},)order = response.json()Field notes:
Field Notes fulfillment_typedelivery,pickupordine_in— requiredcustomerRequired — nameplusemail/phone(Quiqqy finds-or-creates the community customer), or a knowncustomer_iditems[].item_idCatalogue item id; the line’s price comes from the catalogue, never from the request items[].store_idThe merchant store fulfilling that line — optional (inferred from the item) but recommended items[].modifiers[]Selected modifiers by modifier_id, withquantitypayment.methodcard,digital_wallet,cash,bank_transfer— required;payment.providernames the collector, e.g.stripedelivery_addressRequired for deliveryorderstip,expected_totalInteger minor units coupon_code,special_instructions,pickup_atOptional Idempotency-KeyheaderMakes retries safe — the same key returns the original order instead of creating a duplicate -
Track the order
Section titled “Track the order”Read the order back at
GET /communities/{communityId}/orders/{orderId}(or list withGET /communities/{communityId}/orders, filterable by status, store and date range), or skip polling entirely and subscribe toorder.status_changed.
Status ladder
Section titled “Status ladder”pending → confirmed → preparing → ready → out_for_delivery → delivered └──── (pickup ends at ready)any non-terminal state → cancelled| Status | Meaning |
|---|---|
pending | Placed; child orders forwarded to each store |
confirmed | Store(s) accepted |
preparing | Kitchen working |
ready | Ready for pickup / courier handoff |
out_for_delivery | Courier en route (delivery orders) |
delivered | Terminal success |
cancelled | Terminal — cancelled by shopper, store or operator |
Payment status is tracked separately: pending, processing, completed,
failed, refunded.
Cancelling an order
Section titled “Cancelling an order”POST /communities/{communityId}/orders/{orderId}/cancel cancels the parent
order and every child that has not yet reached a terminal state. Send a
customer-facing reason (free text) and, optionally, a structured
reason_code:
{ "reason": "Customer requested cancellation", "reason_code": "OTHER" }Cancellation is only possible while no child is out_for_delivery or later —
after that the call returns 409 order.not_cancellable. Paid orders move to
payment_status: refunded once the refund settles. Details in the
Hub Ordering reference.