API
Orders
Turn a WhatsApp conversation into a confirmed order: stock is reserved, the customer is recognised or created, and — where the company has switched it on — the courier is booked without anyone opening the order.
Create an order
POST/orders
Send JSON with Content-Type: application/json, up to 32 KB.
curl -X POST "https://www.chatcom.in/api/v1/urbanchat/orders" \
-H "X-API-KEY: $UC_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"customer": {
"name": "Anjali Menon",
"phone": "+91 98765 43210",
"email": "anjali@example.com"
},
"items": [
{
"product_id": "TSHIRT-RED-M",
"quantity": 2
},
{
"product_id": "TSHIRT-BLU-L",
"quantity": 1
}
],
"external_reference": "wa-conv-8f2c1e-order-1",
"notes": "Gift wrap, please.",
"delivery_address": {
"line1": "12/4 MG Road, Ravipuram",
"line2": "Opposite the bus stop",
"city": "Kochi",
"pincode": "682016"
},
"payment": "prepaid",
"payment_reference": "UPI 412345678901"
}'Body
customer.namestringrequired- Up to 120 characters.
customer.phonestringrequired- Any format. The customer with this number is used, or created if there is none. Must be a number WhatsApp can reach.
customer.emailstring- Saved only when the customer is new. An email already on file is never changed.
itemsarrayrequired- 1–50 lines. The same product twice is merged into one line.
items[].product_idstringrequired- A variant’s
sku(recommended),variant_idorbarcode, from the catalogue. items[].quantitynumber | stringrequired- Greater than zero, up to three decimal places.
2and"2"are the same. external_referencestringrequired- Your unique id for this order, up to 100 characters. See Idempotency below.
notesstring- Up to 500 characters, shown to staff on the order.
delivery_addressobject- Where this order goes. Strongly recommended — see Delivery below.
delivery_address.line1stringrequired- House, street and area.
delivery_address.line2string- Landmark or second line.
delivery_address.citystringrequired- Town or city.
delivery_address.pincodestringrequired- Six-digit Indian PIN code.
delivery_address.statestring- Optional: worked out from the PIN. Needed only for the few PINs two states share.
delivery_address.namestring- The recipient, when not the customer.
delivery_address.phonestring- A phone for the courier, when not the customer’s.
payment"cod" | "prepaid"codif the courier should collect the amount on delivery;prepaid(the default) if it is already paid.payment_referencestring- For a prepaid order, the payment’s own reference — a UPI transaction id, for example. Shown to staff on the order.
Response
201 Created — the order exists, is confirmed, and its stock is reserved.amount is the total including GST.
{
"data": {
"order_id": "cmg5a9d3k0007ab12cd34ef56",
"order_number": "SO-2627-0042",
"order_status": "confirmed",
"amount": "1623.30",
"currency": "INR",
"created_at": "2026-10-13T07:42:11.000Z",
"external_reference": "wa-conv-8f2c1e-order-1",
"items": [
{
"sku": "TSHIRT-RED-M",
"name": "Cotton T-shirt (Red / M)",
"quantity": "2",
"unit_price": "499.00",
"line_total": "1047.90"
},
{
"sku": "TSHIRT-BLU-L",
"name": "Cotton T-shirt (Blue / L)",
"quantity": "1",
"unit_price": "549.00",
"line_total": "576.45"
}
],
"payment": "prepaid",
"delivery_address": {
"name": null,
"line1": "12/4 MG Road, Ravipuram",
"line2": "Opposite the bus stop",
"city": "Kochi",
"state": "Kerala",
"pincode": "682016",
"phone": null
}
}
}Idempotency and retries
external_reference makes order creation safe to retry. Use something unique to the order in your system — the conversation id plus a counter works well.
- A request with a reference already used answers
200with"duplicate": trueand the original order. Nothing new is created. - After a timeout or a
500, retry with the same reference. If the first attempt got far enough to create the order, the retry finishes it instead of creating another. - A new order for the same customer needs a new reference.
Delivery and shipping
delivery_addressis where this order is shipped, even if the customer’s record holds a different address. A new customer, or one with no address on file, gets it saved to their record too; an address already on file is never overwritten from a chat.- Where the company has turned on automatic booking, the courier is booked as soon as the order is confirmed. An order with no usable address is still created and confirmed, but waits for someone to add one — so send
delivery_addressto keep it hands-free. - For a PIN code that two states share, a missing or contradicting
stateis refused with400 validation_failednamingdelivery_address.state.
Errors
- 400
validation_failed - A missing or malformed field, or a phone number that cannot be used.
detailslists{ path, message }. - 404
not_found - An item that does not exist or is not for sale.
detailslists theproduct_ids. - 409
insufficient_stock - Not enough stock.
detailsgivesrequestedandavailablefor each short item. Nothing was created. - 413 / 415
validation_failed - Body over 32 KB, or not JSON.
- 422
unprocessable - The company has no active stock location to sell from.
- 500
internal - Our fault. Retry with the same external_reference.
Look up an order
GET/orders/{reference}?phone={phone}
{reference} is the order number (SO-2627-0042), the order_id, or your external_reference. The response adds the customer, the lines, the shipment with its tracking link, and the invoice with what is still due. Draft orders are never returned.
curl "https://www.chatcom.in/api/v1/urbanchat/orders/SO-2627-0042?phone=%2B919876543210" \
-H "X-API-KEY: $UC_API_KEY"{
"data": {
"order_id": "cmg5a9d3k0007ab12cd34ef56",
"order_number": "SO-2627-0042",
"order_status": "shipped",
"status_label": "Shipped",
"amount": "1623.30",
"currency": "INR",
"order_date": "2026-10-13T00:00:00.000Z",
"external_reference": "wa-conv-8f2c1e-order-1",
"customer": {
"name": "Anjali Menon",
"phone": "+919876543210"
},
"items": [
{
"sku": "TSHIRT-RED-M",
"name": "Cotton T-shirt (Red / M)",
"quantity": "2",
"unit_price": "499.00",
"line_total": "1047.90"
},
{
"sku": "TSHIRT-BLU-L",
"name": "Cotton T-shirt (Blue / L)",
"quantity": "1",
"unit_price": "549.00",
"line_total": "576.45"
}
],
"shipment": {
"awb": "EZ123456789IN",
"courier": "India Post",
"status": "in_transit",
"status_label": "In transit",
"tracking_url": "https://…",
"delivered_at": null
},
"invoice": {
"invoice_number": "INV-2627-0042",
"payment_status": "paid",
"total": "1623.30",
"amount_due": "0.00"
}
}
}Statuses
order_statusstringconfirmed,packed,shipped,delivered,cancelledorreturned.status_labelis the same in words, for showing a customer.shipment.statusstring | null- The courier’s latest state:
pending,booked,picked_up,in_transit,out_for_delivery,delivered,rto(returning to sender),cancelledorfailed.shipmentisnulluntil a parcel is booked. invoice.payment_statusstringunpaid,partial,paidoroverdue.amount_dueis what is still owed.