# Sendcloud Webhooks

[Sendcloud](https://www.sendcloud.com) 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)

| Item | Value |
| --- | --- |
| Header | `Sendcloud-Signature` |
| Algorithm | HMAC-SHA256 |
| Signed content | The entire raw request body, exactly as received |
| Key | Integration **Secret Key** or **Webhook Signature Key**, as UTF-8 |
| Encoding | Bare lowercase hex (no prefix, no timestamp) |

Sendcloud has no webhook SDK, so verification is manual:

```javascript
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/](https://github.com/hookdeck/webhook-skills/tree/main/skills/sendcloud-webhooks/examples/express/), [examples/nextjs/](https://github.com/hookdeck/webhook-skills/tree/main/skills/sendcloud-webhooks/examples/nextjs/), [examples/fastapi/](https://github.com/hookdeck/webhook-skills/tree/main/skills/sendcloud-webhooks/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.

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

```

## Common Event Types

| `action` | Fired when |
| --- | --- |
| `parcel_status_changed` | A parcel of this integration shifts to a different status |
| `return_created` | A return is created via the API or Return Portal (not via the Return Form) |
| `integration_connected` | The integration is created |
| `integration_updated` | The integration is modified |
| `integration_deleted` | The 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

```bash
SENDCLOUD_WEBHOOK_SECRET=your_secret_key_or_webhook_signature_key

```

## Local Development

```bash
# 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

* [references/overview.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/sendcloud-webhooks/references/overview.md) - Events and payload fields
* [references/setup.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/sendcloud-webhooks/references/setup.md) - Integration configuration and secrets
* [references/verification.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/sendcloud-webhooks/references/verification.md) - Signature details, gotchas, debugging