Documentation Index
Fetch the complete documentation index at: https://packageretriever.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
Tracking & Webhooks
Tracking
Register a tracking number to monitor shipment progress:
const tracker = await pr.trackers.create({
tracking_number: '9400111899223408065744',
carrier: 'USPS'
});
Poll for updates:
const status = await pr.trackers.get(tracker.id);
console.log(status.status); // 'in_transit', 'delivered', etc.
console.log(status.events); // Full chronological event history
Tracking event statuses
| Status | Meaning |
|---|
pre_transit | Label created, not yet scanned |
in_transit | Package picked up and moving |
out_for_delivery | On vehicle for final delivery |
delivered | Confirmed delivered |
exception | Delivery issue (return to sender, held, etc.) |
unknown | Carrier status could not be normalized |
Each event includes the raw carrier message in status_detail for cases where our normalized status isn’t specific enough.
Polling frequency
Our tracking data is updated every 4 hours via carrier API polling. For real-time needs, poll GET /v1/trackers/:id as frequently as your rate limit allows (300/min).
Webhooks
Package Retriever pushes one webhook event: label.created. This fires immediately after a successful label purchase.
Setup
Configure your webhook URL in the dashboard (Apps & Tools → Unleashed tab → Webhook section). You’ll receive a signing secret at configuration time.
Payload
{
"event": "label.created",
"data": {
"id": "lbl_8k2m4n6p",
"carrier": "USPS",
"service": "Ground Advantage",
"tracking_number": "9400111899223408065744",
"rate_cents": 542,
"label_url": "https://api.packageretriever.com/v1/labels/lbl_8k2m4n6p/download",
"created_at": "2026-05-16T14:32:00Z"
},
"timestamp": "2026-05-16T14:32:01Z"
}
Signature verification
Every webhook is signed with HMAC-SHA256. Verify the PR-Signature header:
Node.js:
import crypto from 'crypto';
function verifyWebhook(payload: string, signature: string, secret: string): boolean {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return signature === `sha256=${expected}`;
}
// In your handler:
app.post('/webhooks/pr', (req, res) => {
const payload = JSON.stringify(req.body);
const signature = req.headers['pr-signature'] as string;
if (!verifyWebhook(payload, signature, process.env.PR_WEBHOOK_SECRET!)) {
return res.status(401).send('Invalid signature');
}
// Process the event
const { event, data } = req.body;
console.log(`Label created: ${data.tracking_number}`);
res.status(200).send('OK');
});
Python:
import hmac
import hashlib
def verify_webhook(payload: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(
secret.encode(),
payload,
hashlib.sha256
).hexdigest()
return signature == f"sha256={expected}"
Retry schedule
If your endpoint doesn’t return a 2xx response, we retry:
| Attempt | Delay |
|---|
| 1 | Immediate |
| 2 | 5 minutes |
| 3 | 30 minutes |
| 4 | 2 hours |
| 5 | 24 hours |
After 5 failed attempts, the delivery is marked as failed. You can view all delivery attempts in the dashboard (Apps & Tools → Unleashed → Webhook Deliveries).
Delivery log
View your last 50 webhook deliveries via the dashboard or API:
const deliveries = await fetch('https://api.packageretriever.com/v1/webhooks/deliveries', {
headers: { 'Authorization': `Bearer ${apiKey}` }
});
Each entry shows: status, response code, attempts, timestamps.
Best practices
- Always return 200 quickly (process the payload asynchronously)
- Verify the signature before processing
- Handle duplicate deliveries idempotently (use
data.id as deduplication key)
- If your endpoint is down, deliveries retry for up to 24 hours