Back to Documentation

Webhooks

Get real-time notifications when competitor prices change

Quick Summary

Webhooks allow you to receive instant HTTP callbacks when price changes occur. Instead of polling the API repeatedly, RivalPrice will push notifications to your server when events happen.

How Webhooks Work

1. Event Occurs
A competitor's price changes and triggers one of your webhook rules
2. We Send Request
RivalPrice sends an HTTP POST request to your webhook URL with event data
3. You Process
Your server receives and processes the webhook, updating prices or sending alerts

Available Events

price.changed
Triggered whenever a price changes (up or down)
price.dropped
Triggered only when a price decreases
price.increased
Triggered only when a price increases
price.below_your_price
Triggered when a competitor's price drops below your price
price.above_your_price
Triggered when a competitor's price rises above your price
price.below_threshold
Triggered when price drops below a custom threshold you set
price.above_threshold
Triggered when price rises above a custom threshold you set
scrape.failed
Triggered when we can't scrape a competitor URL (broken link, etc.)
scrape.successful
Triggered when a scrape completes successfully

Creating a Webhook

POSTCreate Webhook
Create a new webhook endpoint

Your API key is only used in your browser and never stored

Request URL
https://api.rivalprice.app/webhooks
Webhook Fields Explained
url - Your HTTPS endpoint that will receive webhook events
events - Array with exactly one event type to monitor
rules (optional) - Filters to narrow down when the webhook fires:
  • product_ids - Only fire for specific products
  • competitor_url_ids - Only fire for specific competitor URLs
  • price_change_threshold - Only fire if price changes by this percentage
  • min_price / max_price - Only fire within this price range

Webhook Payload

When an event occurs, we'll send a POST request to your URL with this payload structure:

{
  "event": "price.changed",
  "timestamp": "2024-01-15T10:30:00Z",
  "data": {
    "product_id": "uuid-here",
    "product_name": "iPhone 15 Pro",
    "product_sku": "IPHONE-15-PRO-256GB",
    "customer_price": 999.99,
    "competitor_url_id": "uuid-here",
    "competitor_name": "Amazon",
    "competitor_url": "https://amazon.com/...",
    "old_price": 999.00,
    "new_price": 949.00,
    "price_change": -50.00,
    "price_change_percent": -5.01,
    "currency": "USD"
  },
  "webhook_id": "webhook-uuid"
}

Webhook Security

Signature Verification

Each webhook includes an X-Webhook-Signature header containing an HMAC-SHA256 signature. Verify this to ensure the request came from RivalPrice.

Python Example:
import hmac
import hashlib

def verify_webhook(payload, signature, secret):
    expected = hmac.new(
        secret.encode('utf-8'),
        payload.encode('utf-8'),
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature)

Your webhook secret is shown once when you create the webhook. Store it securely!

Best Practices
  • Always use HTTPS for webhook URLs
  • Verify the signature on every webhook
  • Return a 2xx status code quickly (process async if needed)
  • Implement idempotency - handle duplicate webhooks gracefully
  • Set up retry logic on your end if webhook processing fails

Managing Webhooks

List All Webhooks

GETList Webhooks
Get all your configured webhooks

Your API key is only used in your browser and never stored

Request URL
https://api.rivalprice.app/webhooks

Test a Webhook

POSTTest Webhook
Send a test event to verify your webhook endpoint

Your API key is only used in your browser and never stored

Request URL
https://api.rivalprice.app/webhooks/:webhook_id/test

Delete a Webhook

DELETEDelete Webhook
Remove a webhook

Your API key is only used in your browser and never stored

Request URL
https://api.rivalprice.app/webhooks/:webhook_id

Retries & Failures

Webhook Delivery: If your endpoint doesn't respond with a 2xx status code, we'll retry the webhook up to 3 times with exponential backoff.

Automatic Disabling: If a webhook fails 10 times in a row, it will be automatically disabled. You'll need to fix the issue and re-enable it manually.

Timeout: Webhook requests timeout after 10 seconds. Make sure your endpoint responds quickly (process data asynchronously if needed).

Example Implementation

Node.js / Express

const express = require('express');
const crypto = require('crypto');

app.post('/webhooks/rivalprice', express.json(), (req, res) => {
  const signature = req.headers['x-webhook-signature'];
  const payload = JSON.stringify(req.body);
  const secret = process.env.WEBHOOK_SECRET;
  
  // Verify signature
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  
  if (signature !== expectedSignature) {
    return res.status(401).send('Invalid signature');
  }
  
  // Process webhook
  const { event, data } = req.body;
  console.log(`Price changed: ${data.product_name} from $${data.old_price} to $${data.new_price}`);
  
  // Send quick response
  res.status(200).send('OK');
  
  // Process async if needed
  processWebhookAsync(event, data);
});

Python / Flask

from flask import Flask, request
import hmac
import hashlib
import os

app = Flask(__name__)

@app.route('/webhooks/rivalprice', methods=['POST'])
def rivalprice_webhook():
    signature = request.headers.get('X-Webhook-Signature')
    payload = request.get_data(as_text=True)
    secret = os.getenv('WEBHOOK_SECRET')
    
    # Verify signature
    expected_signature = hmac.new(
        secret.encode('utf-8'),
        payload.encode('utf-8'),
        hashlib.sha256
    ).hexdigest()
    
    if not hmac.compare_digest(expected_signature, signature):
        return 'Invalid signature', 401
    
    # Process webhook
    data = request.json
    print(f"Price changed: {data['data']['product_name']}")
    
    return 'OK', 200

Next Steps