7 webhook endpoints. All inbound: these are endpoints BoostEcom exposes to receive events, not endpoints you register to receive ours.
| Endpoint | Sender | Idempotency key |
|---|---|---|
| /api/webhooks/stripe | Stripe | StripeEvent by event.id |
| /api/webhooks/shopify/events | Shopify | ShopifyWebhookEvent |
| /api/webhooks/shopify/customer-redact | Shopify (GDPR, mandatory) | ShopifyCustomerRedaction |
| /api/webhooks/shopify/redact | Shopify (GDPR, mandatory) | ShopifyComplianceRequest |
| /api/webhooks/shopify/data-request | Shopify (GDPR, mandatory) | ShopifyComplianceRequest |
| /api/webhooks/resend | Resend | EmailDeliveryEvent.providerEventId |
| /api/webhooks/[platform] | Chat SDK / WhatsApp | per platform |
Stripe
Every handler is idempotent on event.id, recorded in StripeEvent. A
redelivery is a no-op, which matters because credit grants and plan
changes run through here.
Beyond subscriptions and credits, the handler also processes the
marketplace events: account.updated, charge.refunded and
payout.failed for Stripe Connect.
Credit grants read metadata.amount — the pre-tax figure — never
amount_total. Stripe Tax is active, so those two differ.
Shopify GDPR — the three mandatory endpoints
Shopify requires three, and they behave differently on purpose:
customers/redact raises a ShopifyCustomerRedaction barrier
before answering 200. The erasure itself is drained by the
gdpr-erasure cron: vector namespaces, customer links, attribution rows,
archived audit payloads. completedAt is the proof of completion: a row
without it is an unfulfilled obligation, and it is visible as one.
shop/redact records a ShopifyComplianceRequest that the same cron
drains: credentials, vector namespaces, raw payloads archived in
AuditLog, order free-text. It stamps completedAt and names in
pendingSteps whatever still needs an operator.
customers/data_request is entirely manual. handledAt is only
ever set by a human. Past 30 days, a row without it raises an error-level
log — the system refuses to let the obligation go quiet.
Note that these three are idempotent on their own two tables, not on
ShopifyWebhookEvent.
Resend
Delivery, bounces and spam complaints. Signature verified via Svix,
idempotent on EmailDeliveryEvent.providerEventId.
Verification
Every endpoint verifies its sender before doing work: Stripe signature, Shopify HMAC, Svix for Resend. An unverified payload is rejected, never processed on the assumption that it probably came from the right place.
Outbound webhooks
One outbound surface exists, and it is not in the table above because it is not an inbound endpoint: status webhooks. Incident events are signed with HMAC-SHA256 and posted to URLs configured from the admin status panel.