> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pcnaid.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks

> The six Shopify webhook subscriptions, HMAC verification, delivery-ID replay protection, and GDPR compliance topics.

# Webhooks

The app receives six Shopify webhook topics, all mounted at `/webhooks/*` and verified with HMAC-SHA256 before processing.

## Registered topics

| Topic | Endpoint | Purpose |
| - | - | - |
| `app/uninstalled` | `/webhooks/app-uninstalled` | App uninstall cleanup |
| `app_subscriptions/update` | `/webhooks/app-subscriptions-update` | App-managed subscription and entitlement sync |
| `shop/update` | `/webhooks/shop-update` | Refresh the persisted primary domain |
| `customers/data_request` | `/webhooks/customers-data-request` | GDPR data request |
| `customers/redact` | `/webhooks/customers-redact` | GDPR customer redaction |
| `shop/redact` | `/webhooks/shop-redact` | GDPR shop redaction |

The three GDPR topics are declared as compliance-topic subscriptions in `shopify.app.toml`; the legacy privacy-compliance table is not used.

## Processing pipeline

```text theme={null}
Ingest → Verify raw-body signature → Validate ID/topic/shop → Claim delivery ID → Bind app identity → Handle → Complete
```

* Every route verifies the HMAC signature over the unparsed body before JSON parsing. The signature header must be the canonical base64 form of the SHA-256 digest, and the JSON root must be an object.
* Each delivery requires `X-Shopify-Webhook-Id` and a route-matching `X-Shopify-Topic`. The delivery ID is claimed atomically in D1; completed duplicates return `200` with `duplicate: true`, a concurrent live delivery returns retryable `503`, and an ID reused for a different topic or payload returns `409`.
* Customer compliance deliveries require a valid positive customer ID before their receipt is claimed; subscription updates require an object envelope with a recognized status before the claim.
* Handlers return `200` only after required verification and D1/KV work completes. A verified `shop/redact` whose work is queued may return `202`. Handler failures mark the claim failed and return `500` so Shopify can retry.

## Signature verification

Shopify sends `X-Shopify-Hmac-Sha256` (a base64 HMAC-SHA256 digest), `X-Shopify-Topic`, `X-Shopify-Shop-Domain`, `X-Shopify-Api-Version`, and `X-Shopify-Webhook-Id`. The Worker computes HMAC-SHA256 of the raw body with the app secret and compares it in constant time; a mismatch returns `401` before any receipt is claimed.

## Handling summary

* `app/uninstalled` verifies the signed domain and/or stored Shop GID, then probes `currentAppInstallation` with any current session. A still-installed result preserves all data; a revoked offline session triggers cleanup, while a revoked online (staff) session deletes only that session row.
* `shop/update` normalizes the payload domain and updates `sessions.primary_domain` monotonically for the matching offline session.
* `customers/data_request` returns matching audit events, customer-linked retail workflow records with internal fields removed, and an ID-only customer object.
* `customers/redact` deletes audit rows matching the validated customer ID.
* `shop/redact` persists durable signed redaction work, guards against a live reinstall, and purges shop-scoped D1 and KV data.

Shopify retries failed deliveries up to eight times over a four-hour window. The receipt lease is five minutes so a terminated Worker does not suppress later retries.

[Pcnaid Documentation](https://docs.pcnaid.com/namespace/index.md) › [Shopify Ecosystem](https://docs.pcnaid.com/hubs/shopify-ecosystem/index.md) › [POS True Retail Operations Suite](https://docs.pcnaid.com/nodes/shopify/pos-true-retail-operations/index.md) › [Developer](https://docs.pcnaid.com/nodes/shopify/pos-true-retail-operations/developer/index)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.