Manual setup
Add the Atune middleware yourself — any framework, no CLI, full control.
If you don't want auto-wiring — or you're not on Next.js — add the middleware yourself. Capture requires a resolved account ID and server-side credentials.
1. Install
npm install atune2. Set env vars
Add to .env.local (or your platform's secret store):
ATUNE_API_KEY=<YOUR_API_KEY>ATUNE_URL=https://test.useatune.comSign in to find your API key in Settings.
ATUNE_API_KEY is your workspace key from Settings → API key. It is the
only secret and stays server-side. You can rotate it there if it leaks.
ATUNE_URL is the bare host, with no path. The SDK adds /api/v1/... itself,
so never append /api/v1/events or any other path.
3. Add the middleware
// proxy.ts on Next.js 16; middleware.ts on Next.js 14/15
import { createAtuneMiddleware } from "atune";
const atune = createAtuneMiddleware();
export default function capture(request: Request) {
return atune(request);
}This example is for a fresh entry point. Keep existing auth and redirects when
adding capture to an existing app: pass its response to atune(request, response)
and return that response. See chaining.
The published installer cannot automatically chain every handler.
Not on Next.js? Skip the middleware and send events with track() (any Node
backend) or the HTTP API (any language). See Any backend.
What gets captured
The middleware records requests with a resolved account ID as http.<method>.<normalized-route> with
the resolved account and user. Request bodies are never read — no passwords,
tokens, or card numbers. It's fire-and-forget: a slow or down Atune can never
delay or break your app.
4. Verify
Sign in to your app and make one request. Then open Settings → Event log in
Atune: the newest event is named http.<method>.<route> and must carry the
account and user you just used. The SDK logs nothing, so if nothing shows up,
check that ATUNE_API_KEY is set, that ATUNE_URL is the bare host, and that
the request resolves to an account.
Once events land, you can ask about an account. Replace
acme below with that account ID. A knows: false result alone does not tell
you whether capture failed or the evidence is still insufficient; inspect
signals and the received events. An installer success message is not delivery proof:
import { understand } from "atune";
const r = await understand("account:acme", "What recent behavior is available?");
console.log(r.knows, r.signals);