Guide to Snipcart Webhooks: Features and Best Practices
Snipcart is a developer-first e-commerce platform that lets you add a shopping cart to any website using simple HTML attributes. It's a popular choice for JAMstack sites, static site generators, and any project where you want e-commerce without a monolithic backend. Webhooks are a core part of Snipcart's integration model, enabling you to sync orders with fulfillment systems, trigger post-purchase workflows, calculate custom shipping rates, and keep external systems in sync with your store.
This guide covers everything you need to know about Snipcart webhooks: their features, how to configure them, best practices for production deployments, and the common pain points developers face along with solutions to address them.
What are Snipcart webhooks?
Snipcart webhooks are HTTP callbacks that deliver event notifications to your application whenever specific actions occur in your store. When an order is completed, a subscription payment succeeds, or a customer requests shipping rates, Snipcart sends a POST request containing a JSON payload with event details to a URL you've configured in the dashboard.
Webhooks in Snipcart exist in two primary contexts:
- Order and subscription event webhooks — Notifications triggered by order lifecycle events (completion, status changes, refunds) and subscription billing events (payment success, failure, cancellation).
- Shipping rate webhooks — A synchronous webhook where Snipcart calls your endpoint during checkout to fetch custom shipping rates, and your response is displayed to the customer in real-time.
This guide covers both types, as they have different configuration requirements and behaviors.
Snipcart webhook features
| Feature | Details |
|---|---|
| Webhook configuration | Snipcart dashboard (Store Configurations) |
| Authentication method | Token-based validation via X-Snipcart-RequestToken header (API callback) |
| Hashing algorithm | None — no HMAC signature support |
| Timeout | Not publicly documented |
| Retry logic | No documented automatic retry mechanism |
| Manual retry | "Send this hook again" button in dashboard |
| Browsable log | Request and response details viewable per webhook URL in dashboard |
| Multiple endpoints | Supported — semicolon-separated URLs |
| Payload format | JSON (Content-Type: application/json) |
| HTTP method | POST |
Supported webhook events
Snipcart supports webhook events across three categories: order events, subscription events, and shipping events.
Order events
| Event | Description |
|---|---|
order.completed | Triggered when a new order is completed successfully. |
order.status.changed | Triggered when the status of an order changes (e.g., from "Processed" to "Shipped"). |
order.paymentStatus.changed | Triggered when the payment status of an order changes (e.g., from "Authorized" to "Paid"). |
order.trackingNumber.changed | Triggered when the tracking number of an order is updated. |
order.refund.created | Triggered when an order is wholly or partially refunded. |
order.notification.created | Triggered when a notification is added to an order (Invoice, Comment, TrackingNumber, Refund, OrderShipped, etc.). |
Subscription events
| Event | Description |
|---|---|
v3/subscription.invoice.payment.succeeded | Triggered when a recurring subscription payment succeeds. The first payment does not trigger this event. |
v3/subscription.invoice.payment.failed | Triggered when a recurring subscription payment fails. The first payment does not trigger this event. |
v3/subscription.state.cancellationRequested | Triggered when a subscription cancellation is requested. The subscription remains active until the end of the billing cycle. |
v3/subscription.state.cancelled | Triggered when a cancelled subscription's billing cycle finishes, or at the start of a billing cycle if the previous payment was declined. |
Shipping events
| Event | Description |
|---|---|
shippingrates.fetch | Triggered during checkout when Snipcart needs to calculate shipping rates. Your endpoint must return available rates synchronously. |
Webhook payload structure
When Snipcart sends a webhook notification, it delivers a JSON payload with a consistent top-level structure. Every payload includes the eventName, mode (Live or Test), createdOn timestamp, and a content object with event-specific data.
Order event payload
Here's a simplified view of the order.completed payload structure:
{
"eventName": "order.completed",
"mode": "Live",
"createdOn": "2025-01-15T14:30:00.000Z",
"content": {
"token": "1912e4c1-d008-4c15-ab12-fe21a76d30d4",
"invoiceNumber": "SNIP-1003",
"email": "customer@example.com",
"status": "Processed",
"paymentStatus": "Paid",
"currency": "usd",
"items": [
{
"name": "Product Name",
"id": "PRODUCT-1",
"price": 29.99,
"quantity": 2,
"uniqueId": "eb4c9dae-e725-4dad-b7ae-a5e48097c831",
"customFields": [],
"totalPrice": 59.98
}
],
"discounts": [],
"taxes": [],
"user": {
"email": "customer@example.com",
"billingAddress": { "..." : "..." },
"shippingAddress": { "..." : "..." }
},
"billingAddress": { "..." : "..." },
"shippingAddress": { "..." : "..." },
"shippingFees": 10.00,
"shippingMethod": "Standard Shipping",
"subtotal": 59.98,
"grandTotal": 69.98,
"paymentMethod": "CreditCard",
"cardType": "Visa",
"creditCardLast4Digits": "4242",
"metadata": {},
"customFields": []
}
}
Key payload fields
| Field | Description |
|---|---|
eventName | The webhook event type (e.g., order.completed). |
mode | Whether the event occurred in Live or Test mode. |
createdOn | ISO 8601 timestamp of when the webhook was sent. |
content.token | Unique identifier for the order. |
content.invoiceNumber | Human-readable invoice number (e.g., SNIP-1003). |
content.items | Array of line items with product details, quantities, and prices. |
content.user | Customer details including email and addresses. |
content.customFields | Custom checkout fields defined in your cart configuration. |
content.metadata | Arbitrary key-value metadata attached to the order. |
Security with token validation
Unlike most webhook providers that use HMAC-SHA256 signatures, Snipcart uses a token-based callback mechanism to verify webhook authenticity. Each webhook request includes an X-Snipcart-RequestToken header containing a token that's valid for one hour. To verify the request genuinely came from Snipcart, make a GET request to Snipcart's validation endpoint:
GET https://app.snipcart.com/api/requestvalidation/{token}
A successful response confirms the request is authentic. This approach functions as a form of digital handshake, but it means your server must make a network call back to Snipcart's API for every webhook it receives — you cannot verify authenticity offline.
Setting up Snipcart webhooks
Configuring order and event webhooks
- Log into the Snipcart dashboard.
- Navigate to Store Configurations — Webhooks.
- Enter your webhook endpoint URL. The URL must be an absolute URL.
- To send events to multiple endpoints, separate URLs with semicolons (e.g.,
https://example.com/webhooks;https://backup.example.com/webhooks). - Save your configuration.
Configuring shipping webhooks
Shipping webhooks are configured separately from event webhooks:
- In the Snipcart dashboard, navigate to Store Configurations — Shipping — Webhooks.
- Enter your shipping rate endpoint URL.
- Save your configuration.
Inspecting webhook deliveries
After configuring a webhook URL, click on the entry in the dashboard to view its detail page. This page displays the full HTTP request sent to your application and the response received back, making it useful during development. The "Send this hook again" button lets you replay a webhook delivery for debugging.
Best practices when working with Snipcart webhooks
Validating the request token
Always validate the X-Snipcart-RequestToken header to ensure requests genuinely originate from Snipcart.
Node.js
const express = require('express');
const app = express();
app.use(express.json());
async function validateSnipcartRequest(token) {
const response = await fetch(
`https://app.snipcart.com/api/requestvalidation/${token}`
);
return response.ok;
}
app.post('/webhooks/snipcart', async (req, res) => {
const token = req.headers['x-snipcart-requesttoken'];
if (!token || !(await validateSnipcartRequest(token))) {
return res.status(401).json({ error: 'Invalid request token' });
}
const { eventName, content } = req.body;
// Route to appropriate handler based on event type
switch (eventName) {
case 'order.completed':
await handleOrderCompleted(content);
break;
case 'order.status.changed':
await handleStatusChanged(req.body);
break;
case 'order.refund.created':
await handleRefund(req.body);
break;
default:
console.log(`Unhandled event: ${eventName}`);
}
res.status(200).json({ success: true });
});
Python
import requests
from flask import Flask, request, abort, jsonify
app = Flask(__name__)
SNIPCART_VALIDATION_URL = "https://app.snipcart.com/api/requestvalidation/{}"
def validate_snipcart_token(token):
response = requests.get(SNIPCART_VALIDATION_URL.format(token))
return response.ok
@app.route('/webhooks/snipcart', methods=['POST'])
def handle_snipcart_webhook():
token = request.headers.get('X-Snipcart-RequestToken')
if not token or not validate_snipcart_token(token):
abort(401)
data = request.get_json()
event_name = data.get('eventName')
if event_name == 'order.completed':
handle_order_completed(data['content'])
elif event_name == 'order.status.changed':
handle_status_changed(data)
elif event_name == 'order.refund.created':
handle_refund(data)
return jsonify(success=True), 200
Differentiate between Live and Test mode
Every Snipcart webhook payload includes a mode field set to either "Live" or "Test". Always check this field to avoid processing test transactions in production workflows.
Use the order token for idempotency
Each order includes a token field — a unique GUID that identifies the order. Use this to implement idempotent processing and prevent duplicate operations if a webhook is replayed:
async function handleOrderCompleted(order) {
const idempotencyKey = `order-completed-${order.token}`;
const exists = await redis.get(`processed:${idempotencyKey}`);
if (exists) {
console.log(`Order ${order.token} already processed, skipping`);
return;
}
// Process the order
await fulfillOrder(order);
// Mark as processed with a 24-hour TTL
await redis.setex(`processed:${idempotencyKey}`, 86400, '1');
}
Respond quickly to shipping webhooks
The shippingrates.fetch webhook is synchronous — Snipcart waits for your response before showing shipping options to the customer during checkout. Slow responses directly impact the checkout experience. Pre-calculate rates where possible, cache carrier API responses, and keep your endpoint's response time under a few seconds.
Handle errors gracefully in shipping webhooks
For shipping webhooks specifically, you can return user-facing error messages by sending a 2XX response with an errors array. Use this to inform customers about delivery restrictions rather than letting the checkout fail silently.
Snipcart webhook limitations and pain points
No HMAC signature verification
The Problem: Snipcart does not support HMAC-SHA256 signatures for webhook authentication. Instead, it uses a token-based callback where your server must make a GET request to Snipcart's API to validate each webhook.
Why It Happens: Snipcart opted for a token validation callback approach (X-Snipcart-RequestToken) where your server verifies the token by calling https://app.snipcart.com/api/requestvalidation/{token}. The token is valid for one hour.
Workarounds:
- Implement the token validation callback on every request, accepting the additional network latency.
- Restrict your webhook endpoint to Snipcart's known IP ranges if they publish them (not currently documented).
- Use HTTPS and additional application-level checks (e.g., validating payload structure) as defense-in-depth.
How Hookdeck Can Help: Hookdeck can sit between Snipcart and your endpoint, handling token validation and providing a consistent authentication layer. This moves the validation overhead out of your application and into managed infrastructure. You can also use Hookdeck's source verification features to add an additional layer of security.
No documented automatic retry mechanism
The Problem: Snipcart does not describe any automatic retry behavior for failed webhook deliveries. If your endpoint is temporarily unavailable or returns an error, the webhook event may be lost with no automatic attempt to redeliver it. This is a critical gap for any e-commerce integration where missed order notifications can lead to unfulfilled orders and lost revenue.
Why It Happens: Snipcart's webhook system uses a fire-and-forget delivery model. The only retry capability is the manual "Send this hook again" button in the dashboard, which requires a human to notice the failure and manually trigger redelivery.
Workarounds:
- Implement a polling mechanism using the Snipcart REST API to periodically check for new orders as a backup to webhooks.
- Build your own reconciliation process that compares orders received via webhooks with orders listed via the API.
- Log all received webhooks and run periodic gap analysis.
How Hookdeck Can Help: Hookdeck provides configurable automatic retry policies with exponential backoff, ensuring failed deliveries are retried automatically. Failed webhooks are preserved and can be manually replayed from the dashboard, effectively acting as a dead letter queue.
Request token expires after one hour
The Problem: The X-Snipcart-RequestToken included with each webhook is only valid for one hour. If your webhook processing pipeline involves a queue where messages may sit for longer than an hour before being processed, the token will be expired by the time you attempt validation, making it impossible to confirm the webhook's authenticity.
Why It Happens: The one-hour expiry is a security measure on Snipcart's side to limit the window for token reuse. However, it creates a tight coupling between when the webhook is received and when it's validated.
Workarounds:
- Validate the token immediately upon receipt, before queuing the webhook for processing.
- Store the validation result alongside the payload in your queue.
- Accept the risk of processing unvalidated webhooks if your queue processing exceeds one hour.
How Hookdeck Can Help: Hookdeck validates incoming webhooks upon receipt and forwards them to your endpoint as authenticated requests, decoupling the authentication step from your processing pipeline. Even if your endpoint processes webhooks later, the validation has already occurred at ingestion time.
No webhook event filtering
The Problem: Snipcart doesn't allow you to subscribe to specific webhook events. When you configure a webhook URL, it receives all events. If you only care about order.completed, you'll still receive order.status.changed, order.notification.created, and every other event type, adding unnecessary load to your endpoint.
Why It Happens: Snipcart's webhook configuration is URL-based rather than event-based. There's no mechanism in the dashboard or API to filter which events are sent to which endpoints.
Workarounds:
- Filter events in your handler by checking the
eventNamefield and returning200immediately for events you don't care about. - If you need different endpoints for different events, use a routing layer that inspects the
eventNameand forwards accordingly.
How Hookdeck Can Help: Hookdeck's filtering and routing rules let you direct specific Snipcart events to specific destinations based on the eventName field (or any other payload attribute), so each endpoint only receives the events it needs to process.
Shipping webhook errors require specific formatting
The Problem: When returning errors from the shipping webhook, you must return a 2XX status code with a specific JSON error format. Returning a non-2XX status code doesn't show a user-friendly error — it causes Snipcart to display a generic "No shipping method available" message. Developers migrating between Snipcart versions have reported breaking changes in how error responses are handled, with previously working patterns suddenly causing the Snipcart JavaScript to throw errors.
Why It Happens: The shipping webhook is a synchronous call during checkout, and Snipcart interprets non-2XX responses as endpoint failures rather than intentional error messages. The 2XX-with-error-body pattern is unconventional and easy to get wrong.
Workarounds:
- Always return a
2XXstatus code from your shipping endpoint, even for error conditions. - Use the documented error format with
keyandmessagefields inside anerrorsarray. - Test shipping webhook error responses thoroughly with the Snipcart checkout flow, not just with HTTP tools.
How Hookdeck Can Help: Hookdeck's transformation capabilities can normalize error responses from your endpoint, ensuring Snipcart always receives the expected format, even if your backend returns errors in a different structure.
No built-in dead letter queue
The Problem: Webhooks that fail delivery are not stored anywhere for later inspection or replay. If your endpoint is down during a critical period (e.g., a flash sale), order notifications may be permanently lost with no way to recover them from Snipcart's side.
Why It Happens: Snipcart's webhook system doesn't persist failed deliveries beyond what's visible in the dashboard's webhook detail page, and there's no documented mechanism for retrieving a history of failed webhook attempts.
Workarounds:
- Implement a reconciliation job that periodically polls the Snipcart API for recent orders and compares them against your records.
- Use a queuing service (e.g., Hookdeck, AWS SQS, RabbitMQ) between Snipcart and your final processing endpoint.
- Set up monitoring and alerts on your webhook endpoint to catch downtime quickly.
How Hookdeck Can Help: Hookdeck automatically stores all webhook deliveries (successful and failed) providing a complete history you can search, filter, and replay. This functions as a managed dead letter queue without any additional infrastructure.
Token validation adds latency
The Problem: Because Snipcart uses a token callback for authentication instead of HMAC signatures, every webhook your endpoint receives requires an additional HTTP request to Snipcart's API for validation. This adds latency to every webhook processing cycle and introduces a dependency on Snipcart's API availability during validation.
Why It Happens: HMAC signature verification is a local cryptographic operation that takes microseconds. Snipcart's token validation requires a network round-trip to their API, which typically takes tens or hundreds of milliseconds and can fail if Snipcart's API is experiencing issues.
Workarounds:
- Cache validation results for tokens you've already verified (within the one-hour validity window).
- Validate asynchronously — accept the webhook immediately and validate the token in a background process before final processing.
- Accept the latency as a trade-off and ensure your endpoint still responds within Snipcart's expected timeframe.
How Hookdeck Can Help: Hookdeck handles token validation at the gateway level before forwarding requests to your endpoint. This removes the validation latency from your application's critical path and eliminates the dependency on Snipcart's API being available at processing time.
Testing Snipcart webhooks
Use the dashboard's webhook detail page
After setting up a webhook URL, the Snipcart dashboard provides a detail page for each URL that displays the full request and response for recent deliveries. Use this to inspect actual payloads and verify your endpoint is responding correctly.
Use the "Send this hook again" button
The dashboard includes a replay button for re-sending a previous webhook delivery. This is useful for debugging, but be aware that:
- The replayed request will have a fresh
X-Snipcart-RequestToken. - Replayed test payloads may differ slightly from live payloads.
- There's no way to replay webhooks that were never successfully delivered.
Use a request inspector
Before building your handler, use a service like Hookdeck Console to inspect real Snipcart payloads:
- Create a temporary Hookdeck URL.
- Configure it as your webhook endpoint in Snipcart.
- Trigger a real event by completing a test order.
- Inspect the full payload, headers, and metadata.
Test with both Live and Test modes
Snipcart includes a mode field in every webhook payload. Make sure your handler correctly differentiates between Live and Test mode events, and test both paths to avoid accidentally fulfilling test orders.
Conclusion
Snipcart webhooks provide a straightforward mechanism for integrating your e-commerce store with external systems. The event model covers the key order lifecycle stages, subscription billing, and custom shipping rate calculation, and the JSON payloads include comprehensive order and customer data.
However, the lack of HMAC signature verification, automatic retries, event filtering, and dead letter queues means production deployments require additional infrastructure to achieve the reliability that mission-critical e-commerce workflows demand. The token-based authentication model adds latency and a network dependency that other platforms avoid with local HMAC verification.
For small stores with moderate order volumes, Snipcart's built-in webhook capabilities combined with API polling as a safety net will handle most scenarios. For stores where every order notification matters (particularly those with custom fulfillment pipelines, multi-system integrations, or high-volume sales events) webhook infrastructure like Hookdeck can address Snipcart's limitations, providing automatic retries, payload transformation, event routing, and comprehensive delivery monitoring without modifying your Snipcart configuration.