Tinylytics + n8n
n8n talks to Tinylytics through the same two building blocks every other client uses: outbound webhooks for things that happen to you, and the API for things you go and ask for. There is no official Tinylytics community node yet, so you assemble the built-in Webhook, HTTP Request, and Code nodes yourself — which sounds like more work than it is, and we have sample workflows below to save you the first hour.
What works today
| Goal | How |
|---|---|
| React when a site goes down or recovers | Tinylytics webhook → n8n Webhook trigger (monitor_down, monitor_up) |
| React to live hits, kudos, or custom events | Tinylytics webhook → n8n Webhook trigger (new_hit, new_kudo, new_event) |
| React when an AI insight is generated | Tinylytics webhook → n8n Webhook trigger (new_insight) |
| React to content-monitoring issues | Tinylytics webhook → n8n Webhook trigger (content_issue) |
| Pull analytics on a schedule | n8n Schedule + HTTP Request against /api/v1 |
| Verify webhook authenticity | HMAC over the raw body using X-Signature |
Webhooks require an active paid subscription. API keys are available from Account Settings → API Access. Prefer webhooks over tight polling when you can — API requests are rate limited.
Sample workflows
Import these into n8n (⋯ menu → Import from File), then follow the sticky notes in each workflow.
| Workflow | Download | What it does |
|---|---|---|
| Receive webhooks | receive-webhooks.json | Verifies X-Signature, routes core webhook events, formats a message field you can send onward |
| Daily top paths | daily-top-paths.json | Calls GET /sites/:id/hits?grouped=true&group_by=path for yesterday and builds a short summary |
| Poll uptime | poll-uptime.json | Calls GET /sites/:id/uptime on a timer; prefer webhooks for real downtime alerts |
The sample workflows stop at a formatted message (or equivalent). Connect Slack, email, Discord, Linear, or any other n8n node yourself — Tinylytics does not ship those credentials.
1. Receive Tinylytics webhooks in n8n
Requirements
- Paid Tinylytics plan
- An n8n instance with a public HTTPS URL (Tinylytics blocks localhost and private network URLs)
- Webhook platform set to Generic (not Discord)
- Wrap content left off for the sample expressions
If you only need Discord downtime embeds, Tinylytics already has a native Discord webhook platform — you do not need n8n for that path.
Steps
- Import receive-webhooks.json (or recreate the flow below).
- Open the Tinylytics Webhook node, activate the workflow, and copy the Production URL.
- In Tinylytics go to Account Settings → Webhooks, create a webhook with that URL, select the event types you want, and save.
- Copy the signing secret into the Verify Signature Code node (
SIGNING_SECRET). - Use Send Test on the webhook edit screen. You should see a successful delivery and a workflow execution in n8n.
Signature verification
Tinylytics signs the exact JSON body with your webhook signing secret and sends:
X-Signature: sha256=<hex HMAC SHA-256 digest>
Also sent: X-Tinylytics-Event, X-Tinylytics-Delivery, X-Tinylytics-Timestamp.
In n8n:
- Enable Raw Body on the Webhook node (required — the signature is over the raw bytes, not re-serialized JSON).
- Verify with a Code node using the binary raw body, for example:
const crypto = require('crypto');
const SIGNING_SECRET = 'your-signing-secret';
const headers = $input.item.json.headers || {};
const signature = String(headers['x-signature'] || '');
const rawBody = await this.helpers.getBinaryDataBuffer(0, 'data');
const expected = 'sha256=' + crypto.createHmac('sha256', SIGNING_SECRET).update(rawBody).digest('hex');
const sigBuf = Buffer.from(signature);
const expBuf = Buffer.from(expected);
if (sigBuf.length !== expBuf.length || !crypto.timingSafeEqual(sigBuf, expBuf)) {
throw new Error('Invalid Tinylytics webhook signature');
}
return { json: $input.item.json.body };
Treat deliveries as at-least-once. Store X-Tinylytics-Delivery, or hit.id / kudo.uid / analytics_event.id / insight.id / check.id, if duplicate handling matters.
Full payload shapes are documented in Webhooks.
Event types (core)
| Event | When it fires |
|---|---|
monitor_down |
Uptime monitor reports the site down |
monitor_up |
Uptime monitor reports recovery |
new_hit |
An accepted live hit (script, pixel, or API create/batch) |
new_kudo |
An accepted browser kudo, API kudo, or verified Webmention like |
new_event |
An accepted custom analytics event (script or API create/batch) |
new_insight |
A new AI insight record is created |
content_issue |
Content monitoring records a new/changed broken link or mixed content issue |
Ignored paths, ignored visitors, spam-suppressed writes, imports, seeds, and similar non-live writes do not emit hit/kudo/custom-event webhooks. See Webhooks.
2. Call the Tinylytics API from n8n
Auth
Authorization: Bearer tly-ro-your-api-key
Accept: application/json
Use a read-only key (tly-ro-...) for GET workflows. Use a full-access key (tly-fa-...) only when you intentionally write hits, events, kudos, signals, sites, or groups.
Create keys under Account Settings → API Access. Base URL: https://tinylytics.app/api/v1.
Smoke test
HTTP Request node:
- Method:
GET - URL:
https://tinylytics.app/api/v1/me - Header:
Authorization: Bearer tly-ro-...
A valid key returns HTTP 200 with your account payload.
Useful read endpoints for automation
| Endpoint | Notes |
|---|---|
GET /me |
Validate the key |
GET /sites |
List sites and ids |
GET /sites/:id/hits |
Raw or grouped hits (grouped=true, `group_by=path\ |
GET /sites/:id/kudos |
Kudos list |
GET /sites/:id/leaderboard |
All-time path leaderboard |
GET /sites/:id/uptime |
Subscription + uptime enabled on the site |
GET /sites/:id/content |
Subscription + content monitoring |
GET /sites/:id/insights |
Subscription |
GET /sites/:id/signals |
Subscription + insights enabled on the site |
Date query params use YYYY-MM-DD. Analytics ranges default to UTC day boundaries; pass time_zone=user to use your account timezone. Details: API docs.
Example: yesterday’s top paths
GET https://tinylytics.app/api/v1/sites/SITE_ID/hits
?grouped=true
&group_by=path
&start_date=YYYY-MM-DD
&end_date=YYYY-MM-DD
&time_zone=user
&per_page=10
That is what daily-top-paths.json calls. Grouped-by-path rows include views (and unique_views when unique hits are enabled).
What is not available
These gaps are listed plainly so you do not spend an evening building a workflow that can never fire:
| Missing today (core product) | Workaround |
|---|---|
| Official Tinylytics n8n node / OAuth app | Use Webhook + HTTP Request as documented here |
| GET list endpoint for custom analytics events | Events are write-only via the API (POST /sites/:id/events); use the new_event webhook for push |
| Webhook when a scheduled email report is sent | No equivalent push event |
| Native Slack webhook platform | Send Generic webhooks to n8n, then use n8n’s Slack node |
Troubleshooting
| Problem | What to check |
|---|---|
| Tinylytics rejects the webhook URL | URL must be public HTTP(S). Localhost / private IPs are blocked |
| No deliveries | Paid plan active? Webhook active? Event type selected? |
| Signature always fails | Raw Body enabled? Secret pasted correctly? Verify against raw bytes, not JSON.stringify(body) |
| Test works, live hits do not | Hit may be ignored, spam-suppressed, imported, or otherwise non-live — see Webhooks |
API 401 |
Wrong or revoked key; header must be Authorization: Bearer … |
API 403 on uptime/insights/content |
Active subscription required; some features must also be enabled on the site |
Uptime poll returns 404 |
Uptime is not enabled for that site |
| Discord-shaped payload in n8n | Use the Generic webhook platform for n8n |