Orders, delivery tracking & returns

“Where is my order?” is the single most common question an online business receives. This guide shows how your bot answers it from live order, courier and tracking data — from Shopify, WooCommerce and other shop platforms, or from your own system through Account Connect — and how to handle returns and refunds honestly when there is no returns system to read.
10 min readhttps://www.siluxchat.comcurl · Python · PHP · Node.js

Overview

Once a customer is verified, the bot reads that customer’s recent orders and answers with the real status, the courier and the tracking number. It does not estimate delivery dates your system has not given it, and it never reports an order as delivered unless your data says so.

Ready-made shop connectors

Shopify, WooCommerce, BigCommerce, Magento, Wix, Squarespace, Etsy, eBay and more — connect in Dashboard → Integrations → Connectors with a read-only key. No code.

Your own order system

Implement POST /orders as one of the five Account Connect endpoints. It receives a session token and returns that customer’s orders.

The “where is my order?” journey

  1. 1
    The customer asks about an order. The bot asks for their full name plus an email address or mobile number (connectors look the customer up by email or mobile; a postcode can be the extra check).
  2. 2
    A one-time code is sent to the contact details already held for that customer — never to a number typed in the chat. The customer types the code and a 30-minute session starts.
  3. 3
    The bot calls the orders endpoint with the session token. For a connector that isPOST https://www.siluxchat.com/api/connect/{connection_id}/orders; for your own system it is POST {your base}/orders.
  4. 4
    The bot answers from the rows returned: “Order ORD-50231, placed on 20 September, has been dispatched with Royal Mail Tracked 48. The tracking number is TT123456789GB.”
  5. 5
    If the customer has several orders, the bot asks which one they mean, or answers about the most recent.

Why verification comes first

An order record reveals a name, a delivery address and what someone bought. Order calls are blocked in code until verification has succeeded in that conversation, so an order number alone is never enough to read someone else’s delivery.

The order shape

Every source is mapped to the same fields. order_number and placed must be present for a row to count; the rest are included when the source has them. Money reported in minor units (pence or cents) is converted to pounds, and dates are normalised to YYYY-MM-DD.

FieldMeaningExample
order_numberThe order reference the customer sees on their confirmationORD-50231 or #1001
placedDate the order was placed2026-09-20
statusFulfilment or payment status from your systemdispatched
totalOrder total39.99
currencyWhere the source provides itGBP
courierCarrier nameRoyal Mail Tracked 48
trackingTracking numberTT123456789GB

Some shop connectors also map a refunded amount or the customer’s email on the order. When an email is present, a safety net drops any order that names a different customer’s email address, whatever the vendor’s search returned.

Orders from your own system (Account Connect)

POST{your base}/ordersX-API-Key: your key

Request body: {"session_token": "…"}. Return HTTP 200 with {"success": true, "orders": [...]}, or HTTP 401 when the session is unknown or has expired.

Read orders for a verified customer (live demo)
# export SESSION=<the session_token returned by POST /verify-otp>
: "${SESSION:?export SESSION first}"
curl -s -X POST "https://www.siluxchat.com/api/account-connect-demo/v1/orders" \
  -H "X-API-Key: demo-account-connect-key" \
  -H "Content-Type: application/json" \
  -d "{\"session_token\":\"$SESSION\"}"
Response — Test Customer
{
  "success": true,
  "orders": [
    {
      "order_number": "ORD-50231",
      "placed": "2026-09-20",
      "status": "dispatched",
      "courier": "Royal Mail Tracked 48",
      "tracking": "TT123456789GB"
    }
  ]
}
Response — Jane Demo (no orders)
{
  "success": true,
  "orders": []
}

The whole flow, copy and paste

orders-demo.sh
BASE=https://www.siluxchat.com/api/account-connect-demo/v1
KEY=demo-account-connect-key

# 1. Identify Test Customer (the demo never sends a text; the code is always 123456)
OTP=$(curl -s -X POST $BASE/verify-identity -H "X-API-Key: $KEY" -H 'Content-Type: application/json' \
  -d '{"full_name":"Test Customer","postcode":"TE5 7ST"}' | python3 -c 'import sys,json;print(json.load(sys.stdin)["otp_token"])')

# 2. Exchange the code for a session token
SESSION=$(curl -s -X POST $BASE/verify-otp -H "X-API-Key: $KEY" -H 'Content-Type: application/json' \
  -d "{\"otp_token\":\"$OTP\",\"otp_code\":\"123456\"}" | python3 -c 'import sys,json;print(json.load(sys.stdin)["session_token"])')

# 3. Read the customer's orders
curl -s -X POST $BASE/orders -H "X-API-Key: $KEY" -H 'Content-Type: application/json' -d "{\"session_token\":\"$SESSION\"}"; echo

Recommendations

  • Return the most recent orders first — the last 10 is ample. The bot reads roughly the first 2,000 characters of a response.
  • Use statuses a customer understands: processing, dispatched, out for delivery, delivered,cancelled, returned, refunded. Translate internal warehouse codes before returning them.
  • Include the courier and tracking number as soon as a parcel is dispatched; if you have a courier tracking link, add it as an extra field (for example tracking_url) and the bot can share it.
  • An estimated delivery date is helpful only if your system genuinely has one — add it as eta. The bot will not make one up.
  • Never return another customer’s orders; filter by the customer bound to the session token only.

Looking up one order by number

Dashboard → Integrations also offers a Track Order template: an endpoint on your system that receives{"order_number": "ORD-12345"} and returns that order’s status, courier and tracking number. It is marked as requiring verification, so it runs only for a customer who has passed the one-time-code check. Use it when your customers typically quote an order number and you already have a “find order” API.

Example response your Track Order endpoint could return
{
  "order_number": "ORD-12345",
  "status": "dispatched",
  "courier": "DPD",
  "tracking": "15501234567890",
  "eta": "2026-09-28"
}

Check the order belongs to the customer

An order number is easy to guess or share. Your Track Order endpoint should confirm the order belongs to the verified customer before returning a delivery address or item details — or return status and tracking only.

Shop and payment connectors with orders

These connectors read a verified customer’s orders. Each page lists where to create the read-only key in the vendor’s admin, the permissions to grant and the exact fields mapped.

Try it end to end with no vendor account: connect the Silux Demo Store using the key demo-account-connect-key. It reads from a demo shop API with fictional customers:

The demo vendor API the Silux Demo Store connector reads
curl -s "https://www.siluxchat.com/api/account-connect-demo/v1/vendor/orders?customer_id=C1001" \
  -H "X-API-Key: demo-account-connect-key"
Response
{
  "orders": [
    {
      "order_number": "ORD-50231",
      "placed": "2026-09-20",
      "status": "dispatched",
      "courier": "Royal Mail Tracked 48",
      "tracking": "TT123456789GB"
    }
  ]
}

Couriers and tracking connectors

Courier and shipping-platform connectors (AfterShip, Royal Mail Click & Drop, ShipStation, DHL, UPS, FedEx and others) carry an order tracking capability. Connected, it becomes your bot’s Track My Parcel tool: the customer gives the tracking number from their dispatch email or text and the bot answers with the live status and courier.

Customer givesVerificationWhat comes back
A tracking number (8+ letters and digits)Not neededOnly order_number, status, tracking, courier — and only for a parcel whose tracking number is exactly the one given
An order numberRequired (a session from the same connection)That order’s tracking row — only if the order belongs to the verified customer
A short number such as 1002—Refused on the unverified path: “That doesn’t look like a tracking number…”

Why a tracking number needs no verification

The customer already holds the number, and it is the same key the courier’s own public tracking page takes. The bot returns nothing personal — no name, address, email, price or delivery history — and a result only when the courier holds a parcel with exactly that number, so guessing order numbers can never reveal someone else’s parcel or hand out a tracking number. An order number is easy to guess, so it needs verification and must belong to the verified customer.

Switching it on

  • Connect the courier in Dashboard → Integrations → Connectors. If your bot has no parcel tracking yet, Track My Parcel is switched on automatically once the tracking test passes.
  • To choose which connection answers tracking, press Use for tracking on it (POST /api/tenants/{tenant_id}/connectors/{id}/use-for-tracking).
  • Some shipping platforms (AfterShip, ShipStation, Printful) also hold the customer’s name and email on each order, so they can verify customers too — see identity verification.
POSThttps://www.siluxchat.com/api/connect/{connection_id}/order-statusX-API-Key
FieldTypeNotes
tracking_numberstringThe carrier tracking number. No session needed.
order_numberstringOnly with session_token (from this connection’s verify-otp).
postcodestring, optionalPassed to carriers that need it with the number (Parcel2Go).
session_tokenstring, optionalA verified session of the same connection; any other session is ignored.
Request
{"tracking_number": "TT123456789GB"}
Response
{
  "success": true,
  "orders": [
    {"order_number": "1001", "status": "InTransit",
     "tracking": "TT123456789GB", "courier": "royal-mail"}
  ]
}
SituationResponse
No parcel with that number{"success": true, "orders": [], "message": "No parcel with that tracking number was found in <Name>."}
Order number without a verified session{"success": false, "needs_verification": true, "message": "Looking an order up by its order number needs the customer to be verified first. …"}
Courier unreachable or key refused{"success": false, "system_error": true, "message": "We can't check tracking right now — our team has been told."}
Connector has no tracking{"success": true, "orders": [], "message": "<Name> does not hold tracking information"}

Returns and refunds

There is no separate returns endpoint, and the bot does not pretend there is. Returns are handled in three honest steps:

  1. 1
    Policy from your knowledge base. The bot explains your returns window, condition rules and how to send an item back from the returns policy you have added to your knowledge base.
  2. 2
    Status from your order data. If your system reports return or refund progress on the order — statuses such asreturn requested, returned or refunded, or a refunded amount — the bot reads it like any other status.
  3. 3
    A ticket for the request itself. When a customer wants to start a return, the bot raises a support ticket for your team with the order number and reason, and tells the customer a person will follow it up.

Want return status in the chat?

Add it to your order rows (a status or a return_status field on each order), or include a short returns array in your account-summary response. The bot reads whatever you return, so no extra endpoint is needed.

Errors and edge cases

SituationWhat the bot receivesWhat the customer hears
No orders for this customer{"success": true, "orders": []}“I can’t see any orders on your account” — and it may ask whether they used another email.
Connector does not hold orders{"success": true, "orders": [], "message": "<Name> does not hold orders"}Says it cannot see orders from here and offers your team.
Shop unreachable or key revoked{"success": false, "system_error": true, "message": "We can't read orders right now — our team has been told."}Says it cannot check right now — never “you have no orders”.
Vendor rate-limits the requestRetried automatically (up to 3 attempts, honouring Retry-After)Usually nothing; persistent limits surface as the system error above.
Session expiredHTTP 401 — “Session expired — please verify again.”The bot asks the customer to verify again.
Customer ordered as a guest with another emailNo match at verificationAsked for the email or mobile used on the order.

Full status-code reference and fixes: Troubleshooting. To try every call safely first, see Testing with the live demo.

Get help

Running a platform that is not listed, or a warehouse system with its own order API? Email support@siluxcall.co.uk with the system name and an anonymised sample of an order — our integration team will recommend the quickest route.

Need help with your integration?

Our integration team can review your endpoints, help you choose the right connector and check a test run with you. Tell us which system you use and what you would like the bot to answer.

support@siluxcall.co.uk