HarborChase of Mandarin

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 URLFormat
https://harborchasereviews.com/feed.xmlAtom feed of newest reviews
https://harborchasereviews.com/api/feed.jsonJSON Feed v1.1 of newest reviews
https://harborchasereviews.com/reviews.jsonFull 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.