# Loop Returns Webhooks

Loop Returns is a returns and exchanges platform for Shopify merchants. It sends a webhook for each **topic** (return, label, restock, ...) and **trigger** you subscribe to, signed with an `X-Loop-Signature` header. This skill is for Loop Returns (`docs.loopreturns.com`), not [loop-webhooks](/webhooks/skills/loop-webhooks), which is loop.com freight audit and uses Svix headers.

## When to Use This Skill

* How do I receive Loop Returns webhooks?
* How do I verify the Loop Returns `X-Loop-Signature` header?
* How do I handle `return.created`, `return.updated`, `return.closed` or `label.created` events?
* Why is my Loop Returns webhook signature verification failing?
* How do I get the Loop webhook secret from Developer Tools?

## Verification (core)

`X-Loop-Signature` is the **standard base64** HMAC-SHA256 of the **raw request body**, keyed with the webhook secret from the Loop Admin. There is no timestamp and no signature prefix. Verify the raw bytes before parsing JSON.

```javascript
const crypto = require('crypto');

function verifyLoopSignature(rawBody, signature, secret) {
  const expected = crypto.createHmac('sha256', secret).update(rawBody).digest('base64');
  try {
    return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
  } catch {
    return false; // Different lengths = invalid
  }
}

// Express: mount the route with express.raw({ type: '*/*' }) so every content type reaches
// the verifier as a Buffer, and read the header with req.get('x-loop-signature').

```

Loop publishes no verification SDK, so verification is manual in every language. See the examples for Next.js (`request.text()`) and FastAPI (`await request.body()`).

> **For complete handlers with tests**, see [examples/express/](https://github.com/hookdeck/webhook-skills/tree/main/skills/loop-returns-webhooks/examples/express/), [examples/nextjs/](https://github.com/hookdeck/webhook-skills/tree/main/skills/loop-returns-webhooks/examples/nextjs/), [examples/fastapi/](https://github.com/hookdeck/webhook-skills/tree/main/skills/loop-returns-webhooks/examples/fastapi/).

## Common Event Types

The event name is the `trigger` field in the JSON body (there is no event header). `topic` says which payload shape you get.

| Trigger | Topic | Triggered When |
| --- | --- | --- |
| `return.created` | `return` | A return is submitted in the customer returns portal |
| `return.updated` | `return` | A return changes, including state changes (open, closed, cancelled, review, expired) |
| `return.closed` | `return` | A return's state becomes closed |
| `return.processing.failed` | `return processing` | Queued return processing failed to complete |
| `label.created` | `label` | A shipping label is created |
| `label.updated` | `label` | A label's shipment status changes (for example to in transit) |
| `restock.requested` | `restock` | An item in a return is restocked in Shopify |
| `giftcard.requested` | `gift card` | A gift card is requested as part of an exchange |
| `shipment.processed` | `happy returns shipment` | Loop processed a Happy Returns shipment |

> **For the full event reference**, see [Loop's webhook documentation](https://docs.loopreturns.com/webhook-reference/getting-started).

## Delivery Behavior

* Respond with a `2xx` within **10 seconds**. Do slow work after responding.
* Failed deliveries are retried **five times** (six attempts) with exponential backoff and jitter. `429`, `500`, `502`, `503`, `504` and network errors retry. `400`, `401`, `403`, `404`, `405`, `410` and `422` do **not** retry, so return `400` for a bad signature only when you mean it.
* Delivery is **at least once**: dedupe, for example on `id` + `trigger` + `edited_at` / `label_updated_at`.
* Loop may add payload fields at any time, so don't reject unknown fields.

## Environment Variables

```bash
LOOP_WEBHOOK_SECRET=your_loop_webhook_secret   # Loop Admin > Settings > Developer Tools

```

## Local Development

```bash
# Start tunnel (no account needed)
npx hookdeck-cli listen 3000 loop-returns --path /webhooks/loop-returns

```

## Reference Materials

* [references/overview.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/loop-returns-webhooks/references/overview.md) - Loop webhook concepts, topics, triggers, and payloads
* [references/setup.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/loop-returns-webhooks/references/setup.md) - Creating subscriptions, finding the secret
* [references/verification.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/loop-returns-webhooks/references/verification.md) - Signature verification details and gotchas