The tracking number is the credential
A recipient has no account and will never make one. They arrive from an SMS, look at one parcel, and leave. So the tracking number itself is what grants access , and everything about the endpoint follows from accepting that.
It is sixteen characters and the endpoint answers not found identically for a malformed number, an unknown number, and a number that does not exist — telling them apart would make the number space enumerable one request at a time. Requests are rate limited per caller on top of that .
The response carries nothing that is not already printed on the label . Someone holding the number can already read all of it off the parcel in their hand.
Evidence · 5 claims
-
Knowing a tracking number is the only thing required to read that parcel's history.
-
A tracking number is exactly sixteen characters long.
-
A malformed tracking number and an unknown one produce the same response.
-
Tracking requests are limited to twenty per minute per caller.
-
The public tracking response contains nothing that is not already printed on the parcel's label.
What a scan proves, and what it doesn't
A scan is evidence that a barcode was read by a device at a moment. That is all it is, and three things follow that surprise people reading this data for the first time.
The time can be wrong. scanned_at is the handheld's clock . A device that has been offline in a depot basement for six hours may also have drifted.
The order is not arrival order. Batches upload late, so a scan can land after ones that happened later . A tracking history is ordered by when things happened, not by when Relay heard about them.
A quiet parcel is not a stopped parcel. Ten days without a scan marks it lost , but the gap before that is ordinary — a parcel on a trunk vehicle overnight is scanned at neither end until it arrives.
Evidence · 3 claims
-
scanned_at comes from the handheld's own clock and can be wrong.
-
A scan batch can arrive after scans that happened later, because handhelds upload only when they find signal.
-
A parcel with no scan for ten days is marked lost and a claim is opened automatically.
Ten days is the longest a legitimate parcel has ever gone quiet in this network, measured over two years.
stated by ana@example.com, confirmed 7 days ago
What a recipient can change
Rescheduling and redirecting both need a one-time code , because both change where a parcel physically goes and the tracking number alone is a number printed on a box that everyone who handled it has seen.
Neither is accepted once the parcel is out for delivery that day — the van is already loaded and sequenced, and the driver is still holding the stop.
Evidence · 19 claims
-
POST /v1/shipments — Book a shipment and mint a tracking number per parcel. It accepts CreateShipmentInput. It returns Shipment.
-
GET /v1/shipments — List the calling merchant's shipments, newest first. It returns Shipment[].
-
GET /v1/shipments/{id} — One shipment with all of its parcels. Required parameter: id (path). It returns Shipment.
-
POST /v1/shipments/{id}/cancel — Cancel before collection; fails once any parcel has been scanned. Required parameter: id (path). It returns Shipment.
-
GET /v1/parcels/{id}/label — The printable label as a PDF. Required parameter: id (path). It returns application/pdf.
-
GET /v1/track/{tracking_number} — Public tracking history for one parcel. Required parameter: tracking_number (path). It is callable without authentication. It returns TrackingEvent[].
-
POST /v1/track/{tracking_number}/reschedule — Pick another delivery day. Required parameter: tracking_number (path). It accepts RescheduleInput. It returns TrackingEvent.
-
POST /v1/track/{tracking_number}/redirect — Send it to a neighbour or a safe place instead. Required parameter: tracking_number (path). It accepts RedirectInput. It returns TrackingEvent.
-
POST /v1/scans — Upload a batch of scans taken while offline. Required parameter: Idempotency-Key (header). It accepts ScanBatch. It returns ScanBatchResult.
-
POST /v1/attempts — Record a failed delivery attempt with a reason and a photo. It accepts AttemptInput. It returns TrackingEvent.
-
GET /v1/routes/{id}/manifest — Today's sequenced stops for a driver, cacheable offline. Required parameter: id (path). It returns Stop[].
-
GET /v1/depots — Every depot and the postcodes it serves. It returns Depot[].
-
POST /v1/routes/{id}/sequence — Ask the routing engine to order the stops. Required parameter: id (path). It returns Route.
-
GET /track/{tracking_number} — Unversioned tracking; use /v1/track. Required parameter: tracking_number (path). It is callable without authentication. It returns TrackingEvent[]. It is deprecated.
-
EVENT parcel.delivered — Published when a delivery scan lands. It returns ParcelDeliveredEvent.
-
EVENT parcel.attempt-failed — Published when a courier records a failed attempt. It returns ParcelAttemptEvent.
-
EVENT parcel.exception — Published when a parcel is marked lost or begins returning. It returns ParcelExceptionEvent.
-
Rescheduling and redirecting both require a one-time code sent to the phone on the shipment.
-
Neither is accepted once the parcel is out for delivery that day.
What this document does not cover
Read this before trusting an absence. Something missing here is either out of scope below, listed as noticed-and-unaccounted-for, or nobody has looked.
What was read
- Relay data model erd · 13 subjects · read only to resolve references
- Relay API endpoints · 25 subjects · facts derived from it
- The journey of a parcel lifecycle · 12 subjects · read only to resolve references
Deliberately not covered
- What the merchant sees
- Merchants read tracking through the authenticated shipment API, which has a different response shape and different redaction rules. That is covered in the Relay system document.
- How the one-time code is generated and checked
- Not documented yet. This document says reschedule and redirect require one; nothing here says how long it lives or how many attempts are allowed.
- Notification content and timing
- Which SMS a recipient gets, and when, is owned by the notifier and is not modelled here.
- Tracking for partner-carrier parcels
- Not documented yet. Once a parcel leaves for a partner carrier the scan history goes quiet, and nothing here explains what a recipient sees.
Noticed and unaccounted for
- relay.endpoints: 8 of 25 subjects have no claim
- nothing is documented about CreateShipmentInput, Shipment, Parcel, TrackingEvent, ScanBatch, …
All 27 claims check out against the code and the review window as of this build.
Nothing matches that filter.