API
whatsmytraffic exposes public HTTP endpoints for three things: form submissions, a read-only analytics API and the passwordless auth service.
Form submission
POST https://whatsmytraffic.com/f/YOUR-FORM-ID
Create a form in the dashboard (under a website) to get its ID. Point an HTML form at the endpoint, or POST to it from your own code.
<form action="https://whatsmytraffic.com/f/YOUR-FORM-ID" method="POST"> <input name="email" type="email" required /> <textarea name="message" required></textarea> <button type="submit">Send</button> </form>
On success the visitor is redirected to a built-in confirmation page, or to
the path given in the optional _redirect field.
Request
The body may be application/x-www-form-urlencoded, multipart/form-data or application/json. Every field
is stored as part of the submission, except the control fields:
| Field | Purpose |
|---|---|
_gotcha | Honeypot. Keep it hidden and empty. A filled value silently marks the submission as spam. |
_redirect | Where to send the visitor after submit. Must be a relative, same-origin path (starts with a single /). |
Response
- If the request asks for JSON (
Accept: application/json, or a JSON body), the endpoint returns200with{"ok":true}. - Otherwise it returns
303and redirects to_redirect, or to a built-in confirmation page if no redirect was given.
Errors
| Status | Meaning |
|---|---|
404 | Unknown form ID |
413 | Body larger than 256 KB |
429 | Rate limit: more than 5 submissions per minute from one IP |
400 | Body could not be parsed |
AJAX
CORS is open and the OPTIONS preflight is handled, so you can
submit with fetch and read the JSON result:
await fetch('https://whatsmytraffic.com/f/YOUR-FORM-ID', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, message })
}); Side effects
Per form (configured in the dashboard), a successful, non-spam submission can trigger:
- Webhook POST, ntfy push, notify emails.
- Optional confirmation email to the address in the form's
emailfield, sent from the website's SMTP or the instance mail. - If the beacon is loaded on the same page, a
form_submitevent with{ form_id }in analytics.
Analytics API
Every website can have a share link (Websites tab, per website). The share
link opens a public, read-only analytics page; append /data to it
for a JSON feed of the same numbers. The token in the URL is also the API key:
revoke it in the dashboard to cut access.
GET YOUR-SHARE-LINK/data
Query parameters
| Parameter | Values | Default |
|---|---|---|
range | 24h, 7d, 30d, all | all |
res | hour, day, month (the allowed set depends on the range) | per range |
fields | comma-separated, see below | all fields |
fields selects which parts to return; parts you do not request
are not even queried. Available: summary, series, top_pages, top_referrers, top_countries, top_browsers.
Response
{
"website": "example.com",
"range": "7d",
"resolution": "day",
"summary": { "pageViews": 1234, "visits": 567 },
"series": [
{ "x": "2026-05-20T00:00:00.000Z", "pageviews": 120, "sessions": 80 }
],
"top_pages": [ { "x": "/", "y": 540 } ],
"top_referrers": [ { "x": "google.com", "y": 210 } ],
"top_countries": [ { "x": "DE", "y": 430 } ],
"top_browsers": [ { "x": "Chrome", "y": 690 } ]
} Series timestamps are UTC. summary and series come
from the same query, so requesting either one computes both.
Example
curl "YOUR-SHARE-LINK/data?range=30d&res=day&fields=summary,series"
A 404 means the share token is invalid or has been revoked.
Auth service
The auth service is a passwordless (magic-link) login you can add to your own site. Create an auth app in the dashboard (expand a website, open its Auth section) to get an app ID, and configure its redirect URLs and allowed origins. whatsmytraffic stores no end-user data: the session is a signed token that lives in the visitor's browser.
SDK
The simplest integration is the small browser SDK. It wraps every endpoint
below and exposes window.wmtAuth:
<script defer src="https://whatsmytraffic.com/whatsmytraffic-auth.js"
data-app-id="YOUR-APP-ID"></script>wmtAuth.login(email) requests a magic link; wmtAuth.getSession() returns the signed-in user once they return
from the link; wmtAuth.logout() clears the session.
Example: a sign-in page
A complete client-side integration: load the SDK, send the link, and switch between a signed-out and a signed-in view. The SDK captures the token from the URL fragment automatically when the user returns from the email.
<!-- 1. Load the SDK -->
<script defer src="https://whatsmytraffic.com/whatsmytraffic-auth.js"
data-app-id="YOUR-APP-ID"></script>
<!-- 2. Two states: signed out and signed in -->
<div id="signed-out">
<input id="email" type="email" placeholder="you@example.com" />
<button id="send">Email me a sign-in link</button>
</div>
<div id="signed-in" hidden>
Signed in as <span id="who"></span>
<button id="logout">Sign out</button>
</div>
<!-- 3. Wire it up -->
<script>
function render() {
var session = wmtAuth.getSession();
document.getElementById('signed-in').hidden = !session;
document.getElementById('signed-out').hidden = !!session;
if (session) document.getElementById('who').textContent = session.email;
}
addEventListener('load', render);
document.getElementById('send').onclick = function () {
wmtAuth.login(document.getElementById('email').value).then(function (res) {
alert(res.ok ? 'Check your inbox for the link.' : 'Could not send the link.');
});
};
document.getElementById('logout').onclick = function () {
wmtAuth.logout().then(render);
};
</script>This is the visitor-facing half. To act on a session from your own backend (gate an API, store an order against the email), verify the token there as shown below.
Endpoints
| Endpoint | Purpose |
|---|---|
POST /a/APP-ID/request | Body { email, redirect? }. Emails a magic link valid for 15 minutes. |
GET /a/APP-ID/callback | Target of the magic link. Issues a session token and redirects to the configured URL, token in the URL fragment. |
GET /a/APP-ID/verify | Verifies a session token (query ?token= or Authorization: Bearer) and returns its claims. |
POST /a/APP-ID/logout | Stateless acknowledgement. The token is dropped client-side. |
GET /a/APP-ID/jwks | Public keys (JWKS) for verifying session tokens locally. |
request, verify and logout are
cross-origin: the request Origin must be in the app's allowed
origins. callback is a top-level browser navigation.
Verifying a session
A session token is a signed JWT (ES256). Your backend can either ask /verify or check the signature locally against /jwks.
The sub claim is the verified email address.
const res = await fetch(
'https://whatsmytraffic.com/a/YOUR-APP-ID/verify',
{ headers: { Authorization: 'Bearer ' + sessionToken } }
);
const { ok, sub } = await res.json(); Sign-in links and sessions expire on their own; there is no server-side store. Delete the auth app in the dashboard to stop new sign-ins.
Side effects
Per auth app (configured in the dashboard), a sign-in can trigger:
- Optional welcome email on the very first sign-in of each email address. Sent from the website's SMTP or the instance mail.
- If the beacon is loaded on the same page as the SDK, two analytics events:
auth_requestwhenwmtAuth.login()is called, andauth_signinwhen the user returns through the magic link. Both carry{ app_id }.