Webhook Integration Guide
When you set up a Webhook, Miharu sends its monitoring results (System Alerts) to a URL you specify as an HTTP POST with a JSON body. You can connect it to Zapier, Make, n8n, your own server, and more to process notifications however you like.
This feature is for developers and power users. A receiving endpoint is required on your side.
1. Setup
- 1In the app, open “External Notifications” → “Webhook”.
- 2Enter the destination Webhook URL (must start with
https://). - 3Optionally set the notification filter (e.g., only a specific Monitoring Group).
- 4On save, one test notification confirming the setup is delivered.
2. HTTP Specification
No signature (e.g., HMAC) header is sent. The Webhook URL itself is the secret (see Security below).
3. Payload (common fields)
4. Event types and detail
{ diff: [...], truncated: bool }{ hits: [{ keywords: [...], excerpts: [...] }] }{ links: [{ text, url }] }{ target_name, before, after }{ target_name, before, after }{ kind: string } (a string identifying the kind)The diff for page_changed
diff is an array of changes. Each element is one of:
{ "op": "added", "text": "..." }… an added line{ "op": "removed", "text": "..." }… a removed line{ "op": "replaced", "before": "...", "after": "..." }… a replaced line
If truncated is true, the diff was large and partially omitted.
5. Examples
Change Detection (page_changed)
{
"source": "miharu",
"version": "1",
"id": "5c2e1b7a-9f3d-5a6b-8c4e-1d2f3a4b5c6d",
"timestamp": "2026-05-22T01:23:45Z",
"language": "en",
"event": "page_changed",
"monitor": { "id": "abc123", "name": "Product page", "url": "https://example.com/item" },
"message": { "body": "The page has been updated.", "label": "Update" },
"detail": {
"diff": [
{ "op": "replaced", "before": "Out of stock", "after": "In stock" },
{ "op": "added", "text": "Restocked today" }
],
"truncated": false
}
}Keyword Detection (keyword_hit)
{
"source": "miharu", "version": "1", "id": "…",
"timestamp": "2026-05-22T01:23:45Z", "language": "en",
"event": "keyword_hit",
"monitor": { "id": "abc123", "name": "Stock page", "url": "https://example.com/stock" },
"message": { "body": "A keyword has been detected.", "label": "Keyword" },
"detail": { "hits": [ { "keywords": ["restock"], "excerpts": ["…restocked today…"] } ] }
}New Link Detection (new_link)
{
"…": "…",
"event": "new_link",
"message": { "body": "A new link has been detected.", "label": "New Link" },
"detail": { "links": [ { "text": "New product announcement", "url": "https://example.com/news/123" } ] }
}Price/Value change (price_changed)
{
"…": "…",
"event": "price_changed",
"message": { "body": "“Price” has changed.\n\n1980 → 1480", "label": "Price/Value" },
"detail": { "target_name": "Price", "before": "1980", "after": "1480" }
}6. Idempotency (deduplication)
The same event always arrives with the same id, even on retries (the same value is also in the X-Miharu-Notification-Id header). Use id on your side to avoid processing duplicates.
7. Security
- HTTPS required (only
https://URLs can be set). - No signature header is sent, so treat the Webhook URL itself as a secret (if leaked, a third party could send fake notifications).
- If needed, include a random token in the URL (e.g.,
https://example.com/hook/<random>) and verify it on your side. - For a lightweight origin hint, you can check
User-Agent: Miharu-Webhook/1.0and theX-Miharu-*headers (supplementary only).
8. Integrations
Generate a receiving URL in your service and set it as the Webhook URL in Miharu.
- Zapier: the URL from “Webhooks by Zapier” → “Catch Hook”
- Make: the URL of a “Custom webhook”
- n8n: the URL of a “Webhook” node
- Your own server: an endpoint that accepts the JSON body and returns 2xx
9. Limitations
- Webhook delivers System Alerts (detections) and system notifications.
- Long diffs or text may be truncated (e.g.,
truncated: true). - Use the notification filter to limit delivery to a specific Monitoring Group.
10. Troubleshooting
- Does the URL start with
https://? - Is your endpoint returning 2xx? (Redirects and errors count as failures.)
- Has delivery stopped after repeated non-2xx responses? Check the status in the app and reconfigure to resume.
- Is processing taking over 10 seconds (timeout)? Return 2xx immediately and process asynchronously.
Share your feedback via “Feedback & Suggestions” in the app.