# Webhooks

> Signed event deliveries for product events (pro apps).

Source: https://docs.tune.toys/developers/webhooks/ (updated 2026-11-01)

Pro apps with a live key that has `read:products` can receive signed webhooks for products of the app's publisher.

| Topic        | Behavior                                                                                                                                                                                   |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Events       | `version_published`, `listing_updated`, `review_created`, `purchase_completed`, `update_feed_changed`. Not every event is wired in every build; see the status note in the platform guide. |
| Payload      | `{ id, type, createdAt, apiVersion, data }`. `data` holds ids and minimal fields (at most 1 KiB). Fetch details through the API.                                                           |
| Signature    | `TuneToys-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256(secret, t + "." + body)>`, plus `TuneToys-Webhook-Id` and `TuneToys-Event-Id`.                                                   |
| Secret       | `whsec_...`, shown once.                                                                                                                                                                   |
| Endpoint     | Public HTTPS only. Private, loopback and link-local addresses are refused at connect time. No redirects. 10 second timeout.                                                                |
| Verification | Creating a webhook sends `webhook.verify` with `data.challenge`. Respond 2xx with JSON echoing `{"challenge": ...}`.                                                                       |
| Retries      | Eight attempts: immediately, then 1 min, 5 min, 30 min, 2 h, 6 h, 12 h and 24 h. A webhook with no success in three days is disabled.                                                      |

## Verifying a delivery

1. Read the raw body.
2. Reject a timestamp `t` older than five minutes.
3. Compute `HMAC-SHA256(secret, t + "." + rawBody)` and compare in constant time with each `v1` value.
4. Deduplicate on the event id.

The SDK exports `verifyWebhook` which does steps 2 and 3.
