Poll tracking updates
Use GET /tracking/{id} to retrieve real-time shipment tracking data in a unified format. This guide covers the polling flow, how to interpret tracking statuses, and patterns for building customer notifications.
Retrieve tracking data
Use the id from the label creation response:
curl https://api.flexforward.com/tracking/f47ac10b-58cc-4372-a567-0e02b2c3d479 \
-H "Authorization: Bearer YOUR_API_TOKEN"
Response
{
"id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"trackingNumber": "YT2503010001CN",
"tag": "InTransit",
"subtag": "InTransit_001",
"subtagMessage": "In transit",
"slug": "yunexpress",
"checkpoints": [
{
"checkpointTime": "2026-03-17T08:15:00Z",
"city": "Los Angeles",
"state": "CA",
"countryRegion": "US",
"location": "LAX Distribution Center",
"message": "Arrived at destination country",
"tag": "InTransit",
"subtag": "InTransit_001",
"subtagMessage": "In transit",
"slug": "yunexpress"
},
{
"checkpointTime": "2026-03-16T02:30:00Z",
"city": "Shenzhen",
"state": "Guangdong",
"countryRegion": "CN",
"location": null,
"message": "Departed from sorting center",
"tag": "InTransit",
"subtag": "InTransit_001",
"subtagMessage": "In transit",
"slug": "yunexpress"
},
{
"checkpointTime": "2026-03-15T10:30:00Z",
"city": "Tokyo",
"state": "Tokyo",
"countryRegion": "JP",
"location": null,
"message": "Shipment information received",
"tag": "InfoReceived",
"subtag": "InfoReceived_001",
"subtagMessage": "Shipment information received",
"slug": "yunexpress"
}
]
}
Checkpoints are ordered with the most recent event first.
Understand the tracking status
Use the top-level tag field for high-level status logic:
| Tag | Customer-facing meaning | Action |
|---|
Pending | Order is being processed | No notification needed |
InfoReceived | Shipment registered with courier | Notify: “Your order has shipped” |
InTransit | Package is on the way | Notify: “Your package is in transit” |
Delivered | Package delivered | Notify: “Your package has been delivered” |
Exception | Delivery issue | Notify: “There’s an issue with your delivery” and investigate |
Cancelled | Shipment cancelled | Handle internally |
Unknown | Status unavailable | No notification — retry later |
Polling pattern
Since webhooks are not currently available, poll GET /tracking/{id} at a reasonable interval to detect status changes.
Recommended approach
async function pollTracking(labelId, token) {
let lastTag = null;
const interval = setInterval(async () => {
const response = await fetch(
`https://api.flexforward.com/tracking/${labelId}`,
{ headers: { 'Authorization': `Bearer ${token}` } }
);
const tracking = await response.json();
if (tracking.tag !== lastTag) {
lastTag = tracking.tag;
await notifyCustomer(tracking); // Your notification logic
}
// Stop polling when shipment reaches a terminal state
if (['Delivered', 'Cancelled'].includes(tracking.tag)) {
clearInterval(interval);
}
}, 30 * 60 * 1000); // Every 30 minutes
}
Polling guidelines
| Shipment stage | Recommended interval |
|---|
Pending / InfoReceived | Every 4–6 hours |
InTransit | Every 30–60 minutes |
Delivered / Cancelled | Stop polling |
Exception | Every 15–30 minutes until resolved |
Tracking data is fetched from the courier in near-real-time. Polling more frequently than every 15 minutes is unlikely to yield new data and counts against the recommended rate limit of 10 requests per second.
Error handling
| Status | Meaning | Action |
|---|
| 200 | Tracking data retrieved | Process the tag and checkpoints |
| 403 | Access denied | The label belongs to a different account |
| 404 | Label not found | Verify the label ID is correct |
| 502 | Upstream service error | Retry with exponential backoff |
Next steps