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.

HTML form Click to copy
<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:

FieldPurpose
_gotchaHoneypot. Keep it hidden and empty. A filled value silently marks the submission as spam.
_redirectWhere 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 returns 200 with {"ok":true}.
  • Otherwise it returns 303 and redirects to _redirect, or to a built-in confirmation page if no redirect was given.

Errors

StatusMeaning
404Unknown form ID
413Body larger than 256 KB
429Rate limit: more than 5 submissions per minute from one IP
400Body 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 email field, sent from the website's SMTP or the instance mail.
  • If the beacon is loaded on the same page, a form_submit event 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

ParameterValuesDefault
range24h, 7d, 30d, allall
reshour, day, month (the allowed set depends on the range)per range
fieldscomma-separated, see belowall 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:

Auth SDK Click to copy
<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.

Sign-in page Click to copy
<!-- 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

EndpointPurpose
POST /a/APP-ID/requestBody { email, redirect? }. Emails a magic link valid for 15 minutes.
GET /a/APP-ID/callbackTarget of the magic link. Issues a session token and redirects to the configured URL, token in the URL fragment.
GET /a/APP-ID/verifyVerifies a session token (query ?token= or Authorization: Bearer) and returns its claims.
POST /a/APP-ID/logoutStateless acknowledgement. The token is dropped client-side.
GET /a/APP-ID/jwksPublic 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_request when wmtAuth.login() is called, and auth_signin when the user returns through the magic link. Both carry { app_id }.