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:
| Field | Type | Required | Description |
|---|---|---|---|
url | string | Yes | HTTPS URL to receive webhook POST requests |
events | string[] | Yes | Event 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.
| Field | Type | Description |
|---|---|---|
url | string | New HTTPS URL to receive webhook POST requests |
events | string[] | Replacement event list: price_drop, availability_change, schedule_completion |
is_active | boolean | Enable (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.