Set Up E-Commerce Webhooks for Price Drop Alerts
March 6, 2026 · 6 min read
Polling APIs every few minutes to check for price changes is wasteful and slow. Webhooks flip the model: instead of you checking for changes, ShelfRun notifies you the moment something changes. Here's how to set up real-time price drop alerts.
How ShelfRun Webhooks Work
When you add a store to ShelfRun, you provide a webhook URL. After each sync, ShelfRun compares the new data to the previous snapshot. If anything changed, it fires a POST request to your webhook URL with the diff.
You get webhooks for:
- Price drops — any product price decreases
- Price increases — products become more expensive
- Stock changes — in stock ↔ out of stock transitions
- New products — competitor launches something new
- Removed products — competitor discontinues a product
Step 1: Set Up Your Webhook Endpoint
Create a simple endpoint to receive ShelfRun webhooks. Here's a Flask example:
from flask import Flask, request, jsonify
import hmac, hashlib, os
app = Flask(__name__)
WEBHOOK_SECRET = os.environ["SHELFRUN_WEBHOOK_SECRET"]
def verify_signature(payload, signature):
"""Verify the webhook came from ShelfRun."""
expected = hmac.new(
WEBHOOK_SECRET.encode(),
payload,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature)
@app.route("/shelfrun-webhook", methods=["POST"])
def handle_webhook():
# Verify signature
sig = request.headers.get("X-ShelfRun-Signature", "")
if not verify_signature(request.get_data(), sig):
return jsonify({"error": "Invalid signature"}), 401
data = request.json
for change in data.get("changes", []):
if change["type"] == "price_drop":
handle_price_drop(change)
elif change["type"] == "out_of_stock":
handle_stockout(change)
elif change["type"] == "new_product":
handle_new_product(change)
return jsonify({"ok": True})
def handle_price_drop(change):
pct = change["change_pct"]
product = change["product"]
print(f"Price drop: {product} dropped {pct}%")
# Add your logic: email, Slack, update your own pricing, etc.Step 2: Register the Webhook with ShelfRun
import requests
response = requests.post(
"https://api.shelfrun.com/v1/stores",
headers={"X-API-Key": "sr_live_your_key"},
json={
"url": "competitor-store.com",
"sync_frequency": "hourly",
"webhook_url": "https://yourapp.com/shelfrun-webhook",
"webhook_events": [
"price_drop",
"price_increase",
"out_of_stock",
"back_in_stock",
"new_product"
]
}
)
print(response.json())The Webhook Payload
Every webhook POST contains a changes array with structured diffs:
{
"store": "competitor-store.com",
"store_id": "str_abc123",
"sync_at": "2026-03-06T15:00:00Z",
"changes": [
{
"type": "price_drop",
"product": "Premium Widget",
"sku": "WGT-001",
"old_price": 89.99,
"new_price": 69.99,
"change_pct": -22.2,
"currency": "USD",
"product_url": "https://competitor-store.com/products/widget",
"in_stock": true
},
{
"type": "out_of_stock",
"product": "Basic Widget",
"sku": "WGT-002",
"old_stock": "in_stock",
"new_stock": "out_of_stock"
}
]
}Forward Alerts to Slack
The most common use case is forwarding price alerts to Slack:
import requests
SLACK_WEBHOOK = "https://hooks.slack.com/services/..."
def handle_price_drop(change):
emoji = "🔻" if change["change_pct"] < -15 else "📉"
old_p = str(change['old_price'])
new_p = str(change['new_price'])
pct = str(round(change['change_pct'], 1))
message = (
emoji + " *Price Drop Alert*\n"
"*Product:* " + change['product'] + "\n"
"*Old price:* $" + old_p + "\n"
"*New price:* $" + new_p + " (" + pct + "%)\n"
"<" + change['product_url'] + "|View product>"
)
requests.post(SLACK_WEBHOOK, json={"text": message})Set Thresholds to Reduce Noise
Not every price change matters. Filter webhooks to only act on significant drops:
SIGNIFICANT_DROP_PCT = -10 # Only alert on 10%+ drops
SIGNIFICANT_DROP_ABS = 5.00 # Or $5+ absolute drops
def is_significant(change):
pct_significant = change["change_pct"] <= SIGNIFICANT_DROP_PCT
abs_drop = change["old_price"] - change["new_price"]
abs_significant = abs_drop >= SIGNIFICANT_DROP_ABS
return pct_significant or abs_significant
@app.route("/shelfrun-webhook", methods=["POST"])
def handle_webhook():
data = request.json
for change in data.get("changes", []):
if change["type"] == "price_drop" and is_significant(change):
handle_significant_price_drop(change)Test Your Webhook
ShelfRun lets you send a test webhook to verify your endpoint is working before relying on it in production. Use the API docs for the test endpoint details.