DEV Community

XSron Hou
XSron Hou

Posted on Originally published at scrapio.dev

Build a Hotel Price Drop Alert in n8n (No Polling Code Required)

Originally posted on the Scrapio blog — sharing here too.

Rate-intelligence and rate-parity teams already know how to watch a hotel's price by hand: open Booking.com, check the same dates every morning, note what changed. Scrapio's hotel monitors automate the checking and the diffing — this guide connects that directly to n8n, so a price move lands in Slack, a spreadsheet, or wherever your workflow needs it, with zero polling code.

Unlike a typical n8n scraping workflow — where n8n's HTTP Request node polls Scrapio on a schedule — a monitor already owns the schedule and the diffing. n8n's job here is simpler: sit and wait for a webhook, then act on it.

What you'll need

  • n8n (cloud or self-hosted)
  • A Scrapio API key on a Starter plan or higher
  • A Booking.com property you want to track, plus fixed check-in/check-out dates and occupancy

Step 1 — Add a Webhook trigger in n8n

  1. Create a new workflow, add a Webhook node as the trigger
  2. Set HTTP Method to POST
  3. Copy the Production URL n8n generates (something like https://your-instance.app.n8n.cloud/webhook/abc123)

This URL is where Scrapio will deliver monitor.change_detected events.

Step 2 — Register that URL as a Scrapio webhook endpoint

Webhook endpoints are managed from the dashboard, not a public API call: go to Dashboard → Webhooks, click Add Endpoint, paste the n8n URL from Step 1, and subscribe to the monitor.change_detected event. Scrapio hands back the endpoint's id (whe_...) and a signing secret — save the secret now, it's shown only once.

Step 3 — Create the hotel monitor, pointed at that endpoint

curl -X POST https://api.scrapio.dev/v1/booking/monitors \
  -H "Authorization: Bearer $SCRAPIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Hotel Mansion — Amsterdam, Sep 10-12",
    "property_id": "nl/hotel-mansion",
    "check_in": "2026-09-10",
    "check_out": "2026-09-12",
    "adults": 2,
    "currency": "EUR",
    "cron": "0 * * * *",
    "watch": { "thresholds": { "abs": 5, "pct": 2 } },
    "webhook_endpoint_id": "whe_..."
  }'
Enter fullscreen mode Exit fullscreen mode

Scrapio now checks this exact stay hourly. Nothing fires until the price actually moves past $5 or 2%, whichever comes first — see the Hotel Price Drop Alert template for the full parameter reference.

Step 4 — Parse the event in n8n

When a price changes, your Webhook node receives:

{
  "type": "monitor.change_detected",
  "data": {
    "schedule_id": "sch_...",
    "property_id": "nl/hotel-mansion",
    "params": { "check_in": "2026-09-10", "check_out": "2026-09-12", "adults": 2, "currency": "EUR" },
    "previous_price": 296,
    "current_price": 275,
    "currency": "EUR",
    "diff": -21,
    "detected_at": "2026-08-15T09:00:03Z"
  }
}
Enter fullscreen mode Exit fullscreen mode

Add an IF node right after the Webhook trigger to branch on {{ $json.body.data.diff }} — route to your alert path only when diff < 0 (a genuine drop), and skip silently on a price increase.

Step 5 — Verify the signature (recommended)

Every delivery includes an X-Webhook-Signature header (t=<timestamp>,v1=<hex hmac>). Add a Code node before your IF branch that recomputes HMAC-SHA256(secret, "{timestamp}.{raw_body}") using the webhook endpoint's secret (returned once, at creation time, from Step 2) and compares it to the v1 value — reject anything that doesn't match before acting on it.

Step 6 — Send the alert

A complete 3-node workflow from here:

  1. Webhook — receives monitor.change_detected
  2. IF — only continues when diff < 0
  3. Slack (or Gmail, or Google Sheets) — posts "{{ $json.body.data.property_id }} dropped from {{ $json.body.data.previous_price }} to {{ $json.body.data.current_price }} {{ $json.body.data.currency }}"

No cron node, no polling, no "last price" state to persist in n8n at all — Scrapio already owns that.

Batching into a daily digest instead

If you'd rather get one summary per day instead of a message per change, set "digest_interval_minutes": 1440 in the monitor's watch and subscribe your webhook endpoint to monitor.digest_delivered instead of (or alongside) monitor.change_detected — n8n receives one event per day per monitor, with every price move that happened batched into a changes array.

Next steps

Top comments (0)