track_shipment: skill contract
track_shipment returns tracking for an order. Like order_status, it is customer-scoped: every call includes the customer_email the agent supplied, and your endpoint must confirm that email owns the order before returning anything.
Check the customer first
Section titled “Check the customer first”Request: { "order_id": "#1001", "customer_email": "[email protected]" }
1. Look up order #1001.2. Compare its customer email with "[email protected]".3. Match: look up the shipment and return it in the response shape below.4. No match, or no such order: return 404 with an empty body.If you skip step 2, anyone who guesses an order number can get its carrier, tracking number and delivery date through an agent.
Compare the emails the same way as for order_status: normalize both, compare in constant time (see the compare function), and return the same 404 for a wrong email as for an order that does not exist. A 404 reaches the agent as “not found” and does not affect your endpoint’s health.
Request
Section titled “Request”Machine-readable: /skills/v1/track_shipment.request.schema.json
| Field | Type | Required | Notes |
|---|---|---|---|
order_id | string | yes | The order number the customer knows, or your internal ID. 1–128 chars. |
customer_email | string | yes | The email the agent says owns the order. Not verified by Sill. 3–320 chars. |
{ "additionalProperties": false, "properties": { "customer_email": { "maxLength": 320, "minLength": 3, "type": "string" }, "order_id": { "maxLength": 128, "minLength": 1, "type": "string" } }, "required": ["order_id", "customer_email"], "type": "object"}Example request
Section titled “Example request”{ "skill_id": "track_shipment", "site_id": "01EXAMPLE00000000000000000", "arguments": { "order_id": "#1001", }, "observed_at": "2026-07-05T18:22:15.140Z", "nonce": "01K1EXAMPLE0000000000000000"}Response
Section titled “Response”Machine-readable: /skills/v1/track_shipment.response.schema.json
Only order_id is required, so an order that has not shipped yet can be answered with { "order_id": "#1001", "status": "not_yet_shipped" }.
| Field | Type | Required | Notes |
|---|---|---|---|
order_id | string | yes | Echo the order id. 1–256 chars. |
tracking_number | string | no | Carrier-issued tracking number. 1–256 chars. |
carrier | string | no | Carrier name / code. 1–256 chars. |
status | string | no | Free text, 1–64 chars. Common values: not_yet_shipped, in_transit, delivered, cancelled, or the carrier’s own status. |
expected_delivery | string | no | Expected delivery, ISO-8601 UTC. 20–40 chars. |
tracking_url | string | no | The carrier’s tracking page. Use an HTTPS URL. 1–2048 chars. |
Return only these fields. A response with any other field, such as the customer’s name, shipping address or phone, fails the schema: it is not passed to the agent and counts as a failed call (3 failures in a row mark the skill UNREACHABLE).
{ "additionalProperties": false, "properties": { "carrier": { "maxLength": 256, "minLength": 1, "type": "string" }, "expected_delivery": { "maxLength": 40, "minLength": 20, "type": "string" }, "order_id": { "maxLength": 256, "minLength": 1, "type": "string" }, "status": { "maxLength": 64, "minLength": 1, "type": "string" }, "tracking_number": { "maxLength": 256, "minLength": 1, "type": "string" }, "tracking_url": { "maxLength": 2048, "minLength": 1, "type": "string" } }, "required": ["order_id"], "type": "object"}Example response — shipment in transit
Section titled “Example response — shipment in transit”{ "order_id": "#1001", "tracking_number": "1Z999AA10123456784", "carrier": "UPS", "status": "in_transit", "expected_delivery": "2026-07-08T00:00:00.000Z", "tracking_url": "https://www.ups.com/track?tracknum=1Z999AA10123456784"}Example response — before shipping
Section titled “Example response — before shipping”{ "order_id": "#1001", "status": "not_yet_shipped"}When to return 404
Section titled “When to return 404”Return 404 with an empty body when the order does not exist or the email does not match the order’s customer email. Do not return an invented status instead: it tells the caller the order number exists.
What Sill checks
Section titled “What Sill checks”Sill checks every 2xx response against the response schema. A response that fails is not passed to the agent and counts as a failed call; 3 failures in a row mark the skill UNREACHABLE. Common causes are an extra field such as shipping_address, and a status longer than 64 characters.
Sill cannot check that the email matched. Run the self-test with your own orders to confirm it.
Verify the signature
Section titled “Verify the signature”Check the X-Sill-Signature header on every request before answering. The scheme is the same for every skill; see Verify the signature for tested TypeScript, Python and Go code.
See also
Section titled “See also”- Contract overview — request envelope, response handling and signature code.
order_status— the sibling customer-scoped skill.