Webhooks
Detour webhooks let you receive your analytics data on a recurring schedule, delivered automatically to an HTTPS endpoint you control. Instead of polling the dashboard or exporting manually, you register an endpoint once and Detour sends a signed JSON payload on each scheduled run.
Each webhook is tied to a specific app and a specific export type. You manage all of an organization's webhooks from the Webhooks section in the sidebar.
Availability
Webhooks are a paid feature. The number of active webhooks you can run depends on your plan:
| Plan | Active webhooks |
|---|---|
| Free | 0 (unavailable) |
| Starter | 3 |
| Scale | 10 |
| Enterprise | Custom |
For full plan details, see Billing & Payments.
- If you try to create a webhook beyond your active limit, it is saved but created paused (inactive) — activate it later after freeing up a slot.
- If you downgrade to a plan with a lower limit, the oldest active webhooks are automatically paused to fit the new limit.
Creating a webhook
When creating a webhook you configure:
- App — which app's data to export.
- Endpoint URL — where the payload is delivered. Must be a public HTTPS URL on the default port (443). Endpoints that resolve to private/internal addresses are rejected.
- Export type — the dataset to send:
Overview— aggregated performance (link stats, organic vs non-organic installs, retention, top events).Links— link-level breakdown (paths and query parameters).Events— SDK event activity.
- Schedule —
Daily,Weekly, orMonthly. - Platform —
all,ios, orandroid. - Filters — optional, to narrow the exported data.
When the webhook is created, a signing secret is shown once. Store it securely — it cannot be retrieved again later (you can rotate it if lost, see Managing webhooks).
Delivery schedule
Deliveries run on a fixed daily cycle (around 08:00 UTC). Each delivery covers the period that just closed:
| Schedule | Runs on | Period covered |
|---|---|---|
Daily | Every day | The previous day |
Weekly | Mondays | The previous 7 days |
Monthly | The 1st of each month | The previous calendar month |
All period boundaries are in UTC.
Payload format
Each delivery is an HTTP POST with a JSON body:
{
"webhook_id": "<your webhook id>",
"type": "overview | links | events",
"app_id": "<your app id>",
"period": {
"start": "2026-05-01T00:00:00.000Z",
"end": "2026-06-01T00:00:00.000Z"
},
"delivered_at": "2026-06-01T08:00:00.000Z",
"data": [ /* rows for the selected export type */ ]
}
The shape of each row in data matches the chosen export type (the same rows
you get from a manual export of that view).
Verifying the signature
Every request includes an X-Webhook-Signature header so you can confirm the
payload came from Detour and wasn't tampered with:
X-Webhook-Signature: sha256=<hex digest>
The digest is an HMAC-SHA256 of the raw request body, keyed with your webhook's signing secret. Compute the same HMAC on your side and compare:
import { createHmac, timingSafeEqual } from "crypto";
function isValidSignature(rawBody, header, signingSecret) {
const expected = createHmac("sha256", signingSecret)
.update(rawBody)
.digest("hex");
const received = (header ?? "").replace(/^sha256=/, "");
const a = Buffer.from(expected);
const b = Buffer.from(received);
return a.length === b.length && timingSafeEqual(a, b);
}
Always compute the HMAC over the raw, unparsed request body. Re-serializing the JSON can change bytes (key order, whitespace) and break the comparison.
Delivery behavior
- Detour only follows the configured URL — redirects are not followed.
- The endpoint must respond with a 2xx status within 10 seconds for the delivery to count as successful.
- Failed deliveries are not retried within the same cycle. The next attempt is the next scheduled run. Make sure your endpoint is reachable at delivery time.
- The dashboard shows the last successful delivery time for each webhook.
Managing webhooks
From the Webhooks section you can:
- Pause / resume a webhook. Resuming is subject to your plan's active-webhook limit — pause another webhook first if you're at the limit.
- Rotate the signing secret. A new secret is shown once and the previous one stops being valid immediately, so update your endpoint before rotating.
- Delete a webhook.
There is no in-place edit for a webhook's URL, schedule, export type, or platform — to change those, delete the webhook and create a new one.