Agent skill

Sendcloud Webhooks Skill

Receive and verify Sendcloud shipping webhooks. Use when setting up a Sendcloud webhook endpoint, debugging Sendcloud-Signature HMAC-SHA256 verification, or handling actions like parcel_status_changed, return_created, integration_connected, integration_updated and integration_deleted.

Install this skill

npx skills add hookdeck/webhook-skills --skill sendcloud-webhooks


Sendcloud is a shipping platform. Its webhooks notify your application when a parcel changes status, when a return is created, and when an integration is connected, modified or deleted. Every webhook request is signed with an HMAC-SHA256 signature in the Sendcloud-Signature header. Webhooks are scoped to the integration they are configured on.

When to Use This Skill

  • How do I receive Sendcloud webhooks?
  • How do I verify the Sendcloud-Signature header?
  • Where do I find the Sendcloud webhook secret (Secret Key or Webhook Signature Key)?
  • How do I handle parcel_status_changed or return_created webhooks?
  • Why is my Sendcloud webhook signature verification failing?
  • How do I deal with out-of-order Sendcloud parcel updates?

Verification (core)

ItemValue
HeaderSendcloud-Signature
AlgorithmHMAC-SHA256
Signed contentThe entire raw request body, exactly as received
KeyIntegration Secret Key or Webhook Signature Key, as UTF-8
EncodingBare lowercase hex (no prefix, no timestamp)

Sendcloud has no webhook SDK, so verification is manual:

const crypto = require('crypto');

// rawBody: Buffer of the exact request body, NOT re-serialised JSON
function verifySendcloudSignature(rawBody, signature, secret) {
  if (!signature || !secret) return false;
  const expected = crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
  const a = Buffer.from(expected);
  const b = Buffer.from(signature);
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

Docs test vector: body {"key": "value"} with secret secretkey gives 1eed4b3d41f4653ac64fd56f1bf1cbfd349e4482cbc11dff7134bd93e5da4b0a.

For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.

Event Envelope

The event type is in the action field (there is no event type header). Payloads carry a timestamp and no event ID.

{ "action": "parcel_status_changed", "timestamp": 1525271885993,
  "parcel": { "id": 1, "tracking_number": "3SYZXG132912330", "status": { "id": 1, "message": "Ready to send" } } }

Common Event Types

actionFired when
parcel_status_changedA parcel of this integration shifts to a different status
return_createdA return is created via the API or Return Portal (not via the Return Form)
integration_connectedThe integration is created
integration_updatedThe integration is modified
integration_deletedThe integration is deleted

Delivery Semantics

  • Return a 2xx within 10 seconds. Sendcloud makes up to 10 attempts over about an hour and a half: the first retry is within 5 minutes and later waits grow to roughly half an hour.
  • Timeouts, an unreachable endpoint, 406, 408, 409, 429 and 5xx are retried. Any other 4xx, such as 400, 401, 404 or 422, stops delivery with no retry, so return a 5xx for temporary problems. Every failed attempt appears in the connection issue log.
  • Webhooks can arrive out of order. Use the payload timestamp to find the latest parcel update, and make handlers idempotent.
  • Read the body raw (Express: express.raw({ type: '*/*' })) so any content type verifies.

Environment Variables

SENDCLOUD_WEBHOOK_SECRET=your_secret_key_or_webhook_signature_key

Local Development

# Express / Next.js (use 8000 for FastAPI). No install or account required.
npx hookdeck-cli listen 3000 sendcloud --path /webhooks/sendcloud

Put the printed URL in the integration's Webhook url field and use Test API webhook to send a test request.

Reference Materials


Repository

hookdeck/webhook-skills

v0.1.0 · MIT · Updated Nov 5, 2026

View on GitHub →