Get price-drop and availability webhooks

Last updated · Changelog · OpenAPI spec · Markdown

Register webhook URLs to get notified when prices drop, product availability changes, or scheduled refreshes complete.

Create Webhook

Endpoint: POST /v1/webhooks

Request Body:

FieldTypeRequiredDescription
urlstringYesHTTPS URL to receive webhook POST requests
eventsstring[]YesEvent types: price_drop, availability_change, schedule_completion

Example:

curl -X POST 'https://api.shopsavvy.com/v1/webhooks' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"url": "https://your-app.com/webhooks/shopsavvy", "events": ["price_drop", "availability_change"]}'

The response includes a secret field (shown once) — use it to verify webhook signatures.

Webhook Delivery Format

Every delivery is a JSON POST shaped like this:

{
  "id": "8f14e45f-ceea-467a-9d2b-1c8f0b1a9c33",
  "event": "price_drop",
  "attempt": 1,
  "timestamp": "2026-08-10T18:04:11.529Z",
  "data": { "product": { }, "retailer": "amazon", "price": { }, "availability": { } }
}

id is the stable identifier for the event. attempt is the 1-based delivery attempt — 1 on the first delivery, 2 through 5 on retries. Both are also sent as headers, X-ShopSavvy-Event-Id and X-ShopSavvy-Delivery-Attempt, so you can check them without parsing the body.

Deduplicating Retries

Delivery is at-least-once. If your server processes a request but the response is lost, times out, or returns a non-2xx status, we treat the delivery as failed and retry it — so you can receive the same event more than once.

id stays the same across the first attempt and every retry of that event, and is different for every new event. Record the ids you have processed and ignore a repeat. timestamp and the signature change on every attempt and must not be used for this.

attempt tells you which delivery of that event you are looking at without keeping any state of your own — attempt > 1 means we did not see a 2xx for an earlier delivery of the same id. It is informational; dedupe on id.

Verifying Webhook Signatures

Every webhook delivery includes an X-ShopSavvy-Signature header with format: t=<timestamp>,v1=<signature>.

To verify: compute HMAC-SHA256(secret, "<timestamp>.<request_body>") and compare to v1.

List Webhooks

GET /v1/webhooks — Returns all your registered webhooks with status and failure counts.

Update Webhook

Endpoint: PUT /v1/webhooks/:id

Update an existing webhook without losing its signing secret. All fields are optional, but at least one must be provided. Omitted fields are left unchanged — so you can flip is_active without resending url or events.

FieldTypeDescription
urlstringNew HTTPS URL to receive webhook POST requests
eventsstring[]Replacement event list: price_drop, availability_change, schedule_completion
is_activebooleanEnable (true) or disable (false) the webhook

Example — disable a webhook without deleting it:

curl -X PUT 'https://api.shopsavvy.com/v1/webhooks/wh_abc123' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"is_active": false}'

Re-enabling a webhook (is_active: true) resets its consecutive-failure counter, so a webhook that was auto-disabled after repeated failures starts fresh.

Test Webhook

POST /v1/webhooks/:id/test — Sends a test event to verify your URL is reachable.

Delete Webhook

DELETE /v1/webhooks/:id — Permanently removes a webhook and all its event history.

Retry Policy: Failed deliveries are retried with exponential backoff (1min, 5min, 30min, 2hr, 12hr). After 5 failed attempts per event, the event is marked as permanently failed. After 50 consecutive failures, the webhook is automatically disabled.

Limits: Maximum 5 webhooks per account. Maximum 3 event types per webhook.

Was this page helpful?