Skip to main content

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

StatusMeaning
pre_transitLabel created, not yet scanned
in_transitPackage picked up and moving
out_for_deliveryOn vehicle for final delivery
deliveredConfirmed delivered
exceptionDelivery issue (return to sender, held, etc.)
unknownCarrier 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:
AttemptDelay
1Immediate
25 minutes
330 minutes
42 hours
524 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