Agent skill
parcelLab Webhooks Skill
Receive and authenticate parcelLab post-purchase tracking webhooks. Use when setting up a parcelLab webhook endpoint, checking the HTTP Basic Authorization header, debugging 401s, or handling shipment events such as onDispatch, onOutForDelivery, onDelivered and onReturn.
Install this skill
npx skills add hookdeck/webhook-skills --skill parcellab-webhooks
parcelLab (post-purchase tracking and delivery notifications) sends a webhook to your HTTPS endpoint each time a consignment changes status. Payloads are not signed. parcelLab sets webhooks up for you from the URL and credentials you give it, and supports three authentication mechanisms: HTTP Basic, access token headers and OAuth 2.0. This skill covers HTTP Basic.
When to Use This Skill
- How do I receive parcelLab webhooks?
- How do I verify the parcelLab
Authorization: Basicheader? - Does parcelLab sign webhook payloads? (No: shared credentials only)
- Why does my parcelLab webhook endpoint return 401?
- How do I handle
onDispatch,onOutForDeliveryoronDeliveredevents?
Verification (core)
Give parcelLab a username and password along with your HTTPS URL. It sends them as Authorization: Basic base64(username:password). Split the decoded value on the first colon, then compare username and password each in constant time, evaluating both before deciding:
const crypto = require('crypto');
const sha = (buf) => crypto.createHash('sha256').update(buf).digest();
const safeEqual = (a, b) => crypto.timingSafeEqual(sha(a), sha(b)); // equal-length digests
function verifyParcellabRequest(headers, config = process.env) {
const { PARCELLAB_WEBHOOK_USERNAME: user, PARCELLAB_WEBHOOK_PASSWORD: pass } = config;
if (!user || !pass) return false; // never accept when unconfigured
const m = /^basic\s+([A-Za-z0-9+/]+={0,2})\s*$/i.exec(headers['authorization'] || '');
if (!m) return false;
const decoded = Buffer.from(m[1], 'base64');
const colon = decoded.indexOf(0x3a); // first colon only
if (colon < 0) return false;
const userOk = safeEqual(decoded.subarray(0, colon), Buffer.from(user));
const passOk = safeEqual(decoded.subarray(colon + 1), Buffer.from(pass));
return userOk && passOk; // no short-circuit
}
Return 401 for a missing or malformed header or any mismatch, 400 for a body that is not a JSON object, and 200 once handled. Read the body raw (express.raw({ type: '*/*' })) so any content type works, and parse JSON only after the credential check. Python and Next.js equivalents are in references/verification.md.
Static credentials authenticate the sender, not the body. There is no signature and no timestamp, so a captured request can be replayed and the body can't be proven untampered. Use HTTPS only (parcelLab doesn't support plain HTTP), keep the credential secret, and rotate it if it leaks. Deduplicate on
eventid.
Credentials must arrive on the first request. The docs don't say whether parcelLab sends Basic credentials preemptively, so assume it does. A
401+WWW-Authenticatechallenge flow won't work, and it won't work through Hookdeck either, which verifies the request as received.
For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.
Event Types
The event name is in the event field of the JSON body:
| Event | Fires when |
|---|---|
onCreated / onUpdated | A record is created or updated from retailer data |
onDispatch | First carrier scan (once per consignment) |
onScheduled | Carrier announces or changes the delivery day or window |
onOutForDelivery | Consignment is out for delivery |
onDelay / onInternalDelay | Carrier delay, or the consignment wasn't shipped in time |
onFailedAttempt | Delivery attempted but recipient not met or location not accessible |
onPickupReady | Ready for collection at an access point or locker |
onDelivered | Final: delivered |
onReturn | Final: being returned to the sender |
parcelLab can also send CloudEvents format, where type is com.parcellab.tracking.event.<lowercased event> and the data sits under data. The examples handle both shapes. There is no event deduplication on parcelLab's side.
Environment Variables
PARCELLAB_WEBHOOK_USERNAME=parcellab
PARCELLAB_WEBHOOK_PASSWORD=replace-with-a-long-random-password
Local Development
npx hookdeck-cli listen 3000 parcellab --path /webhooks/parcellab
No account required. Give the printed URL, plus your Basic credentials, to parcelLab as the webhook target.
Resources
- references/overview.md - Events, payload structure, retries, CloudEvents format
- references/setup.md - Giving parcelLab your URL and Basic credentials
- references/verification.md - Basic auth check in Node, Python and Next.js, gotchas
- examples/ - Runnable Express, Next.js and FastAPI handlers with tests