# Printify Webhooks

## When to Use This Skill

* How do I receive Printify webhooks (orders, shipments, product publishing)?
* How do I verify the Printify `X-Pfy-Signature` header?
* How do I create a Printify webhook and set a secret through the API?
* How do I handle `order:shipment:created` or `product:publish:started` events?
* Why is my Printify webhook signature verification failing?

## How Printify Secures Webhooks

Printify webhooks are created **through the API** (`POST /v1/shops/{shop_id}/webhooks.json`), one per topic. The `secret` field is optional, but **always set one**: without it Printify sends no signature and anyone who finds your URL can post to it. Generate one with `openssl rand -hex 20`.

## Verification (core)

Every request carries `X-Pfy-Signature: sha256=<hex>`. The value is the **hex** HMAC-SHA256 of the **raw request body**, keyed with your secret as a UTF-8 string (not base64-decoded). Strip the `sha256=` prefix before comparing. Printify has no webhook SDK, so verify manually against the raw body (don't `JSON.parse` first).

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

function verifyPrintifySignature(rawBody, header, secret) {
  if (typeof header !== 'string' || !header.startsWith('sha256=')) return false;
  const received = header.slice('sha256='.length).trim();
  const expected = crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
  try {
    return crypto.timingSafeEqual(Buffer.from(received), Buffer.from(expected));
  } catch {
    return false; // different lengths
  }
}

```

In Express, read the body with `express.raw({ type: '*/*' })` so any content type verifies. There is no timestamp in the signature, so there is no replay window; dedupe on the event `id`.

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

## Common Event Types

The payload is `{ id, type, created_at, resource: { id, type, data } }`. The event name is in `type`.

| Event | Triggered When | `resource.data` contains |
| --- | --- | --- |
| `order:created` | An order was created | Nothing |
| `order:updated` | An order's status changed | `shop_id`, `status` |
| `order:line-item:canceled` | A single line item was canceled | `line_item_id`, `status`, `status_details` |
| `order:sent-to-production` | An order was sent to production | Nothing |
| `order:shipment:created` | Some or all items were fulfilled | `shipped_at`, `carrier`, `skus` |
| `order:shipment:delivered` | Some or all items were delivered | `delivered_at`, `carrier`, `skus` |
| `product:created` | A product was created | `shop_id` |
| `product:updated` | A product was updated | `shop_id` |
| `product:publish:started` | Publishing to the storefront began | `action`, `publish_details` |
| `product:deleted` | A product was deleted | `shop_id` |
| `shop:disconnected` | A shop was disconnected | Nothing |
| `personalization-preview-task:processed` | A preview task reached a terminal state | `task_id`, `status`, `mockups` |

> **For the full event reference**, see [Printify's webhook documentation](https://developers.printify.com/#webhooks).

## Delivery Behavior

* Respond `200 OK`. On a `4xx` or `5xx`, Printify retries up to **3 times**, then **blocks the webhook for 1 hour**; no deliveries are sent during the block.
* That makes returning `400` for a bad signature costly if your secret is misconfigured. Test with the simulate endpoint first.

## Environment Variables

```bash
PRINTIFY_WEBHOOK_SECRET=your_printify_webhook_secret   # the "secret" passed when creating the webhook

```

## Local Development

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

```

## Reference Materials

* [references/overview.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/printify-webhooks/references/overview.md) - Printify webhook concepts, events, and payloads
* [references/setup.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/printify-webhooks/references/setup.md) - Creating webhooks and secrets through the API
* [references/verification.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/printify-webhooks/references/verification.md) - Signature verification details and gotchas