Webhooks
Webhooks (WebSub)
Get pushed the moment reviews change instead of polling. This site runs a live WebSub hub.
How WebSub works
WebSub (a W3C Recommendation) is publish/subscribe over HTTP. You register a callback URL with a hub for a given topic (a feed URL). When the topic content changes, the hub POSTs the new content to your callback. No polling, no API key — just an HTTPS endpoint you control. Read the full spec at w3.org/TR/websub.
Hub endpoint
Send all subscribe/unsubscribe requests here:
https://harborchasereviews.com/api/websub/hub
Topics
Subscribe to any of these topic URLs. They all track the same underlying review data in different formats:
| Topic URL | Format |
|---|---|
https://harborchasereviews.com/feed.xml | Atom feed of newest reviews |
https://harborchasereviews.com/api/feed.json | JSON Feed v1.1 of newest reviews |
https://harborchasereviews.com/reviews.json | Full reviews dataset |
1. Subscribe
POST a form-encoded subscription request to the hub with your callback, the mode, and the topic:
curl -X POST https://harborchasereviews.com/api/websub/hub \ --data-urlencode "hub.callback=https://you.example/cb" \ --data-urlencode "hub.mode=subscribe" \ --data-urlencode "hub.topic=https://harborchasereviews.com/feed.xml"
2. Verify (the challenge handshake)
Before activating the subscription, the hub sends a GET to your callback with hub.mode, hub.topic, and a random hub.challenge query parameter. To confirm intent, echo the hub.challenge value back in the response body with a 2xx status. Reply with any non-2xx (or the wrong body) and the subscription is rejected.
GET https://you.example/cb?hub.mode=subscribe&hub.topic=https://harborchasereviews.com/feed.xml&hub.challenge=Kd83hQ...&hub.lease_seconds=86400 # Your callback responds: HTTP/1.1 200 OK Content-Type: text/plain Kd83hQ... ← echo the exact challenge back
3. Receive notifications
Once verified, every time the topic changes the hub POSTs the full topic content to your callback. The request carries a Link header pointing back at the hub and the topic — use it to discover the hub for renewals.
POST https://you.example/cb Content-Type: application/atom+xml Link: <https://harborchasereviews.com/api/websub/hub>; rel="hub", <https://harborchasereviews.com/feed.xml>; rel="self" <?xml version="1.0"?> <feed xmlns="http://www.w3.org/2005/Atom"> ...the updated feed content... </feed> # Respond 2xx to acknowledge receipt.
4. Unsubscribe
Same request as subscribing, with hub.mode=unsubscribe. The hub re-runs the challenge handshake to confirm before removing the subscription.
curl -X POST https://harborchasereviews.com/api/websub/hub \ --data-urlencode "hub.callback=https://you.example/cb" \ --data-urlencode "hub.mode=unsubscribe" \ --data-urlencode "hub.topic=https://harborchasereviews.com/feed.xml"
Pitfalls
- Your callback URL must be HTTPS. Plain HTTP callbacks are rejected.
- You must echo the exact hub.challenge value in the verification response body, with a 2xx status. A 200 with the wrong body fails verification.
- Acknowledge each notification with a 2xx. After 3 consecutive delivery failures the hub auto-unsubscribes your callback — you will stop receiving notifications and must re-subscribe.
- Subscriptions have a lease (hub.lease_seconds); re-subscribe before it expires to keep receiving updates.