# Agent Analytics Docs > Guides, installation pages, reference pages, and the full API reference for Agent Analytics. ## Guides URL: https://docs.agentanalytics.sh/guides/ Task-oriented guides for setting up Agent Analytics and running experiments through AI agents such as Claude Code, Cursor, Codex, and OpenClaw. Use these guides when you want to tell an AI agent such as Claude Code, Cursor, Codex, or OpenClaw what to do, not manually stitch together the low-level steps yourself. ## Start with the right guide If you are landing from a Paperclip company workflow, start with [Set up Agent Analytics for your Paperclip company](/guides/paperclip/) for onboarding and [Paperclip Live Plugin](/reference/paperclip-live-plugin/) for the thin live-monitor surface. If you need environment-specific setup outside Paperclip, use the [installation hub](/installation/). If you need low-level browser or endpoint details, continue to [Tracker.js](/reference/tracker-js/) or the [API reference](/api/). ## Getting Started URL: https://docs.agentanalytics.sh/getting-started/ Create a project, install Agent Analytics in your AI agent, and verify the first query. This is the shortest path from zero to a working Agent Analytics setup. The main flow is agent-first: choose `Connect as agent`, start in the AI agent you already use, let that agent open the browser for you or give you a login link, then have it create the project and wire tracking for you. Use `Connect as human` only when you need direct account access yourself, such as billing, cancellation, or manual review. Browser approval and finish-code handoff still belong to the normal agent-owned setup flow. If your AI agent, such as Claude Code, OpenWork, Cursor, Codex, or OpenClaw, is already installed and you want the clearest create-project, place-snippet, verify-first-page-view, and add-first-useful-event walkthrough, use [First Project in 5 Minutes](/guides/first-project-in-5-minutes/). If you only have a public URL and want a scanner-informed setup preview, use [Product Growth Scanner](/guides/website-analysis/). When your agent has repo access, let it inspect the product code and ask you to confirm the initial goal before it installs intentional events. If you want to understand the two public skills first, start with [Agent Analytics Skill](/guides/agent-analytics-skill/) for setup and reporting, then [Autoresearch Growth Skill](/guides/autoresearch-growth-skill/) for data-informed variant generation. ## 1. Pick and complete an install path Go to the [installation hub](/installation/) and complete the setup for the environment you actually use: - [Claude Code](/installation/claude-code/) - [Claude Desktop / Cowork](/installation/claude-desktop-cowork/) - [OpenWork](/installation/openwork/) - [Cursor](/installation/cursor/) - [OpenClaw](/installation/openclaw/) - [OpenAI Codex](/installation/openai-codex/) If none of those are a fit, the [API reference](/api/) stays available for direct integration into your own runtime. ## 2. Open your AI agent in the project directory Start from the codebase or site you actually want to track. Then ask your AI agent for the full setup flow: - `Set up Agent Analytics for this project. Open the browser for me and wait while I sign in with Google or GitHub and approve it. Ask for a finish code only if the browser callback cannot resume you. Then create or identify the matching project, ask me to confirm the initial product goal before storing durable context, install the project-owned tracker, add only meaningful events tied to this repo's product workflows and that goal, explain what each event enables, and verify the first useful event.` When the browser approval page opens, sign in with Google or GitHub, approve it, and let the agent continue. That approval creates or connects your account and gives the agent the session it needs. ## 3. Create your first project After your AI agent is connected, ask it to create the first project for you: - `Create a project called my-site.com` - `Create a project called my-site.com and give me the tracking snippet` If your AI agent has code write access to your site, ask it: - `Set up analytics for my-site.com. Inspect the product code and workflows, ask me to confirm the initial goal, then install only the first useful events tied to that goal.` Your AI agent should create the project and either: - return the tracker snippet for you to paste, or - install the tracker itself if it can edit the site ## 4. Add the tracker manually if needed If your AI agent already added the tracker to your site, skip this step. If it only created the project and returned a snippet, add the script before ``: ```html ``` The initial page view is tracked automatically. If your app is a SPA and you want route changes tracked automatically too, add `data-track-spa="true"` to the script tag; otherwise send intentional manual page calls for virtual screens. Automatic URL fields are privacy-safe by default: `url` and `referrer` are sanitized to origin plus pathname, and automatic attribution only reads the allowlisted UTM keys `utm_source`, `utm_medium`, `utm_campaign`, `utm_content`, and `utm_term`. Add intentional events with `data-aa-event` attributes or `window.aa.track()` so your agent can answer questions tied to the product goal. If your product has login or signup, keep `signup` for the moment the account is actually created, preferably server-side. After auth succeeds in the browser, call `window.aa.identify(account.id, { email: account.email })` only when you intentionally want support lookup by email. Use your stable app/account ID as the user ID, not the email address. Agent Analytics computes a project-scoped HMAC lookup on the server and strips raw email from event rows and profile traits by default. Browser storage is project-scoped by token/name. Older unscoped anonymous IDs are not migrated, so a visitor may receive a new scoped anonymous ID after upgrading from an older tracker. If your site uses Astro, add `is:inline` to that tracker tag. For advanced tracker options like declarative events, cross-domain identity, consent, scroll depth, vitals, and error tracking, use the [Tracker.js guide](/reference/tracker-js/). If your app is a SPA, use [SPA and Virtual Page Tracking](/guides/spa-and-virtual-page-tracking/) to decide between `data-track-spa="true"` route tracking and manual virtual `page_view` calls. If you want your AI agent to launch your first browser-side A/B test after setup, continue with [AI Agent Experiment Tracking](/guides/ai-agent-experiment-tracking/). ## 5. Verify the loop Once the install is working and the tracker is live, ask your AI agent one of these: - `List my projects` - `How is my-site doing this week?` - `What are the top pages for my-site this week?` - `Show bot traffic for my-site this week` If the setup is correct, the agent should answer without you hand-writing requests or opening a reporting UI. ## Compatibility API keys If you need direct HTTP access for a server-side runtime that cannot use agent sessions, generate an API key from [app.agentanalytics.sh](https://app.agentanalytics.sh). CLI, MCP, paid upgrades, and agent onboarding should use browser approval and agent sessions instead. ## Next - Use [Installation](/installation/) for the fastest per-agent or per-workspace setup. - Use [First Project in 5 Minutes](/guides/first-project-in-5-minutes/) when you want the full activation walkthrough from installed agent to first live project. - Use [Product Growth Scanner](/guides/website-analysis/) when you only have a public URL or want a scanner-informed preview before agent-assisted instrumentation. - Use [Agent Analytics Skill](/guides/agent-analytics-skill/) when you want the regular skill for setup, reporting, and experiments. - Use [Autoresearch Growth Skill](/guides/autoresearch-growth-skill/) when you want a loop that generates variants, tests approved experiments, and feeds the next run from measured behavior. - Use [SPA and Virtual Page Tracking](/guides/spa-and-virtual-page-tracking/) when your app changes screens client-side and you need accurate page tracking without double-counting. - Use [AI Agent Experiment Tracking](/guides/ai-agent-experiment-tracking/) when you want your AI agent to launch and read browser-side experiments for you. - Use [Tracker.js](/reference/tracker-js/) for browser-side tracking options. - Use [Bot Traffic](/reference/bot-traffic/) to inspect filtered automated callers separately from normal analytics. - Use [Authentication](/reference/authentication/) when you need the read token vs write token rules. - Use [API Reference](/api/) when you need endpoint-level details. ## Set up Agent Analytics for your Paperclip company URL: https://docs.agentanalytics.sh/guides/paperclip/ Ask the user to create one CEO task, then review the blocked task when login approval is needed, and finally query the live project. [πŸ“ŽPaperclip](https://paperclip.ing/) is open-source orchestration for zero-human companies. The clean Agent Analytics path in πŸ“ŽPaperclip is now: 1. ask the user to create one task for the CEO 2. review the blocked task when login approval is needed 3. ask the analyst the first real traffic or signup question Use `Connect as agent` if you want the agent to own that blocked-login handoff from start to finish. Use `Connect as human` only when you need direct account access yourself, not because the setup flow has changed. For normal Paperclip setup, keep browser approval and finish-code handoff as the default path. Paid upgrades use the CLI handoff link, not a pasted API key. If you want the strategic context before you set this up, read [If You Use Paperclip, You Need End-User Analytics](https://blog.agentanalytics.sh/blog/paperclip-companies-need-agent-readable-analytics/). If the engineer already has access and you only need the activation loop, continue with [First Project in 5 Minutes](/guides/first-project-in-5-minutes/). ## Step 1: create one CEO task For most Paperclip companies, the setup should start with one explicit CEO task. Task title: ```text Hire an analyst to use AgentAnalytics ``` Task description: ```text Hire or assign the analytics analyst for our company. First install the Agent Analytics skill in Paperclip: npx skills add agent-analytics/skills Make sure Agent Analytics is available to the analyst and the engineer working on the project. Ask the engineer on the relevant project to set up Agent Analytics tracking in the codebase. If approval is needed, send me the approval link, wait for me to sign in with Google or GitHub, accept the finish code I reply with, and then continue by creating the project, adding tracking and key events, and verifying the first event. ``` ![CEO task for hiring an analyst and setting up Agent Analytics in Paperclip](/paperclip-ceo-issue-creation.png) ## Step 2: review the blocked task and approve login At some point, the working agent will return that the task is blocked because it needs your help with login approval. When that happens: 1. open the login approval URL the agent posted in the Paperclip task 2. sign in with Google or GitHub 3. copy the finish code from the browser 4. paste that finish code back into the blocked Paperclip task ![Agent Analytics finish-code handoff screen](/finishcode.jpg) That lets the working setup agent continue: - finish login - create the project - add tracking - verify the first event If your Paperclip company wants a shared install primitive, the company skill key is still: ```text agent-analytics/skills/agent-analytics ``` But that is implementation detail, not the main product story. The important path is still: create one CEO task, let it drive the setup in the real project, then ask real analytics questions. ## What approval looks like in practice In Paperclip, the detached login flow should look like this: 1. the working setup agent starts Agent Analytics detached login, gets an approval URL, and the start command exits 2. you open that URL in the browser 3. you sign in with Google or GitHub 4. the browser shows a finish code 5. you paste that finish code back into the Paperclip issue thread 6. the working setup agent uses that code to complete login and keep going Paperclip should not depend on a long-running polling command for this path. The finish-code reply is the handoff that lets the agent resume reliably inside the issue thread. The important product rule is simple: the user approves identity in the browser, but the working agent ends up holding the session and continues the setup. If you later want to review or revoke that Paperclip-owned session, open [app.agentanalytics.sh](https://app.agentanalytics.sh), go to `Account Settings`, and use the `Agent Sessions` section. That page now shows active Paperclip, CLI, macOS Live, and similar hosted agent logins. ## Step 3: ask the analyst real questions Once the engineer has the project live, ask the analyst real questions: - `Show me traffic, top pages, recent events, signups, purchases, and feature usage for this project.` - `Set up an A/B experiment for this project and help me decide what to change next.` - `Create a recurring 8:00 AM analyst job. Every morning, query Agent Analytics for the latest 24 hours across this company's projects and post a short brief with anomalies, winners, drop-offs, and one recommended action.` The success condition is not just login. The success condition is: - the setup agent can authenticate through browser approval and finish-code handoff - create the project - verify the first live event - the analyst can answer a real analytics question from the same issue flow ## Fast rollout order for Paperclip companies Use this order if you want the shortest path to first value: 1. create the CEO task 2. let that task cover the analyst and the engineer in one delegation path 3. review the blocked task when the working agent needs approval 4. sign in and reply with the finish code 5. let the working agent create the first project and verify the first event 6. ask the analyst one real traffic or signup question 7. add the recurring 8:00 AM analyst brief once the first traffic question works ## Compatibility API keys If you need direct HTTP access for a custom server-side runtime later, you can still generate a raw API key from [app.agentanalytics.sh](https://app.agentanalytics.sh). Keep that outside the normal Paperclip setup and upgrade path. For the normal Paperclip setup path, prefer browser approval plus finish code handoff. ## When to use a different page - Use [Getting Started](/getting-started/) if you want the shortest overview for the whole product. - Use [Installation](/installation/) if you need the raw per-environment install pages outside the Paperclip company flow. - Use [First Project in 5 Minutes](/guides/first-project-in-5-minutes/) if the engineer already has access and you want the clearest install-to-live walkthrough. - Use [Tracker.js](/reference/tracker-js/) if you need browser-side details such as SPA tracking, declarative events, consent, errors, or web vitals. - Use [CLI vs MCP vs API](/reference/cli-mcp-api/) if your team is deciding between access paths. ## Related - [If You Use Paperclip, You Need End-User Analytics](https://blog.agentanalytics.sh/blog/paperclip-companies-need-agent-readable-analytics/) - [Paperclip Live Plugin](/reference/paperclip-live-plugin/) - [Getting Started](/getting-started/) - [First Project in 5 Minutes](/guides/first-project-in-5-minutes/) - [Tracker.js](/reference/tracker-js/) - [CLI vs MCP vs API](/reference/cli-mcp-api/) - [API Reference](/api/) ## Agent Analytics Skill URL: https://docs.agentanalytics.sh/guides/agent-analytics-skill/ Install the regular Agent Analytics skill and let your coding agent create projects, add tracking, query analytics, and run experiments from the same workflow. Use the regular Agent Analytics skill when you want your AI agent to operate Agent Analytics end-to-end from the product codebase it is already editing. The skill starts from the [Projects, Surfaces, and Portfolios](/guides/projects-surfaces-portfolios/) model. Before setup, analytics reads, or instrumentation recommendations, the agent should classify whether the target is project-local work, a surface inside a project, or related-project portfolio work. It is the right first skill for setup, tracking, reporting, funnels, session paths, and normal experiment work. Use [Closed-loop growth analysis](/guides/closed-loop-growth-analysis/) as the normal full-loop analysis recipe when you want the agent to diagnose activation drop-off, choose one narrow experiment or readiness fix, and read the result later. If you want the agent to generate and judge growth variants before an A/B test, use the [Autoresearch Growth Skill](/guides/autoresearch-growth-skill/) after the basic analytics loop works. ## Install Install from the public skill repo: ```bash npx skills add agent-analytics/skills ``` If the installer asks which skill to install, choose `agent-analytics`. You can also install it explicitly: ```bash npx skills add agent-analytics/skills --skill agent-analytics ``` The source is public: - [Agent Analytics skill repo](https://github.com/Agent-Analytics/skills) - [Agent Analytics](https://agentanalytics.sh) ## What To Ask Your Agent Start in the codebase or site you want to measure, then ask: ```text Set up Agent Analytics for this project. If browser approval is needed, open it and wait for me. I will sign in with Google or GitHub and approve it. Ask for a finish code only if the browser callback cannot resume you. Then create or identify the matching Agent Analytics project, ask me to confirm the initial product goal before storing durable context, install the project-owned tracker, add only meaningful custom events tied to this repo's product workflows and that goal, explain what each event enables, and verify the first useful event. ``` After setup, ask normal analytics questions in plain English: ```text How did this site perform in the last 7 days? ``` ```text Show the funnel from page_view to signup_cta_click to signup. ``` ```text Create an experiment for the signup CTA with control and a clearer variant, then show me how to QA both versions before it gets traffic. ``` ## Classify scope before setup or reads The canonical model is covered in [Projects, Surfaces, and Portfolios](/guides/projects-surfaces-portfolios/). The short version for agent workflows: - A project is the unit of local product learning: events, activation, retention, lifecycle, releases, experiments, and local goals belong here. - A project can include many surfaces, including app pages, docs, blog, pricing, signup/onboarding, mobile clients, subdomains, local previews, and deploy previews. - A portfolio is the cross-project growth system for related projects. Use it for related-project grouping and shared interpretation without collapsing project-local truth. - Cross-project identity is available only when configured within intentionally grouped portfolio projects. Do not imply automatic identity merging across every project in an account. Decision rules the skill teaches: - Subdomains are usually surfaces inside one project when they share the same product learning loop. - Mobile apps and free tools stay surfaces when they support the same product readout, but become separate projects when they have their own activation, retention, lifecycle, release cadence, experiments, acquisition loop, or local goals. - Localhost, staging, branch previews, and deploy previews are setup or QA surfaces for the intended project, not canonical project identities. - Separate products under one company should be separate projects under one portfolio when each needs its own local readout. - A domain mismatch is recoverable. The agent should clarify the intended project and surface instead of failing immediately. Command scope follows the model: use project commands for project-local work, `portfolios` commands for related-project grouping, and portfolio context only for shared goals, roles, and milestones across related projects. ## What The Skill Does The skill teaches the agent to use the official Agent Analytics CLI and API patterns without making you hand-write requests. Typical jobs: - classify the setup or read target as project-local work, a surface inside a project, or related-project portfolio work before taking action - infer goal and event candidates from the product code and workflow context - create or find the right project - install `tracker.js` - add only the first useful declarative events such as CTA clicks - verify the first useful recommended event - inspect pages, events, funnels, retention, and bot traffic - store compact project goals, activation events, and event-name glossary context so later analytics reads include the product meaning - store date annotations for major landing page, pricing, onboarding, feature, release, or experiment changes - store account-level portfolio context for shared goals, surface roles, and milestones across multiple related sites or projects - create, QA, measure, and complete experiments - explain gaps in the data before recommending action Browser approval is the normal login path. Setup, paid upgrade, and resumed agent work do not require an API key. When a product has its own activation definition, human vocabulary, or major shipped changes, ask the agent to keep project context updated. The skill tells the agent to check `properties` or `properties-received` first, then use `context set` with short entries tied to real event names through `event_name`. It can also add date annotations with `occurred_at`, `title`, and optional `note` when the user changes pricing, ships a feature, updates onboarding, changes a landing page, starts an experiment, or makes another meaningful product change. That context is returned as `project_context` on project-scoped analytics results, so future reads can explain metrics in the product's own language without carrying a long prompt. Annotations are intentionally not a git changelog. Keep them sparse, do not store PII or secrets, and use them only for changes that could explain graph movement later. When many related projects or surfaces work together, also ask the agent to maintain portfolio context. Portfolio context is account-level memory for shared goals, surface roles, and cross-project milestones such as `qualified_click_to_product`, `signup`, or `first_recommended_event_verified`. Use project context for project-local truth and portfolio context for the shared growth system across a landing page, docs site, directory, product app, or ecosystem surfaces. For OpenClaw and similar managed runtimes, tell the agent to keep Agent Analytics CLI auth in a persistent workspace path instead of the default home config path: ```bash export AGENT_ANALYTICS_CONFIG_DIR="$PWD/.openclaw/agent-analytics" npx --yes @agent-analytics/cli@0.5.34 auth status ``` If the runtime may not preserve exported variables between commands, prefix each Agent Analytics CLI command with that same `AGENT_ANALYTICS_CONFIG_DIR=...` value or pass `--config-dir "$PWD/.openclaw/agent-analytics"`. Do not commit `.openclaw/agent-analytics/config.json`. ## When To Use The Autoresearch Skill Instead Use [Autoresearch Growth Skill](/guides/autoresearch-growth-skill/) when the task is not just "read analytics" or "create an experiment," but: - generate landing-page, onboarding, pricing, or CTA variants - critique generic copy and product-truth drift - blind-rank multiple candidates - output two review-ready experiment variants - rerun the loop after experiment data comes back In practice, the regular skill gets the analytics foundation working. The autoresearch skill uses that foundation to run a structured growth loop. ## Related - [Closed-loop growth analysis](/guides/closed-loop-growth-analysis/) - [Autoresearch Growth Skill](/guides/autoresearch-growth-skill/) - [First Project in 5 Minutes](/guides/first-project-in-5-minutes/) - [AI Agent Experiment Tracking](/guides/ai-agent-experiment-tracking/) - [Session Paths](/guides/session-paths/) - [CLI](/reference/cli/) - [Skill vs MCP vs API](/reference/cli-mcp-api/) ## Projects, Surfaces, and Portfolios URL: https://docs.agentanalytics.sh/guides/projects-surfaces-portfolios/ Learn the Agent Analytics product-system model: portfolios connect related projects, projects own product learning, and surfaces are the places users encounter each project. Agent Analytics uses one hierarchy for product-system understanding: **Portfolio β†’ Projects β†’ Surfaces** Start with this model before you choose an install path, create extra projects, or ask an agent to read analytics across a company account. ![Portfolio connects separate projects, and each project contains its own surfaces.](/images/projects-surfaces-portfolios-diagram.png) ## The model ### Portfolio A **portfolio** is the broader product or company growth system. It connects related projects so your agent can reason about shared milestones, project roles, surface roles, shared goals, and cross-project identity **when configured** within intentionally grouped portfolio projects. A portfolio does not collapse everything into one analytics blob. Each project still keeps its own local truth: activation, retention, lifecycle, releases, experiments, and goals remain project-local; portfolio-level questions compare or relate that local truth instead of replacing it. ### Project A **project** is the unit of product learning. It owns the events, activation goal, retention behavior, lifecycle, releases, experiments, and local readouts for one product or product loop. Create a separate project when something has its own learning loop or needs its own activation, retention, lifecycle, release, experiment, or local-goal readout. ### Surface A **surface** is a place where users encounter or use a project. Surfaces live inside projects. A project can have many surfaces, such as: - app pages - marketing pages - docs - blog or content pages - pricing pages - signup and onboarding flows - local preview URLs - preview deployments - mobile clients - launch pages - subdomains Do not create a separate project just because a product has multiple surfaces. Keep surfaces together when they serve the same product learning loop. ![App, docs, pricing, mobile, localhost, and preview URLs shown as surfaces inside one project.](/images/projects-surfaces-guide-surfaces.png) ### Domain, subdomain, and URL A **domain**, **subdomain**, localhost address, preview deployment, or URL is an address for a surface. It is not the product model by itself. For example, `app.example.com`, `docs.example.com`, `www.example.com/pricing`, a mobile deep link, and `localhost:3000` can all point at surfaces. The question is not β€œwhich domain is this?” The question is β€œwhich project does this surface belong to?” ## Generic SaaS portfolio example Imagine one company with a SaaS product and three related growth properties. In Agent Analytics, that can be modeled as one portfolio with several projects inside it: | Portfolio | Project | Example surfaces | Why it is a project | | --- | --- | --- | --- | | ExampleCo growth portfolio | Main SaaS | App, marketing site, docs, pricing, onboarding, local preview | It owns the core product activation, retention, releases, and experiments. | | ExampleCo growth portfolio | Free ROI calculator | Calculator page, results page, lead capture, embed, preview URL | It has its own acquisition loop, completion goal, lead handoff, and experiment readout. | | ExampleCo growth portfolio | Newsletter/content site | Articles, archive, signup page, referral page, product handoff pages | It has its own content growth loop and local goals. Native email-service-provider opens/clicks are not assumed unless you explicitly send those events. | | ExampleCo growth portfolio | Mobile companion | iOS app, Android app, app landing page, deep links, beta preview | It may have its own lifecycle, release cadence, retention behavior, and product readout. | The portfolio connects these projects because they are part of one product-system story. The projects remain separate because each has its own learning loop. ## Default: subdomains are usually surfaces Do not split a product into separate projects just because it uses multiple subdomains. Subdomains are deployment and routing details first. They should remain surfaces inside one project by default when they support the same product learning loop. For example, keep these as surfaces of the same Main SaaS project when they share the SaaS activation, retention, lifecycle, releases, experiments, and readout: - `app.example.com` for the product app - `docs.example.com` for product education and activation support - `blog.example.com` for content that feeds the same product funnel - `www.example.com` or `marketing.example.com` for marketing, pricing, signup, and onboarding The question is not β€œdoes this have its own subdomain?” The question is β€œdoes this need its own product-learning container?” ## When something is a surface instead of a project Keep something as a surface inside an existing project when it serves the same product learning loop and should be read with that project’s local truth. Common examples: - App, docs, blog, marketing, pricing, signup, and onboarding subdomains that all support the same SaaS activation and conversion loop. - A small calculator, checklist, or feature page on the main marketing site that feeds the same signup funnel and does not need its own local readout. - A mobile app that is simply another client for the same product, with the same activation and retention definitions as the web app. - A newsletter signup page, article archive, referral page, or product handoff surface that is part of the same product funnel. - A localhost URL or preview deployment used only to set up, test, or QA tracking for the intended project. Surfaces can be permanent, temporary, public, private, web, mobile, or local. They still live inside projects. ## When a surface should become a separate project Create a separate project when the work needs its own product-learning container. Good signals include: - a distinct activation goal - a distinct retention pattern - its own lifecycle - its own release cadence - separate experiments or readouts - a local goal that should not be averaged into the main product - a separate acquisition loop, such as a free tool or newsletter/content site - a mobile companion that behaves like a product, not just a client surface If one or more of those signals materially changes how the team should read the product, promote the surface to its own project and connect it to related projects through a portfolio when the broader product system should be understood together. ![A highlighted surface is promoted into a separate project, with both projects connected by a portfolio.](/images/projects-surfaces-guide-promote.png) ## Edge-case classification examples ### Mobile app: surface or project Treat a mobile app as a surface when it is another way to use the same product and shares the same activation, retention, lifecycle, and product readout as the web app. For example, an iOS client and Android client can be surfaces of the Main SaaS project when they are client entry points for the same account workflow. Treat a mobile app as its own project when it has its own activation, retention behavior, lifecycle, release cadence, experiments, or local goals. A mobile companion with app-specific onboarding, push-notification retention, beta cohorts, store releases, and mobile-specific readouts should usually be its own project inside the portfolio. ### Free tool: surface or project Treat a free tool as a surface when it is a small part of the main product funnel. A calculator section on a pricing page can stay inside the Main SaaS project when the only goal is to help users continue to signup. Treat a free tool as its own project when the team needs to measure the tool as a product loop: tool starts, completions, result views, lead captures, embeds, referrals, handoffs to the paid product, and tool-specific experiments. In that case, connect the Free Tool project to the Main SaaS project through a portfolio instead of merging their local goals. ### Newsletter/content site: surface or project Treat newsletter/content pages as surfaces when they support the same product loop: a newsletter signup page, article archive, referral page, or product handoff surface can live inside the Main SaaS project when the readout is the main product funnel. Treat a newsletter/content site as its own project when it has its own content growth loop, acquisition goals, referral mechanics, publication cadence, experiments, or local readout. Track the web and event surfaces you instrument, such as signup pages, archive pages, referral pages, and product handoff pages. Agent Analytics does not automatically track native email-service-provider opens or clicks unless you explicitly send those events. ### Localhost and preview deployments Treat `localhost`, local network addresses, branch previews, staging links, and deploy-preview URLs as setup or testing surfaces. They help you install, verify, and QA tracking for the intended project, but they are not canonical project identities. Do not create a new canonical project for every preview URL. If a preview URL is ambiguous, ask which project and surface it is testing, then map the setup work back to that project. ## How portfolios should be used Use a portfolio when related projects need to be understood together without losing project-local truth. In the CLI/API reference, identity portfolios define the membership and lookup boundary, and portfolio context stores interpretation notes. This guide uses portfolio as the product-system model those features support. A portfolio can help your agent answer questions like: - Which project is driving the best handoff into the main SaaS product? - Did a shared launch milestone affect multiple projects? - Which surface roles belong to acquisition, activation, education, or retention? - How do intentionally grouped projects relate when cross-project identity is configured? Portfolio-level reasoning should stay intentional. Agent Analytics should not imply that identity automatically merges across every project in an account. Cross-project identity is a portfolio capability only **when configured** and only within the projects you intentionally group together. ## Quick classification checklist Before setup or analytics reads, the user or agent should classify the target in this order: 1. **Name the broader system.** Is this one product, or a company growth system with related projects that should be connected by a portfolio? 2. **Find the project-local learning loop.** Which product owns the activation, retention, lifecycle, releases, experiments, and local goals? 3. **Check whether the target is only a surface.** Is it an app, docs, blog, marketing page, mobile client, free-tool page, newsletter signup page, archive, referral page, product handoff surface, localhost URL, preview deployment, or subdomain that supports that same project? 4. **Promote only when needed.** Does it have its own activation, retention, lifecycle, release cadence, local goal, acquisition loop, experiment plan, or readout? If yes, make it a separate project. 5. **Connect related projects intentionally.** If separate projects belong to one company or product-system story, put them in a portfolio. Do not use the portfolio to overwrite each project’s local truth. 6. **Handle identity carefully.** Cross-project identity is available only within intentionally grouped portfolio projects **when configured**. Do not assume automatic identity merging across every project in an account. 7. **Map URLs last.** Which domain, subdomain, path, mobile deep link, local address, or deployment URL currently points to the surface? If a URL is ambiguous, ask which project and surface it belongs to. Do not treat the raw domain as the project identity, and do not fail just because a URL is local, temporary, or different from the primary setup URL. ## Related guides - [Getting Started](/getting-started/) - [First Project in 5 Minutes](/guides/first-project-in-5-minutes/) - [Examples](/guides/examples/) - [Session Paths](/guides/session-paths/) ## Autoresearch Growth Skill URL: https://docs.agentanalytics.sh/guides/autoresearch-growth-skill/ Use the Agent Analytics Autoresearch skill to run a loop on top of the loop: generate variants, judge them, ship approved experiments, measure real behavior, and feed the next run. Use the Autoresearch Growth skill when you want your coding agent to turn analytics data into review-ready growth experiments. The inner loop generates, critiques, synthesizes, and blind-ranks candidates. The outer loop waits for real behavior, pulls the experiment data back into the next brief, and runs again from evidence. This skill is based on [Andrei Karpathy's `autoresearch`](https://github.com/karpathy/autoresearch) pattern: keep the loop simple, let an external coding agent read the markdown instructions, write artifacts to disk, and iterate. Agent Analytics adapts that pattern for growth work in the public template repo: - [Agent Analytics Autoresearch Growth](https://github.com/Agent-Analytics/autoresearch-growth) - [Agent Analytics](https://agentanalytics.sh) The important change is the outer evidence loop. Karpathy's original loop is useful for generating and judging ideas. The growth version uses measured experiment behavior to seed the next run, so the loop does not stop at what LLM judges think sounds good. ## Install Install from the public skill repo: ```bash npx skills add agent-analytics/skills ``` If the installer asks which skill to install, choose `agent-analytics-autoresearch`. You can also install it explicitly: ```bash npx skills add agent-analytics/skills --skill agent-analytics-autoresearch ``` The regular `agent-analytics` skill can be installed from the same repo. Use it first when the site still needs project setup, tracking, or basic experiment wiring. ## What The Skill Needs The skill works with any analytics source, but works best with Agent Analytics because the agent can collect the evidence itself. Give the agent: - the target surface, such as homepage hero, pricing page, onboarding step, or signup CTA - the current control copy or screenshot - the product truth that must not drift - the audience - one primary event, such as `signup`, `checkout`, or `activation_completed` - one proxy event, such as `cta_click` - guardrails, such as bounce, scroll depth, time on page, errors, performance, source quality, or signup quality - recent analytics data or permission to fetch it The skill can also run on demo data from the template repo, so you can try the workflow before connecting an account. ## Run The Inner Loop Start with a review-only run: ```text Run the autoresearch growth loop for this landing page. Use signup as the primary event and cta_click as the proxy. Fetch the latest analytics data if you can; otherwise use the data I provide. Keep product truth intact, run 5 rounds, and produce two distinct variants for review. Do not wire the experiment yet. ``` The skill should create or update the normal run artifacts: - `brief.md` - `results.tsv` - `final_variants.md` - a dated data snapshot when live data is available `results.tsv` is the round log. The final decision artifact is `final_variants.md`. ## Run The Outer Loop Only move into production after human approval. Once you approve a variant, ask: ```text Implement the approved variants on the landing page, create an experiment with control plus the two candidates, verify signup and cta_click tracking, and show me the QA links before launch. ``` After the experiment has collected behavior, ask: ```text Pull the experiment results and guardrails into a new snapshot. Summarize what won, what lost, what is still too sparse to trust, and run the next autoresearch loop from that evidence. ``` That is the loop on top of the loop: 1. run several LLM judging rounds 2. pick two variants for human review 3. ship an approved experiment 4. wait for real behavior 5. collect the measured result 6. feed the next autoresearch run LLM judges are useful for pressure-testing options. They are not the final judge. User behavior is the final judge. ## Try It With Sample Data Clone or open the public template repo: ```bash git clone https://github.com/Agent-Analytics/autoresearch-growth.git cd autoresearch-growth ``` Then ask your agent: ```text Use the demo SaaS data in examples/demo-saas. Run the autoresearch growth loop and show me final_variants.md so I can judge the two winners. ``` No Agent Analytics account is required for the demo data. ## Related - [Agent Analytics Skill](/guides/agent-analytics-skill/) - [AI Agent Experiment Tracking](/guides/ai-agent-experiment-tracking/) - [Session Paths](/guides/session-paths/) - [CLI](/reference/cli/) - [Karpathy autoresearch](https://github.com/karpathy/autoresearch) - [Autoresearch Growth repo](https://github.com/Agent-Analytics/autoresearch-growth) - [Autoresearch Growth Loops Need Reality Checks](https://blog.agentanalytics.sh/blog/autoresearch-growth-loop-agent-analytics/) ## Examples URL: https://docs.agentanalytics.sh/guides/examples/ Browse working Agent Analytics example projects with real integration code, tests, and README notes you can copy into your own product. The [Agent Analytics examples repository](https://github.com/Agent-Analytics/agent-analytics-examples) contains working product surfaces that show how to integrate Agent Analytics without inventing fake product flows. Use it when you want to see the tracker in a real codebase instead of reading another isolated snippet. ## What the examples repo is for Each example is meant to answer three practical questions: 1. Where does the tracker snippet live in this framework? 2. Which events should be tracked for the product flow that actually exists? 3. Which tracker features should be omitted because the product does not honestly have that flow? That third point matters. A good example should not fire `purchase`, `checkout`, `signup`, or `identify` events unless the product really has purchase, checkout, account, or authentication behavior. ## Current examples | Example | Stack | Product surface | Primary conversion | What it demonstrates | | --- | --- | --- | --- | --- | | [Astro Velvet Paw](https://github.com/Agent-Analytics/agent-analytics-examples/tree/main/examples/astro-velvet-paw) | Astro | Ecommerce-style affiliate storefront | Outbound merchant click | Tracker snippet placement, automatic traffic/session fields, declarative CTA events, section impressions, runtime `window.aa.track(...)` events, client-side experiment assignment, outbound merchant attribution, and tests that prevent fake checkout/cart/purchase tracking. | ## Start from Astro Velvet Paw Astro Velvet Paw is a simple storefront for a fictional premium cat-sneaker brand. It looks and behaves like a normal ecommerce/affiliate page: product cards, prices, ratings, size guidance, add-ons, recommendations, support content, and merchant handoff links. The README in the example explains exactly what was plugged in: - tracker snippet location and configuration - automatic signals the tracker collects without extra custom events - declarative click tracking with `data-aa-event` - section exposure tracking with `data-aa-impression` - runtime events for state that only exists in the browser - client-side experiment exposure - outbound merchant-click conversion tracking - events and flows intentionally omitted - tests that lock the integration behavior Open it here: - [Repository: Agent-Analytics/agent-analytics-examples](https://github.com/Agent-Analytics/agent-analytics-examples) - [Example: examples/astro-velvet-paw](https://github.com/Agent-Analytics/agent-analytics-examples/tree/main/examples/astro-velvet-paw) ## Ask your agent to use the example If your agent can read GitHub repositories, give it this prompt: ```text Use the Agent Analytics examples repo as a reference: https://github.com/Agent-Analytics/agent-analytics-examples Start with examples/astro-velvet-paw. Show me where the tracker snippet, data-aa-event attributes, data-aa-impression sections, runtime window.aa.track calls, and tests live. Then adapt the same pattern to my product without adding fake checkout, purchase, signup, or identify events. ``` ## Related - [Tracker.js](/reference/tracker-js/) - [First Project in 5 Minutes](/guides/first-project-in-5-minutes/) - [AI Agent Experiment Tracking](/guides/ai-agent-experiment-tracking/) - [SPA and Virtual Page Tracking](/guides/spa-and-virtual-page-tracking/) ## First Project in 5 Minutes URL: https://docs.agentanalytics.sh/guides/first-project-in-5-minutes/ Go from installed agent to a live Agent Analytics project with the tracker placed, the first page view verified, one useful event planned, and one real analytics question answered. Use this guide when your AI agent install is already done and you want the clearest path to your first real success loop. If you still need to connect your AI agent first, go back to the [installation hub](/installation/) or the short [Getting Started](/getting-started/) overview. ## 1. Confirm your AI agent install is already working Ask your AI agent: ```text List my Agent Analytics projects and confirm you can reach my account. Open the browser for me or send me the login link, then wait for me. ``` When the browser approval page opens, sign in with Google or GitHub, approve it, and let the agent continue. If the agent still cannot see your account after that, stop here and finish the right [installation path](/installation/). ## 2. Create the first project and get the tracker snippet Ask your AI agent: ```text Create a project called my-site.com and give me the tracking snippet. ``` At this point you want one of two outcomes: - the agent creates the project and returns the tracker snippet for you to paste - the agent creates the project and can place the snippet itself ## 3. Choose the path that matches your setup ### Agent can edit code If your AI agent can change your site, ask it: ```text Create a project called my-site.com, add the Agent Analytics tracking snippet to the site, and tell me exactly which file you changed. ``` Then ask: ```text Show me where you placed the snippet and confirm it will load on the page I want to track first. ``` If your site uses Astro, tell the agent to add `is:inline` to the tracker ` ``` Required attributes: - `data-project`: your project name - `data-token`: the public project token (`aat_*`) The tracker automatically sends an initial `page_view` with a sanitized URL and referrer, pathname, hostname, title, screen size, browser, OS, device, language, timezone, session count, days since first visit, and allowlisted UTM attribution. No cookies are required. ## Privacy contract Agent Analytics separates the default browser contract from explicit opt-ins: | Area | Default behavior | Explicit opt-ins | | --- | --- | --- | | Page views | One initial `page_view` is sent on load. `url` and `referrer` are sanitized to `origin + pathname`; query strings and fragments are not sent by the automatic URL fields. `path` is the current pathname. | SPA route listeners require `data-track-spa="true"`. Manual virtual pages can be sent with `aa.page(name)` or `aa.track('page_view', ...)`. | | Attribution | Only `utm_source`, `utm_medium`, `utm_campaign`, `utm_content`, and `utm_term` are read from the query string. They are kept for the current session and first touch. Other query parameters are not collected automatically. | Add custom campaign fields yourself with `aa.track(...)` only when they are safe and intentional. | | Browser fields | Browser family/version, OS, coarse device type, language, timezone, hostname, title, and screen size are included. The tracker does not use hard fingerprinting, dynamic script loading, `eval`, `document.write`, or form value collection. | Performance, Web Vitals, errors, scroll depth, 404s, downloads, form-submit metadata, outgoing links, and generic clicks are off until their `data-track-*` attributes are set. | | Clicks and forms | Declarative `data-aa-event` clicks only send the event name and explicit `data-aa-event-*` attributes you add. | `data-track-clicks="true"` tracks link/button metadata but not visible click text. `data-track-forms="true"` tracks form metadata but not form values. | | Identity | Anonymous IDs and session IDs are scoped to the project token/name in browser storage. Legacy unscoped keys are not migrated, so a new scoped anonymous ID may be created after upgrading. | `aa.identify(userId, traits)` is explicit-only. Use a stable app/account ID as `userId`; pass email only as top-level `traits.email` when you want server-side support lookup. | | Email lookup | Email is not collected automatically and should not be used as the `userId`. | When `traits.email` is provided to `identify`, raw email is transmitted over HTTPS for that identify call so the server can compute a project-scoped HMAC lookup index. Raw email is stripped from event rows and profile traits by default. | | Cross-domain identity | No link decoration occurs by default. | `data-link-domains` decorates allowed cross-domain links with a short `_aa` anonymous ID parameter and then removes it on the destination. | | Consent and DNT | Tracking starts immediately unless you configure consent or DNT. | `data-require-consent="true"` buffers until `aa.grantConsent()`. `data-do-not-track="true"` respects the browser DNT signal. | Automated traffic that reaches the tracker is filtered out of your normal analytics. Use [Bot Traffic](/reference/bot-traffic/) if you want to inspect those automated requests separately. If your agent can edit code, ask it to add the snippet for you. If not, use [First Project in 5 Minutes](/guides/first-project-in-5-minutes/) to create the project, get the snippet, and verify the first page view. If you want to see these pieces in a working repository, start with the [examples guide](/guides/examples/) and the [Agent Analytics examples repo](https://github.com/Agent-Analytics/agent-analytics-examples). Website analysis recommendations assume these automatic fields already exist. A good `implementation_hint` should use the smallest tracker capability that unlocks the decision: declarative attributes for simple intent, `window.aa.track(...)` for computed client state, and server-side tracking for durable outcomes like account creation. ## Common options | Attribute | What it does | | --- | --- | | `data-link-domains="example.com"` | Link anonymous identity across sibling domains or subdomains | | `data-do-not-track="true"` | Respect the browser Do Not Track signal | | `data-heartbeat="15"` | Measure active time on page while the tab is visible | | `data-track-outgoing="true"` | Track external link clicks as `outgoing_link` | | `data-track-clicks="true"` | Track `` and ` ``` That fires a `signup_cta_clicked` event with `{ plan: "pro" }`. This is usually the easiest path for agents too. They can add attributes to existing markup instead of wiring `onclick` handlers or editing application code. Reserve `signup` for the durable moment when an account is actually created. If a button only starts the flow, use an intermediate event like `signup_started` or `signup_cta_clicked` instead of treating the click itself as the completed signup. ## Impressions Track whether a section was actually seen: ```html
...
``` When the element becomes visible, the tracker sends an `$impression` event. ## `window.aa` API Use the JavaScript API when the event depends on runtime state: ```js window.aa?.track('checkout_started', { plan: 'pro' }); window.aa?.identify('user_123', { email: 'alice@example.com', plan: 'pro' }); window.aa?.set({ plan: 'pro', team: 'acme' }); ``` Useful methods: - `aa.track(event, properties)`: send a custom event - `aa.page(name)`: manually send a page view - `aa.identify(id, traits)`: link anonymous behavior to a stable known user ID and update the private profile lookup index used for support journeys - `aa.set(properties)`: attach global properties to future events - `aa.experiment(name, variants)`: assign variants deterministically client-side - `aa.grantConsent()` / `aa.revokeConsent()`: manage consent mode ## Authenticated apps: `signup`, `login`, and `identify` For apps with accounts, the cleanest post-auth browser step is: ```js window.aa?.identify(account.id, { email: account.email, plan: account.plan, team: account.team, }); ``` Call `aa.identify(account.id, traits)` immediately after auth succeeds and before any other post-auth browser events. That stitches the current browser activity onto the same canonical user ID that your server should use. Use a stable app/user/account ID as the first argument, not an email address. Pass email only as top-level `traits.email` when you want later support lookup by email. When `traits.email` is present, raw email is transmitted over HTTPS during identify so Agent Analytics can compute a project-scoped HMAC lookup index on the server. Raw email is stripped from event rows and profile traits by default; browser-side SHA-256 email hashing and `email_hash` payloads are no longer part of the public tracker contract. Recommended event boundaries: - Fire `signup` exactly once when the account is created. Prefer the server-side account-creation path for this. - Fire `login` when an existing account finishes auth. Prefer the server-side auth callback or session-creation path for this too. - Use client-side events like `signup_started`, `signup_cta_clicked`, or `checkout_started` for earlier UI steps that happen before the account exists. That separation keeps funnels honest and makes browser events and server auth events land on the same `user_id`. ## SPA routing and virtual pages By default, Agent Analytics sends the initial page view only. Automatic SPA route tracking is now explicit opt-in because it listens for URL changes and patches `history.pushState()` / `history.replaceState()`. To enable automatic route-change page views, add `data-track-spa="true"`: ```html ``` With that opt-in, Agent Analytics tracks `page_view` when the browser URL changes through `history.pushState()`, `history.replaceState()`, `popstate`, or `hashchange`. That covers most client-side routers, including hash-based SPAs. If your UI changes without changing the path, query string, or hash, the tracker does not try to guess that a new screen appeared. In that case, send a manual `page_view`. Preferred implementation order: 1. Real URL changes 2. Hash routing 3. Manual virtual `page_view` Use `aa.page(name)` when the current browser URL already matches the screen you want to label. It sends a `page_view` with a `page` property, but `path` and `url` still come from the current browser location. For true virtual pages with no URL change, send a manual `page_view` and override the route fields yourself: ```js window.aa?.track('page_view', { page: 'Checkout Step 2', path: '/checkout/step-2', url: `${location.origin}/checkout/step-2` }); ``` Do not combine manual page tracking with router-driven transitions after you enable `data-track-spa="true"`, or you will double-count the same screen change. If you want a prompt-first workflow for deciding between router tracking and manual virtual pages, use [SPA and Virtual Page Tracking](/guides/spa-and-virtual-page-tracking/). ## Common recipes ### Cross-domain identity Use `data-link-domains` when one visitor can move between related domains and should keep the same anonymous browser identity across that click. ```html ``` On click, the tracker decorates links to those domains with a short `_aa` query parameter. The destination tracker captures that anonymous ID, links it to the destination browser's anonymous ID, and removes `_aa` from the address bar. For projects that use the same project token, `data-link-domains` is enough. For separate Agent Analytics projects, add the projects to the same identity portfolio; otherwise the link is decorated, but cross-project reads stay project-local. See [Identity portfolios](/reference/cli/#identity-portfolios) for the CLI setup. Typical portfolio flow: ```text discovery.example.com -> example.com -> app.example.com ``` Example with separate projects in one portfolio: ```bash agent-analytics portfolios create growth-system \ --name "Growth system" \ --projects example.com,discovery.example.com ``` Then include the same portfolio domains on each participating surface: ```html ``` Verify the destination project after a real click: ```bash agent-analytics query example.com \ --metrics event_count,unique_users \ --filter '[{"field":"properties.referrer","op":"contains","value":"discovery.example.com"}]' \ --days 1 ``` Expected result: the destination events from that browser resolve to one `unique_users` value instead of fragmenting across the source and destination projects. ### Privacy and consent ```html ``` ```js window.aa?.grantConsent(); window.aa?.revokeConsent(); ``` When consent is granted, buffered events are flushed automatically. If the buffer contains more than 100 events, the tracker splits it into multiple `/track/batch` requests of 100 events or fewer. ### Experiments ```html

Start your free trial

``` If you want the full prompt-first workflow for creating, wiring, QAing, and reading an experiment through your agent, use [AI Agent Experiment Tracking](/guides/ai-agent-experiment-tracking/). ### Local development On localhost, the tracker switches to dev mode and logs activity to the browser console instead of sending production data. That keeps local testing out of your real analytics. ## Related - [Getting Started](/getting-started/) - [First Project in 5 Minutes](/guides/first-project-in-5-minutes/) - [Examples](/guides/examples/) - [SPA and Virtual Page Tracking](/guides/spa-and-virtual-page-tracking/) - [AI Agent Experiment Tracking](/guides/ai-agent-experiment-tracking/) - [Bot Traffic](/reference/bot-traffic/) - [Authentication](/reference/authentication/) - [API Reference](/api/) ## Bot Traffic URL: https://docs.agentanalytics.sh/reference/bot-traffic/ See which automated callers hit your tracker, how many events were filtered, and which actors generated that traffic. Bot Traffic shows automated requests that reached Agent Analytics and were filtered out of your normal analytics. Use it when you want to answer questions like: - Did ChatGPT or another agent actually hit this site? - Are search crawlers or preview bots touching the tracker? - How many analytics events were dropped because they came from automation? ## Important scope This feature is intentionally narrower than CDN or reverse-proxy logs. - It is **not** full site traffic visibility like Cloudflare. - It only includes automated requests that reached `POST /track` or `POST /track/batch`. - It stores daily aggregates, not raw request logs. - It does **not** store IPs. - It does **not** add bot hits to your normal event analytics, sessions, or billing. ## What you get back Project and account views return: - `automated_requests`: how many filtered tracking requests were received - `dropped_events`: how many analytics events were discarded inside those requests - `categories`: grouped buckets like `ai_agent`, `search_crawler`, `social_preview`, `monitoring_perf` - `actors`: normalized sources like `ChatGPT-User`, `Googlebot`, `ClaudeBot`, `curl` - `time_series`: zero-filled daily rollup for the selected period ## Access paths ### CLI ```bash npx --yes @agent-analytics/cli@0.5.34 bot-traffic my-site --period 7d --limit 5 npx --yes @agent-analytics/cli@0.5.34 bot-traffic --all --period 7d --limit 10 ``` ### MCP Use: - `bot_traffic_overview` for one project - `all_sites_bot_traffic` for account scope ### API ```bash curl "https://api.agentanalytics.sh/bot-traffic?project=my-site&period=7d&limit=5" \ -H "X-API-Key: aak_..." ``` ```bash curl "https://api.agentanalytics.sh/account/bot-traffic?period=7d&limit=10" \ -H "X-API-Key: aak_..." ``` ## Project vs account scope Use project scope when you want top actors and category breakdown for one site. Use account scope when you want: - total filtered automation across all active projects - which projects are seeing that traffic - a lightweight all-sites overview instead of per-project details Deleted projects are excluded from account rankings and totals. ## Availability Bot traffic overview is available on both hosted free and pro plans through API, CLI, and MCP. ## Related - [Tracker.js](/reference/tracker-js/) - [CLI vs MCP vs API](/reference/cli-mcp-api/) - [Rate Limits](/reference/rate-limits/) - [API Reference](/api/) ## Authentication URL: https://docs.agentanalytics.sh/reference/authentication/ Understand the difference between agent sessions, API keys, and project tokens before you wire an agent or a tracker. Agent Analytics uses three different credentials. They serve different jobs and should not be swapped. ## Agent session (`aas_*`) Use the agent session for: - official CLI login through browser approval - skill flows that authenticate through the hosted approval flow - agent-native setup where the agent should keep the connection after approval In the normal product flow, you do not paste this token around manually. The hosted approval flow creates it for the agent or CLI and stores it locally for later use. ## Managing active agent sessions If you want to inspect or revoke agent-owned logins later, open [app.agentanalytics.sh](https://app.agentanalytics.sh) and go to `Account Settings` β†’ `Agent Sessions`. That page shows active hosted agent sessions such as: - CLI logins - macOS Live app connections - Paperclip connections - MCP or other hosted agent-session clients Use `Disconnect` there when you want to revoke one specific session on the server. ## API key (`aak_*`) Use the API key for: - reading analytics data - creating or listing projects - account-level endpoints - direct API access from server-side scripts and tools that cannot use agent sessions Pass it with the `X-API-Key` header or the `?key=` query parameter. ```bash curl "https://api.agentanalytics.sh/stats?project=my-site&since=7d" \ -H "X-API-Key: aak_..." ``` Treat it as secret material. ## Project token (`aat_*`) Use the project token for: - `POST /track` - `POST /track/batch` - the browser tracker snippet embedded on your site The token is public by design. It identifies the project for event ingestion and is expected to appear in HTML. ```html ``` ## Common mistake Do not put the API key in the client-side tracker. The tracker uses the public project token only. ## auth.md agent authentication Agent Analytics also publishes auth.md discovery metadata so compatible agents can discover the API auth flow from a 401 response instead of asking for a copy-pasted API key. Live discovery endpoints: - [`https://api.agentanalytics.sh/auth.md`](https://api.agentanalytics.sh/auth.md) - [`https://api.agentanalytics.sh/.well-known/oauth-protected-resource`](https://api.agentanalytics.sh/.well-known/oauth-protected-resource) - [`https://api.agentanalytics.sh/.well-known/oauth-authorization-server`](https://api.agentanalytics.sh/.well-known/oauth-authorization-server) Compatible agents should use the user-claimed browser approval flow. Agent Analytics issues scoped `aas_*` sessions after human approval; it does not issue raw account API keys to agents. For details, see [auth.md agent authentication](/reference/auth-md/). ## CLI auth helpers If you use the official CLI, it provides browser-approved local auth helpers: - `npx --yes @agent-analytics/cli@0.5.34 login` starts browser approval and saves a local CLI session. - `npx --yes @agent-analytics/cli@0.5.34 login --detached` starts the same flow for headless or issue-based runtimes where the agent sends you an approval link and may ask for a finish code. - `npx --yes @agent-analytics/cli@0.5.34 auth status` shows whether local CLI auth exists, where config is stored, and which credential store is active without printing token values. - `npx --yes @agent-analytics/cli@0.5.34 upgrade-link --detached` prints a human-owned Pro payment handoff when a free account hits a paid-only analytics task. - `npx --yes @agent-analytics/cli@0.5.34 logout` clears saved local CLI auth and revokes the stored agent session when possible. Use the web app's `Agent Sessions` section when you want to inspect active agent sessions or disconnect a specific session from the server without using that client. Scoped agent sessions cannot generate or rotate raw account API keys. Manage compatibility API keys from the dashboard. ## CLI credential storage Credential storage is automatic. Normal users do not need to set an environment variable. - macOS and Windows store CLI agent-session secrets in the OS keychain by default. - Linux and headless runtimes use config-file storage by default. - Existing file-stored sessions migrate to native keychain storage on the next authenticated command when native storage is available. - `AGENT_ANALYTICS_CREDENTIAL_STORE` is only an advanced troubleshooting override. Supported values are `auto`, `native`, and `file`. ## Related - [Getting Started](/getting-started/) - [CLI vs MCP vs API](/reference/cli-mcp-api/) - [Error Format](/reference/error-format/) - [API Reference](/api/) ## Skill vs MCP vs API URL: https://docs.agentanalytics.sh/reference/cli-mcp-api/ Agent Analytics exposes one analytics surface through skill, MCP, CLI, and raw HTTP. Use this page to choose the native path that fits the environment your AI agent already uses. Agent Analytics exposes one analytics surface through four real access paths: - `Skill` for agent environments that already support skills and command execution - `MCP` for chat-native and editor-native tool use - `CLI` for shell-oriented agent workflows - `API` for raw HTTP control The product model does not change between them. Projects, analytics reads, and experiment operations stay the same; only the native entrypoint changes. ## Recommended path by environment | Environment | Recommended path | Why | | --- | --- | --- | | Claude Code | Skill first | Keeps the workflow agent-native without requiring raw MCP | | Claude Desktop / Cowork | Hosted MCP | Best fit for connector-style chat tools with native tool calls | | OpenWork | Skill first | Best fit when you want workspace-local skills, automations, and optional MCP fallback in the same app | | Cursor | Skill + CLI first | Usually lower overhead than MCP when the agent can already run commands | | OpenAI Codex | Skill first | Keeps the workflow agent-native without requiring MCP | | OpenClaw | Skill first | Cleanest path when OpenClaw owns the scheduled analytics job from chat | | Custom runtime or internal agent | API | Best fit when you own retries, parsing, and orchestration | ## When to use each path ### Skill Use a skill when your agent already supports skills and can execute commands in the same environment. A skill is usually the best fit when: - you want a guided workflow layer around common analytics tasks - your agent already has terminal access - you want to stay in the agent's native loop instead of switching to tool-call-heavy MCP flows ### MCP Use MCP when your AI agent already runs inside a tool that supports connectors or MCP servers. MCP is usually the best fit when: - you want the install to feel native inside chat - you want tool calls instead of shell commands - you do not want to hand-roll auth headers or request payloads - you want quick project or account summaries through structured tool responses - you want agent-readable reports such as `analytics_paths`, where the tool response includes both compact text and structured data Tradeoff: - MCP often adds more latency and token overhead than skill + CLI flows because the model has to manage more tool-call round trips and tool result payloads. ### CLI Use the CLI when your AI agent already has terminal access and is comfortable executing commands. CLI is usually the best fit when: - your AI agent already lives in a shell-first environment - you want predictable command output - you prefer command composition over tool integration - you want lower overhead than MCP in editor-style agents like Cursor - you want simple local auth helpers like `login` and `logout` around the same API - you want shell-readable commands such as `paths` that summarize entry pages, exit pages, terminal labels, and next-step analysis For install, login flow, common commands, and CLI-to-API mapping, continue to the dedicated [CLI page](/reference/cli/). ### API Use the API when you want strict control over requests, retries, and response parsing. API is usually the best fit when: - you are integrating from your own code - you need exact HTTP-level behavior - you are debugging auth or payload shape directly Agent Analytics publishes [auth.md discovery and user-claimed agent authentication](/reference/auth-md/) for custom agent runtimes. Compatible agents can start from an unauthenticated API call, follow the `WWW-Authenticate` metadata pointer, ask the human for browser approval, then use a scoped `aas_*` bearer token. ## Quick rule of thumb - Choose `skill + CLI` first in shell-capable or workspace-driven environments like Claude Code, OpenWork, Cursor, or Codex. - Choose `MCP` when the agent already lives in a connector-style chat environment and you want native tool calls. - Choose `API` when you need full control, custom integration, or lower-level debugging. ## Paths Across Access Paths Session paths are available through the same product surface: - CLI: `agent-analytics paths --goal ` - MCP: `analytics_paths` - API: `POST /paths` Use paths when the agent needs to connect entry pages and exit pages to goal behavior before deciding whether to run a funnel query, retention check, or experiment. The report is intentionally bounded and session-local. It is not a long-cycle identity-stitching report. ## Related - [CLI](/reference/cli/) - [Session Paths](/guides/session-paths/) - [Installation Overview](/installation/) - [Authentication](/reference/authentication/) - [auth.md agent authentication](/reference/auth-md/) - [Bot Traffic](/reference/bot-traffic/) - [API Reference](/api/) ## Rate Limits URL: https://docs.agentanalytics.sh/reference/rate-limits/ Hosted Agent Analytics uses account-level API limits and event-volume limits that vary by plan. ## Standard limits | Tier | Requests / minute | Event limit | Data retention | | --- | --- | --- | --- | | Free | 10 | 100,000 / month | 90 days | | Pro | 1,000 | Unlimited | 365 days | Free hosted accounts also get: - up to 2 projects - 500 agent/API read actions per month - MCP access for `list_projects`, `create_project`, `all_sites_overview`, `analytics_overview`, `bot_traffic_overview`, and `all_sites_bot_traffic` Bot traffic overview stays available on both hosted tiers through API, CLI, and MCP. Paid plans unlock the full API, CLI, and MCP surface. Free accounts receive `PRO_REQUIRED` on query, funnels, retention, experiments, and the richer analytics endpoints. `POST /track/batch` accepts up to 100 events per request. If you buffer events for consent or offline delivery, split larger buffers into multiple batch requests. Request-per-minute limits apply per HTTP request; monthly event limits and spend caps apply per accepted event. ## Streaming limits | Limit | Value | | --- | --- | | Concurrent SSE streams | 10 per account | | `/live` rate | Standard API rate limit | | Inactivity timeout | 30 minutes | | Ring buffer | 5 minutes / 10,000 events | ## What to do if you hit a limit - back off and retry instead of hammering the same endpoint - reduce polling frequency for overview queries - batch ingestion where possible - move experiments and heavier analysis to a pro account if that is the bottleneck ## Related - [Bot Traffic](/reference/bot-traffic/) - [Error Format](/reference/error-format/) - [API Reference](/api/) ## Error Format URL: https://docs.agentanalytics.sh/reference/error-format/ All API errors return a machine-readable code plus a human-readable message. All errors return JSON with an `error` code and a `message`. ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ## Common error codes - `AUTH_REQUIRED` - `FORBIDDEN` - `PROJECT_REQUIRED` - `MISSING_FIELDS` - `RATE_LIMITED` - `INVALID_TOKEN` - `BATCH_TOO_LARGE` - `INVALID_METRIC` - `INVALID_GROUP_BY` - `INVALID_FILTER_OP` - `INVALID_PROPERTY_KEY` - `NOT_FOUND` - `EXPERIMENT_NOT_FOUND` - `EXPERIMENT_NAME_EXISTS` - `INVALID_VARIANTS` - `INVALID_EXPERIMENT_STATUS` - `PRO_REQUIRED` - `STREAM_LIMIT` - `INVALID_FUNNEL_STEPS` ## How to debug 1. check the `error` field first and branch on that in your code 2. use the `message` field for logs and human-readable tool output 3. confirm whether the failure came from auth, a missing project, or invalid query shape before retrying ## Related - [Authentication](/reference/authentication/) - [Rate Limits](/reference/rate-limits/) - [API Reference](/api/) ## API Reference # Agent Analytics API - **OpenAPI Version:**Β `3.1.0` - **API Version:**Β `1.0.0` Web analytics platform with an HTTP API that AI agents can query. **Docs:** [Home](https://docs.agentanalytics.sh) Β· [Getting Started](https://docs.agentanalytics.sh/getting-started/) Β· [Installation](https://docs.agentanalytics.sh/installation/) Β· [API Reference](https://docs.agentanalytics.sh/api/) Β· [OpenAPI Spec](https://docs.agentanalytics.sh/openapi.yaml) **Quick start:** 1. Start an agent session with `POST /agent-sessions/start` or sign in on the dashboard. 2. Create a project with `POST /projects`. 3. Add the returned tracker snippet to your site. 4. Query analytics with `GET /stats`. **Authentication:** - `aas_*` agent sessions are the primary machine-auth mechanism for CLI, MCP, and managed runtimes. - `aak_*` API keys are an advanced/manual fallback for direct HTTP users. - `aat_*` project tokens are public and used for ingestion only. Installation guides for Claude Code, Claude Desktop / Cowork, Cursor, and OpenAI Codex now live in the docs site instead of this OpenAPI intro block. ## Servers - **URL:**Β `https://api.agentanalytics.sh` - **Description:**Β Production (hosted) ## Operations ### Start an agent-session signup/login flow - **Method:**Β `POST` - **Path:**Β `/agent-sessions/start` - **Tags:**Β Agent Sessions Creates a pending auth request for a CLI, MCP client, or managed runtime. Use `mode=interactive` when the runtime can receive a localhost/browser callback. Use `mode=detached` when the runtime must wait for approval by polling or manual exchange. #### Request Body ##### Content-Type: application/json - **`client_type` (required)** `string` β€” Runtime type such as \`cli\`, \`mcp\`, \`paperclip\`, or \`openclaw\`. - **`callback_url`** `string | null` β€” Required for interactive mode. Local loopback callback URL. - **`client_instance_id`** `string | null` - **`client_name`** `string | null` - **`code_challenge`** `string | null` β€” Optional PKCE-style challenge for interactive runtimes. - **`label`** `string | null` - **`metadata`** `object | null` - **`mode`** `string`, possible values: `"interactive", "detached"`, default: `"interactive"` - **`scopes`** `array` **Items:** `string`, possible values: `"account:read", "projects:write", "analytics:read", "experiments:write", "feedback:write", "live:read"` **Example:** ```json { "mode": "interactive", "client_type": "cli", "client_name": "Agent Analytics CLI", "client_instance_id": "pid:12345", "label": "Paperclip Workspace", "callback_url": "http://127.0.0.1:43123/callback", "scopes": [ "account:read" ], "code_challenge": null, "metadata": null } ``` #### Responses ##### Status: 201 Auth request created ###### Content-Type: application/json - **`auth_request_id`** `string` - **`authorize_url`** `string` - **`expires_at`** `integer` - **`mode`** `string`, possible values: `"interactive", "detached"` - **`ok`** `boolean` - **`poll_token`** `string` - **`scopes`** `array` **Items:** `string` **Example:** ```json { "ok": true, "auth_request_id": "req_agent123", "authorize_url": "https://api.agentanalytics.sh/agent-sessions/authorize/req_agent123", "poll_token": "aap_polltoken", "mode": "interactive", "expires_at": 1775079600000, "scopes": [ "" ] } ``` ##### Status: 400 Invalid request payload ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Browser approval page for an auth request - **Method:**Β `GET` - **Path:**Β `/agent-sessions/authorize/{id}` - **Tags:**Β Agent Sessions Human-facing browser entry for agent signup/login approval. The response is HTML and lets the user continue with Google or GitHub OAuth. This endpoint is usually opened from the `authorize_url` returned by `POST /agent-sessions/start`. #### Responses ##### Status: 200 HTML approval page ###### Content-Type: text/html `string` **Example:** ```json true ``` ##### Status: 404 Auth request not found ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 410 Auth request expired ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Poll detached auth status - **Method:**Β `POST` - **Path:**Β `/agent-sessions/poll` - **Tags:**Β Agent Sessions Checks whether a detached auth request has been approved, exchanged, revoked, or expired. #### Request Body ##### Content-Type: application/json - **`auth_request_id` (required)** `string` - **`poll_token` (required)** `string` **Example:** ```json { "auth_request_id": "", "poll_token": "" } ``` #### Responses ##### Status: 200 Auth request status ###### Content-Type: application/json - **`account_id`** `object` - **`approved_email`** `object` - **`exchange_code`** `object` - **`status`** `string`, possible values: `"pending", "approved", "exchanged", "revoked", "expired"` **Example:** ```json { "status": "pending", "exchange_code": "", "account_id": "", "approved_email": "" } ``` ##### Status: 401 Invalid poll token or auth request ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 410 Auth request revoked or expired ###### Content-Type: application/json - **`account_id`** `object` - **`approved_email`** `object` - **`exchange_code`** `object` - **`status`** `string`, possible values: `"pending", "approved", "exchanged", "revoked", "expired"` **Example:** ```json { "status": "pending", "exchange_code": "", "account_id": "", "approved_email": "" } ``` ### Exchange an approved auth request for an agent session - **Method:**Β `POST` - **Path:**Β `/agent-sessions/exchange` - **Tags:**Β Agent Sessions Redeems an approved auth request into a renewable agent session. Interactive runtimes should send the matching `code_verifier` when the start request included a `code_challenge`. #### Request Body ##### Content-Type: application/json - **`auth_request_id` (required)** `string` - **`exchange_code` (required)** `string` - **`code_verifier`** `string | null` β€” Required when the auth request was started with a code challenge. **Example:** ```json { "auth_request_id": "", "exchange_code": "", "code_verifier": null } ``` #### Responses ##### Status: 200 Agent session issued ###### Content-Type: application/json - **`account`** `object` - **`email`** `string` - **`github_login`** `object` - **`google_name`** `object` - **`id`** `string` - **`tier`** `string`, possible values: `"free", "pro"` - **`agent_session`** `object` - **`access_expires_at`** `integer` - **`access_token`** `string` - **`id`** `string` - **`refresh_expires_at`** `integer` - **`refresh_token`** `string` - **`scopes`** `array` **Items:** `string` - **`ok`** `boolean` **Example:** ```json { "ok": true, "agent_session": { "id": "", "access_token": "aas_123", "refresh_token": "aar_123", "access_expires_at": 1, "refresh_expires_at": 1, "scopes": [ "" ] }, "account": { "id": "", "email": "", "github_login": "", "google_name": "", "tier": "free" } } ``` ##### Status: 400 Auth request is not ready ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 401 Invalid exchange code or code verifier ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 409 Auth request has already been exchanged ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 410 Auth request expired ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Refresh an agent session access token - **Method:**Β `POST` - **Path:**Β `/agent-sessions/refresh` - **Tags:**Β Agent Sessions Exchanges a valid refresh token for a new access token while keeping the same logical agent session. #### Request Body ##### Content-Type: application/json - **`refresh_token` (required)** `string` **Example:** ```json { "refresh_token": "" } ``` #### Responses ##### Status: 200 Session refreshed ###### Content-Type: application/json - **`agent_session`** `object` - **`access_expires_at`** `integer` - **`access_token`** `string` - **`account`** `object` - **`email`** `string` - **`github_login`** `object` - **`google_name`** `object` - **`id`** `string` - **`tier`** `string`, possible values: `"free", "pro"` - **`refresh_expires_at`** `integer` - **`refresh_token`** `string` - **`scopes`** `array` **Items:** `string` - **`session_id`** `string` - **`ok`** `boolean` **Example:** ```json { "ok": true, "agent_session": { "session_id": "", "access_token": "", "refresh_token": "", "access_expires_at": 1, "refresh_expires_at": 1, "account": { "id": "", "email": "", "github_login": "", "google_name": "", "tier": "free" }, "scopes": [ "" ] } } ``` ##### Status: 400 Missing refresh token ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 401 Invalid or expired refresh token ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Revoke an agent session - **Method:**Β `POST` - **Path:**Β `/agent-sessions/revoke` - **Tags:**Β Agent Sessions Revokes one active agent session owned by the authenticated account. #### Request Body ##### Content-Type: application/json - **`session_id` (required)** `string` **Example:** ```json { "session_id": "" } ``` #### Responses ##### Status: 200 Session revoked ###### Content-Type: application/json - **`ok`** `boolean` - **`session_id`** `string` **Example:** ```json { "ok": true, "session_id": "" } ``` ##### Status: 401 Missing or invalid account auth ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 404 Session not found ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Track a single event - **Method:**Β `POST` - **Path:**Β `/track` - **Tags:**Β Ingestion Record an event. Called automatically by the `tracker.js` script running in your visitors' browsers β€” you don't need to call this directly. Add the tracker to your site and it handles everything: ```html ``` The response is `202 Accepted` β€” events are queued and written asynchronously. Automated traffic that reaches this endpoint is filtered out of normal analytics and reported separately via `/bot-traffic` and `/account/bot-traffic`. #### Request Body ##### Content-Type: application/json - **`event` (required)** `string` β€” Event name (max 256 chars) - **`token` (required)** `string` β€” Project token (\`aat\_\*\`) - **`properties`** `object | null` β€” Arbitrary key-value properties (max 8KB JSON). The tracker auto-populates \`path\`, \`url\`, \`hostname\`, \`title\`, \`referrer\`, \`screen\`, \`browser\`, \`browser\_version\`, \`os\`, \`device\`, \`language\`, \`timezone\` (IANA), \`utm\_\*\` params, \`session\_count\`, \`days\_since\_first\_visit\`, and \`first\_utm\_\*\` (first-touch attribution). - **`session_id`** `string | null` β€” Session identifier (max 256 chars). The tracker auto-generates one via sessionStorage with 30-min inactivity timeout. - **`timestamp`** `number | null` β€” Unix timestamp in milliseconds. Defaults to \`Date.now()\`. Must be within 30 days ago to 5 minutes in the future. - **`user_id`** `string | null` β€” Anonymous user identifier (max 256 chars). The tracker auto-generates one via localStorage. **Example:** ```json { "token": "aat_51da22cdcab084ae1cdb50fd4841c642f0dafdb1d9adfa6b", "event": "page_view", "properties": { "path": "/pricing", "referrer": "https://google.com", "browser": "Chrome", "os": "macOS" }, "user_id": "usr_abc123", "session_id": "ses_xyz789", "timestamp": 1706745600000 } ``` #### Responses ##### Status: 202 Event queued ###### Content-Type: application/json - **`ok`** `boolean` - **`queued`** `boolean` **Example:** ```json { "ok": true, "queued": true } ``` ##### Status: 400 Validation error (missing fields, invalid event name, properties too large) ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 401 Invalid or missing token ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 429 Rate limited ###### Content-Type: application/json **All of:** - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message * **`reason`** `string`, possible values: `"rate_limit", "lifetime_event_limit", "monthly_spend_cap"` **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required", "reason": "rate_limit" } ``` ### Track multiple events - **Method:**Β `POST` - **Path:**Β `/track/batch` - **Tags:**Β Ingestion Record up to 100 events in a single request. All events must use the same project token. If a client buffers more than 100 events, such as while waiting for tracking consent, split the buffer into multiple `/track/batch` requests. Like `/track`, this is called by the browser tracker β€” not by agents or CLI. Automated traffic that reaches this endpoint is filtered out of normal analytics and reported separately via `/bot-traffic` and `/account/bot-traffic`. #### Request Body ##### Content-Type: application/json - **`events` (required)** `array` β€” Array of events (max 100 per batch) **Items:** - **`event` (required)** `string` - **`token` (required)** `string` β€” Project token (\`aat\_\*\`). All events must use the same token. - **`properties`** `object | null` - **`session_id`** `string | null` - **`timestamp`** `number | null` - **`user_id`** `string | null` **Example:** ```json { "events": [ { "token": "aat_51da22cdcab084ae1cdb50fd4841c642f0dafdb1d9adfa6b", "event": "page_view", "properties": null, "user_id": null, "session_id": null, "timestamp": null } ] } ``` #### Responses ##### Status: 202 Events queued ###### Content-Type: application/json - **`count`** `integer` - **`ok`** `boolean` - **`queued`** `boolean` **Example:** ```json { "ok": true, "queued": true, "count": 5 } ``` ##### Status: 400 Validation error (empty array, exceeds 100 events, invalid event) ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 401 Invalid or missing token ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 429 Rate limited ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Link anonymous user to authenticated identity - **Method:**Β `POST` - **Path:**Β `/identify` - **Tags:**Β Ingestion Maps `previous_id` (typically an anonymous tracker ID like `anon_xxx`) to `user_id` (the authenticated identity). All historical events and sessions with `previous_id` are backfilled to use `user_id`. Called automatically by the tracker's `aa.identify("user_123", { email: "alice@example.com" })` method. Can also be called server-side after authentication to stitch identities. Use a stable application user ID for `user_id`; do not identify users by email address. If `traits.email` is present, raw email is transmitted over HTTPS only for identify-time lookup indexing. Agent Analytics stores a scoped HMAC lookup index and strips raw email from event rows and profile traits by default. - **Idempotent**: sending the same mapping twice is a no-op - **Re-identify**: updating the mapping triggers a new backfill - **Project-scoped**: only affects events/sessions in the specified project #### Request Body ##### Content-Type: application/json - **`previous_id` (required)** `string` β€” The anonymous or previous user ID to replace - **`token` (required)** `string` β€” Project token (\`aat\_\*\`) - **`user_id` (required)** `string` β€” The authenticated stable application user ID to assign. Do not use an email address as the user ID. - **`traits`** `object` β€” Optional safe profile traits. \`traits.email\` may be sent for server-side HMAC lookup indexing; raw email is not stored in event rows or profile traits by default. **Example:** ```json { "token": "aat_abc123", "previous_id": "anon_k7x9m2abc", "user_id": "user_12345", "traits": { "email": "alice@example.com", "plan": "pro", "role": "admin", "team": "acme" } } ``` #### Responses ##### Status: 202 Identity mapping queued for processing ###### Content-Type: application/json - **`ok`** `boolean` - **`queued`** `boolean` **Example:** ```json { "ok": true, "queued": true } ``` ##### Status: 400 Validation error (missing fields, same IDs, exceeds length) ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 401 Invalid or missing token ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 429 Rate limited ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Aggregated stats overview - **Method:**Β `GET` - **Path:**Β `/stats` - **Tags:**Β Analytics Returns an overview of a project's analytics: time series, top events, session metrics, and totals. Bounce metrics are computed from event names at query time. A session is a bounce when it has only non-interactive events: `page_view`, `$impression`, `$scroll_depth`, `$error`, `$time_on_page`, `$performance`, `$web_vitals`. **CLI:** `npx --yes @agent-analytics/cli@0.5.34 stats my-site --since 7d` #### Responses ##### Status: 200 Stats overview ###### Content-Type: application/json - **`events`** `array` β€” Top event names by count (max 20) **Items:** - **`count`** `integer` - **`event`** `string` - **`unique_users`** `integer` - **`period`** `object` - **`from`** `string` - **`groupBy`** `string`, possible values: `"hour", "day", "week", "month"` - **`to`** `string` - **`project`** `string` - **`project_context`** `object` - **`activation_events`** `array`, default: `[]` β€” Event names that define activation or the main success path. **Items:** `string` - **`annotations`** `array`, default: `[]` β€” Major date annotations. Project-scoped analytics responses include only annotations inside the requested date range plus one day before and after. **Items:** - **`occurred_at` (required)** `string`, format: `date-time` β€” ISO-8601 datetime when a major product change happened. Stored as a UTC ISO string. - **`title` (required)** `string` β€” Short annotation title for a meaningful product, pricing, release, landing-page, onboarding, feature, or experiment change. - **`note`** `string` β€” Optional short note. Do not store commit logs, PII, secrets, or long release notes. - **`glossary`** `array`, default: `[]` **Items:** - **`definition` (required)** `string` β€” Short meaning that helps an agent interpret analytics results. - **`event_name` (required)** `string` β€” Event name this glossary entry explains. Use \`/properties\` or \`/properties/received\` to inspect current project event names before updating. - **`term` (required)** `string` β€” Human or product term for the event. - **`goals`** `array`, default: `[]` **Items:** `string` - **`sessions`** `object` - **`avg_duration`** `integer` β€” Average session duration in milliseconds - **`bounce_rate`** `number` β€” Bounce rate computed from event names at query time. A session is a bounce when it has only non-interactive events: \`page\_view\`, \`$impression\`, \`$scroll\_depth\`, \`$error\`, \`$time\_on\_page\`, \`$performance\`, \`$web\_vitals\`. - **`pages_per_session`** `number` - **`sessions_per_user`** `number` - **`total_sessions`** `integer` - **`timeSeries`** `array` **Items:** - **`bucket`** `string` - **`total_events`** `integer` - **`unique_users`** `integer` - **`totals`** `object` - **`total_events`** `integer` - **`unique_users`** `integer` **Example:** ```json { "project": "my-site", "project_context": { "goals": [ "Increase activated Agent Analytics accounts" ], "activation_events": [ "signup_completed", "project_created", "first_event_received" ], "glossary": [], "annotations": [] }, "period": { "from": "2025-01-01", "to": "2025-01-07", "groupBy": "day" }, "totals": { "unique_users": 142, "total_events": 1247 }, "timeSeries": [ { "bucket": "2025-01-01", "unique_users": 1, "total_events": 1 } ], "events": [ { "event": "page_view", "count": 1, "unique_users": 1 } ], "sessions": { "total_sessions": 1, "bounce_rate": 0.45, "avg_duration": 1, "pages_per_session": 1, "sessions_per_user": 1 } } ``` ##### Status: 400 Missing project parameter ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 401 Missing or invalid API key ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Raw event log - **Method:**Β `GET` - **Path:**Β `/events` - **Tags:**Β Analytics Returns individual events, newest first. Filter by event name and/or session ID. **CLI:** `npx --yes @agent-analytics/cli@0.5.34 events my-site --event page_view --since 7d --limit 50` #### Responses ##### Status: 200 Event list ###### Content-Type: application/json - **`events`** `array` **Items:** - **`country`** `string | null` β€” ISO 3166-1 alpha-2 country code derived from the request IP at ingestion time - **`date`** `string` - **`event`** `string` - **`id`** `string` - **`project_id`** `string` - **`properties`** `object | null` - **`session_id`** `string | null` - **`timestamp`** `number` - **`user_id`** `string | null` - **`project`** `string` **Example:** ```json { "project": "", "events": [ { "id": "", "project_id": "", "event": "", "properties": null, "user_id": null, "session_id": null, "timestamp": 1, "date": "", "country": "US" } ] } ``` ##### Status: 401 Missing or invalid API key ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Raw event log by user ID or email lookup - **Method:**Β `POST` - **Path:**Β `/events` - **Tags:**Β Analytics Authenticated lookup variant for one customer's rows. Use `user_id` for stable IDs, or send raw `email` in the HTTPS POST body for server-side scoped HMAC lookup. `email_hash` is no longer accepted. Agent Analytics does not store raw lookup email in event rows or profile traits. #### Request Body ##### Content-Type: application/json **Any of:** **Example:** ```json { "project": "my-site", "user_id": "user_12345", "email": "alice@example.com", "event": "signup", "since": "30d", "limit": 100 } ``` #### Responses ##### Status: 200 Event list ###### Content-Type: application/json - **`events`** `array` **Items:** - **`country`** `string | null` β€” ISO 3166-1 alpha-2 country code derived from the request IP at ingestion time - **`date`** `string` - **`event`** `string` - **`id`** `string` - **`project_id`** `string` - **`properties`** `object | null` - **`session_id`** `string | null` - **`timestamp`** `number` - **`user_id`** `string | null` - **`project`** `string` **Example:** ```json { "project": "", "events": [ { "id": "", "project_id": "", "event": "", "properties": null, "user_id": null, "session_id": null, "timestamp": 1, "date": "", "country": "US" } ] } ``` ##### Status: 400 Validation error ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 401 Missing or invalid API key ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Customer journey by user ID or email lookup - **Method:**Β `POST` - **Path:**Β `/journey` - **Tags:**Β Analytics Returns chronological events and matching profiles for a single known identity. Use a stable `user_id` when available. For support lookup by email, send raw `email` in the HTTPS POST body; the API normalizes it, computes scoped HMAC lookup indexes server-side, and does not store raw email in event rows or profile traits. `email_hash` is no longer accepted. #### Request Body ##### Content-Type: application/json **Any of:** **Example:** ```json { "project": "my-site", "user_id": "user_12345", "email": "alice@example.com", "event": "signup", "since": "30d", "limit": 100 } ``` #### Responses ##### Status: 200 Chronological journey ###### Content-Type: application/json - **`events`** `array` **Items:** - **`country`** `string | null` β€” ISO 3166-1 alpha-2 country code derived from the request IP at ingestion time - **`date`** `string` - **`event`** `string` - **`id`** `string` - **`project_id`** `string` - **`properties`** `object | null` - **`session_id`** `string | null` - **`timestamp`** `number` - **`user_id`** `string | null` - **`profiles`** `array` **Items:** - **`project`** `string` - **`user_id`** `string | null` **Example:** ```json { "project": "", "user_id": null, "profiles": [ { "additionalProperty": "anything" } ], "events": [ { "id": "", "project_id": "", "event": "", "properties": null, "user_id": null, "session_id": null, "timestamp": 1, "date": "", "country": "US" } ] } ``` ##### Status: 400 Validation error ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 401 Missing or invalid API key ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Flexible analytics query - **Method:**Β `POST` - **Path:**Β `/query` - **Tags:**Β Analytics Run custom analytics queries with metrics, grouping, filtering, and ordering. This is the most powerful endpoint for building custom reports. **Metrics:** `event_count`, `unique_users`, `session_count`, `bounce_rate`, `avg_duration` **Group by:** `event`, `date`, `user_id`, `session_id`, `country` Property-based grouping such as `properties.hostname`, `properties.first_utm_source`, or `properties.cta` is not supported. **Filter operators:** `eq`, `neq`, `gt`, `lt`, `gte`, `lte`, `contains` **Filterable fields:** `event`, `user_id`, `date`, `country`, `session_id`, `timestamp`, and any `properties.*` field (e.g. `properties.path`, `properties.browser`, `properties.first_utm_source`) Built-in fields are a closed list. Common analytics properties such as `referrer`, `utm_source`, `path`, `browser`, and `hostname` must be queried as `properties.referrer`, `properties.utm_source`, `properties.path`, `properties.browser`, and `properties.hostname`. Invalid filter fields fail the query with `400` and include `/properties`-style discovery guidance instead of being silently ignored. **Count modes:** `session_then_user` (default for `event_count`) or `raw` `/events` remains lossless and returns every ingested row. `/query` uses `session_then_user` as the default for `event_count`: session-backed rows count by session, no-session rows fall back to `user_id` only when that user has no session-backed row in the same filtered/grouped result set, and fully anonymous rows fall back to event `id`. `count_mode` is ignored for queries without `event_count`. Use `count_mode: raw` when the question is about ingestion volume or debugging raw writes. For support lookup by email, send raw `email` in the HTTPS POST body. The API computes scoped HMAC lookup indexes server-side and does not store raw email in event rows or profile traits. `email_hash` is no longer accepted. **CLI:** `npx --yes @agent-analytics/cli@0.5.34 query my-site --metrics event_count --group-by event --filter '[{"field":"country","op":"eq","value":"US"}]'` #### Request Body ##### Content-Type: application/json - **`project` (required)** `string` β€” Project name - **`count_mode`** `string`, possible values: `"raw", "session_then_user"` β€” How \`event\_count\` is aggregated. Default for \`event\_count\`: \`session\_then\_user\`. Session-backed rows count by session, no-session rows fall back to user only when that user has no session-backed row in the same group, and fully anonymous rows fall back to event id. Ignored for queries without \`event\_count\`. Use \`raw\` to count ingested rows without dedupe. - **`date_from`** `string` β€” Start date (ISO 8601 or \`Nd\` shorthand). Defaults to 7 days ago. - **`date_to`** `string` β€” End date (ISO 8601). Defaults to today. - **`email`** `string`, format: `email` β€” Optional raw email for authenticated lookup. Send only in the HTTPS POST body. The API normalizes it, computes a scoped HMAC lookup index server-side, and does not store raw email in event rows or profile traits. - **`filters`** `array` **Items:** - **`field`** `string` β€” Field to filter on. Built-in: \`event\`, \`user\_id\`, \`date\`, \`country\`, \`session\_id\`, \`timestamp\`. You can also filter on any \`properties.\*\` field, including first-touch attribution fields like \`properties.first\_utm\_source\`. - **`op`** `string`, possible values: `"eq", "neq", "gt", "lt", "gte", "lte", "contains"` - **`value`** `object` β€” Value to compare against - **`group_by`** `array`, default: `[]` β€” Built-in fields to group results by. Property-based grouping such as \`properties.hostname\` is not supported. **Items:** `string`, possible values: `"event", "date", "user_id", "session_id", "country"` - **`limit`** `integer`, default: `100` - **`metrics`** `array`, default: `["event_count"]` β€” Metrics to compute **Items:** `string`, possible values: `"event_count", "unique_users", "session_count", "bounce_rate", "avg_duration"` - **`order`** `string`, possible values: `"asc", "desc"`, default: `"desc"` - **`order_by`** `string`, possible values: `"event_count", "unique_users", "session_count", "date", "event"` β€” Field to sort by **Example:** ```json { "project": "my-site", "metrics": [ "event_count" ], "group_by": [], "filters": [ { "field": "event", "op": "eq", "value": "page_view" } ], "date_from": "2025-01-01", "date_to": "2025-01-07", "count_mode": "raw", "email": "alice@example.com", "order_by": "event_count", "order": "desc", "limit": 100 } ``` #### Responses ##### Status: 200 Query results ###### Content-Type: application/json - **`count`** `integer` - **`group_by`** `array` **Items:** `string` - **`metrics`** `array` **Items:** `string` - **`period`** `object` - **`from`** `string` - **`to`** `string` - **`project`** `string` - **`project_context`** `object` - **`activation_events`** `array`, default: `[]` β€” Event names that define activation or the main success path. **Items:** `string` - **`annotations`** `array`, default: `[]` β€” Major date annotations. Project-scoped analytics responses include only annotations inside the requested date range plus one day before and after. **Items:** - **`occurred_at` (required)** `string`, format: `date-time` β€” ISO-8601 datetime when a major product change happened. Stored as a UTC ISO string. - **`title` (required)** `string` β€” Short annotation title for a meaningful product, pricing, release, landing-page, onboarding, feature, or experiment change. - **`note`** `string` β€” Optional short note. Do not store commit logs, PII, secrets, or long release notes. - **`glossary`** `array`, default: `[]` **Items:** - **`definition` (required)** `string` β€” Short meaning that helps an agent interpret analytics results. - **`event_name` (required)** `string` β€” Event name this glossary entry explains. Use \`/properties\` or \`/properties/received\` to inspect current project event names before updating. - **`term` (required)** `string` β€” Human or product term for the event. - **`goals`** `array`, default: `[]` **Items:** `string` - **`rows`** `array` **Items:** **Example:** ```json { "project": "", "project_context": { "goals": [ "Increase activated Agent Analytics accounts" ], "activation_events": [ "signup_completed", "project_created", "first_event_received" ], "glossary": [], "annotations": [] }, "period": { "from": "", "to": "" }, "metrics": [ "" ], "group_by": [ "" ], "rows": [ { "additionalProperty": "anything" } ], "count": 1 } ``` ##### Status: 400 Invalid query (bad metric, group\_by, filter, or missing project) ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 401 Missing or invalid API key ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Discover event names and property keys - **Method:**Β `GET` - **Path:**Β `/properties` - **Tags:**Β Analytics Returns all event names with counts, and a list of known property keys from recent events. Useful for building dynamic filters and understanding what data is available. **CLI:** `npx --yes @agent-analytics/cli@0.5.34 properties my-site` #### Responses ##### Status: 200 Event names and property keys ###### Content-Type: application/json - **`events`** `array` **Items:** - **`count`** `integer` - **`event`** `string` - **`first_seen`** `string` - **`last_seen`** `string` - **`unique_users`** `integer` - **`project`** `string` - **`property_keys`** `array` **Items:** `string` **Example:** ```json { "project": "", "events": [ { "event": "page_view", "count": 1, "unique_users": 1, "first_seen": "", "last_seen": "" } ], "property_keys": [ "browser", "device", "hostname", "language", "os", "path", "referrer", "screen", "title", "url" ] } ``` ##### Status: 401 Missing or invalid API key ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Property keys by event name - **Method:**Β `GET` - **Path:**Β `/properties/received` - **Tags:**Β Analytics Returns which property keys appear on which event names, sampled from recent events. More detailed than `/properties` β€” shows the event-to-property mapping. #### Responses ##### Status: 200 Property-to-event mapping ###### Content-Type: application/json - **`project`** `string` - **`properties`** `array` **Items:** - **`event`** `string` - **`key`** `string` - **`sample_size`** `integer` - **`since`** `string` **Example:** ```json { "project": "", "sample_size": 5000, "since": "", "properties": [ { "key": "path", "event": "page_view" } ] } ``` ##### Status: 401 Missing or invalid API key ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Get project replay settings - **Method:**Β `GET` - **Path:**Β `/replays/settings` - **Tags:**Β Session Replay Returns explicit enablement, mandatory privacy controls, custom selectors, and hard limits. Replay remains off until the separate `replay.js` bootstrap is installed. #### Responses ##### Status: 200 Replay settings and limits ###### Content-Type: application/json **Example:** ```json {} ``` ##### Status: 401 Missing or invalid account authentication ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Enable, disable, or update project replay settings - **Method:**Β `PUT` - **Path:**Β `/replays/settings` - **Tags:**Β Session Replay Enabling requires Pro or complimentary access and explicit HTTPS allowed origins. Input masking and PII redaction are mandatory and cannot be disabled. #### Request Body ##### Content-Type: application/json - **`enabled` (required)** `boolean` - **`project` (required)** `string` - **`block_selectors`** `array` **Items:** `string` - **`ignore_selectors`** `array` **Items:** `string` - **`mask_inputs`** `boolean` - **`mask_selectors`** `array` **Items:** `string` - **`recording_start`** `string`, possible values: `"immediate", "after_consent"` - **`redact_pii`** `boolean` **Example:** ```json { "project": "", "enabled": true, "recording_start": "immediate", "mask_inputs": true, "redact_pii": true, "mask_selectors": [ "" ], "block_selectors": [ "" ], "ignore_selectors": [ "" ] } ``` #### Responses ##### Status: 200 Updated replay settings and limits ###### Content-Type: application/json **Example:** ```json {} ``` ##### Status: 400 Invalid project origins or settings ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 403 Replay entitlement required ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### List replay metadata - **Method:**Β `GET` - **Path:**Β `/replays` - **Tags:**Β Session Replay Lists bounded replay metadata without returning recorded DOM data. Filter by analytics session ID to find all segments linked to one measured session. #### Responses ##### Status: 200 Replay summaries and pagination cursor ###### Content-Type: application/json - **`next_before`** `integer | null`, format: `int64` - **`replays`** `array` **Items:** - **`analytics_session_id`** `string` - **`committed_bytes`** `integer`, format: `int64` - **`ended_at`** `integer | null`, format: `int64` - **`event_count`** `integer` - **`has_full_snapshot`** `boolean` - **`id`** `string` - **`project_id`** `string` - **`started_at`** `integer`, format: `int64` - **`status`** `string`, possible values: `"recording", "complete", "incomplete", "deleting", "deleted"` - **`stop_reason`** `string | null` **Example:** ```json { "replays": [ { "id": "rpl_abc123", "project_id": "", "analytics_session_id": "", "status": "recording", "started_at": 1, "ended_at": null, "committed_bytes": 1, "event_count": 1, "has_full_snapshot": true, "stop_reason": null } ], "next_before": null } ``` ### Disable and delete replay data - **Method:**Β `DELETE` - **Path:**Β `/replays` - **Tags:**Β Session Replay Disables replay and deletes all retained replay objects for the account or one project. This operation requires explicit confirmation. #### Request Body ##### Content-Type: application/json - **`confirm` (required)** `string` - **`project`** `string` **Example:** ```json { "confirm": "delete_replay_data", "project": "" } ``` #### Responses ##### Status: 200 Deletion result ###### Content-Type: application/json - **`deleted`** `integer` - **`ok`** `boolean` - **`project`** `string | null` **Example:** ```json { "ok": true, "deleted": 1, "project": null } ``` ### Get replay storage and ingestion usage - **Method:**Β `GET` - **Path:**Β `/replays/usage` - **Tags:**Β Session Replay #### Responses ##### Status: 200 Retained, reserved, and rolling 30-day replay bytes ###### Content-Type: application/json **Example:** ```json {} ``` ### PARAMETERS /replays/{replayId} - **Method:**Β `PARAMETERS` - **Path:**Β `/replays/{replayId}` ### Get replay metadata and committed chunks - **Method:**Β `GET` - **Path:**Β `/replays/{replayId}` - **Tags:**Β Session Replay #### Responses ##### Status: 200 Replay metadata and chunk boundaries ###### Content-Type: application/json **All of:** - **`analytics_session_id`** `string` - **`committed_bytes`** `integer`, format: `int64` - **`ended_at`** `integer | null`, format: `int64` - **`event_count`** `integer` - **`has_full_snapshot`** `boolean` - **`id`** `string` - **`project_id`** `string` - **`started_at`** `integer`, format: `int64` - **`status`** `string`, possible values: `"recording", "complete", "incomplete", "deleting", "deleted"` - **`stop_reason`** `string | null` * **`chunks`** `array` **Items:** **Example:** ```json { "id": "rpl_abc123", "project_id": "", "analytics_session_id": "", "status": "recording", "started_at": 1, "ended_at": null, "committed_bytes": 1, "event_count": 1, "has_full_snapshot": true, "stop_reason": null, "chunks": [ {} ] } ``` ### Delete one replay - **Method:**Β `DELETE` - **Path:**Β `/replays/{replayId}` - **Tags:**Β Session Replay #### Responses ##### Status: 200 Replay deleted ###### Content-Type: application/json **Example:** ```json {} ``` ### Create a short-lived sandboxed viewer link - **Method:**Β `POST` - **Path:**Β `/replays/{replayId}/open` - **Tags:**Β Session Replay Returns a replay-specific viewer URL that expires after one hour. The URL fragment contains the bearer token and must not be logged, persisted, or published. #### Responses ##### Status: 201 Short-lived viewer link ###### Content-Type: application/json - **`expires_at`** `integer`, format: `int64` - **`viewer_url`** `string`, format: `uri` **Example:** ```json { "viewer_url": "", "expires_at": 1 } ``` ##### Status: 409 Replay is not playable ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### List sessions - **Method:**Β `GET` - **Path:**Β `/sessions` - **Tags:**Β Analytics Returns individual session records with duration, entry/exit pages, event count, and bounce status. Filter by user ID and/or bounce status. `is_bounce` is computed from event names at query time. `1` means the session has only non-interactive events: `page_view`, `$impression`, `$scroll_depth`, `$error`, `$time_on_page`, `$performance`, `$web_vitals`. #### Responses ##### Status: 200 Session list ###### Content-Type: application/json - **`project`** `string` - **`sessions`** `array` **Items:** - **`date`** `string` - **`duration`** `integer` β€” Duration in milliseconds - **`end_time`** `number` - **`entry_page`** `string | null` - **`event_count`** `integer` - **`exit_page`** `string | null` - **`has_replay`** `boolean` β€” Present for callers with replay read authority. True when the session has at least one playable replay segment. - **`is_bounce`** `integer`, possible values: `0, 1` β€” Computed from event names at query time. \`1\` means the session has only non-interactive events: \`page\_view\`, \`$impression\`, \`$scroll\_depth\`, \`$error\`, \`$time\_on\_page\`, \`$performance\`, \`$web\_vitals\`. - **`project_id`** `string` - **`replay_count`** `integer` β€” Number of playable replay segments linked to this analytics session. - **`replays`** `array` β€” Bounded replay summaries. Omitted when the caller does not have replay read authority. **Items:** - **`analytics_session_id`** `string` - **`committed_bytes`** `integer`, format: `int64` - **`ended_at`** `integer | null`, format: `int64` - **`event_count`** `integer` - **`has_full_snapshot`** `boolean` - **`id`** `string` - **`project_id`** `string` - **`started_at`** `integer`, format: `int64` - **`status`** `string`, possible values: `"recording", "complete", "incomplete", "deleting", "deleted"` - **`stop_reason`** `string | null` - **`session_id`** `string` - **`start_time`** `number` - **`user_id`** `string | null` **Example:** ```json { "project": "", "sessions": [ { "session_id": "", "user_id": null, "project_id": "", "start_time": 1, "end_time": 1, "duration": 1, "entry_page": null, "exit_page": null, "event_count": 1, "is_bounce": 0, "has_replay": true, "replay_count": 1, "replays": [ { "id": "rpl_abc123", "project_id": "", "analytics_session_id": "", "status": "recording", "started_at": 1, "ended_at": null, "committed_bytes": 1, "event_count": 1, "has_full_snapshot": true, "stop_reason": null } ], "date": "" } ] } ``` ##### Status: 401 Missing or invalid API key ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Top property values - **Method:**Β `GET` - **Path:**Β `/breakdown` - **Tags:**Β Analytics Breaks down events by a specific property, showing the top values by count. Useful for top pages, referrers, browsers, countries, UTM sources, etc. Use `property=country` to see visitor geography (ISO 3166-1 alpha-2 codes). Country is stored as a dedicated column for fast queries. **CLI:** `npx --yes @agent-analytics/cli@0.5.34 breakdown my-site --property path --event page_view --days 7` #### Responses ##### Status: 200 Property breakdown ###### Content-Type: application/json - **`event`** `string | null` - **`project`** `string` - **`project_context`** `object` - **`activation_events`** `array`, default: `[]` β€” Event names that define activation or the main success path. **Items:** `string` - **`annotations`** `array`, default: `[]` β€” Major date annotations. Project-scoped analytics responses include only annotations inside the requested date range plus one day before and after. **Items:** - **`occurred_at` (required)** `string`, format: `date-time` β€” ISO-8601 datetime when a major product change happened. Stored as a UTC ISO string. - **`title` (required)** `string` β€” Short annotation title for a meaningful product, pricing, release, landing-page, onboarding, feature, or experiment change. - **`note`** `string` β€” Optional short note. Do not store commit logs, PII, secrets, or long release notes. - **`glossary`** `array`, default: `[]` **Items:** - **`definition` (required)** `string` β€” Short meaning that helps an agent interpret analytics results. - **`event_name` (required)** `string` β€” Event name this glossary entry explains. Use \`/properties\` or \`/properties/received\` to inspect current project event names before updating. - **`term` (required)** `string` β€” Human or product term for the event. - **`goals`** `array`, default: `[]` **Items:** `string` - **`property`** `string` - **`total_events`** `integer` - **`total_with_property`** `integer` - **`values`** `array` **Items:** - **`count`** `integer` - **`unique_users`** `integer` - **`value`** `string` **Example:** ```json { "project": "", "project_context": { "goals": [ "Increase activated Agent Analytics accounts" ], "activation_events": [ "signup_completed", "project_created", "first_event_received" ], "glossary": [], "annotations": [] }, "property": "path", "event": null, "values": [ { "value": "/pricing", "count": 342, "unique_users": 201 } ], "total_events": 1, "total_with_property": 1 } ``` ##### Status: 400 Missing property parameter or invalid property key ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 401 Missing or invalid API key ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Period-over-period comparison - **Method:**Β `GET` - **Path:**Β `/insights` - **Tags:**Β Analytics Compares the current period against the previous period of the same length. Returns change metrics and an overall trend indicator (`growing`, `stable`, `declining`). `bounce_rate` is computed from event names at query time. A session is a bounce when it has only non-interactive events: `page_view`, `$impression`, `$scroll_depth`, `$error`, `$time_on_page`, `$performance`, `$web_vitals`. **CLI:** `npx --yes @agent-analytics/cli@0.5.34 insights my-site --period 7d` #### Responses ##### Status: 200 Insights with trend ###### Content-Type: application/json - **`current_period`** `object` - **`from`** `string` - **`to`** `string` - **`metrics`** `object` - **`avg_duration`** `object` - **`change`** `number` - **`change_pct`** `integer | null` β€” Percentage change. Null when previous period was 0 but current is > 0. - **`current`** `number` - **`previous`** `number` - **`bounce_rate`** `object` - **`change`** `number` - **`change_pct`** `integer | null` β€” Percentage change. Null when previous period was 0 but current is > 0. - **`current`** `number` - **`previous`** `number` - **`total_events`** `object` - **`change`** `number` - **`change_pct`** `integer | null` β€” Percentage change. Null when previous period was 0 but current is > 0. - **`current`** `number` - **`previous`** `number` - **`total_sessions`** `object` - **`change`** `number` - **`change_pct`** `integer | null` β€” Percentage change. Null when previous period was 0 but current is > 0. - **`current`** `number` - **`previous`** `number` - **`unique_users`** `object` - **`change`** `number` - **`change_pct`** `integer | null` β€” Percentage change. Null when previous period was 0 but current is > 0. - **`current`** `number` - **`previous`** `number` - **`previous_period`** `object` - **`from`** `string` - **`to`** `string` - **`project`** `string` - **`project_context`** `object` - **`activation_events`** `array`, default: `[]` β€” Event names that define activation or the main success path. **Items:** `string` - **`annotations`** `array`, default: `[]` β€” Major date annotations. Project-scoped analytics responses include only annotations inside the requested date range plus one day before and after. **Items:** - **`occurred_at` (required)** `string`, format: `date-time` β€” ISO-8601 datetime when a major product change happened. Stored as a UTC ISO string. - **`title` (required)** `string` β€” Short annotation title for a meaningful product, pricing, release, landing-page, onboarding, feature, or experiment change. - **`note`** `string` β€” Optional short note. Do not store commit logs, PII, secrets, or long release notes. - **`glossary`** `array`, default: `[]` **Items:** - **`definition` (required)** `string` β€” Short meaning that helps an agent interpret analytics results. - **`event_name` (required)** `string` β€” Event name this glossary entry explains. Use \`/properties\` or \`/properties/received\` to inspect current project event names before updating. - **`term` (required)** `string` β€” Human or product term for the event. - **`goals`** `array`, default: `[]` **Items:** `string` - **`trend`** `string`, possible values: `"growing", "stable", "declining"` **Example:** ```json { "project": "", "project_context": { "goals": [ "Increase activated Agent Analytics accounts" ], "activation_events": [ "signup_completed", "project_created", "first_event_received" ], "glossary": [], "annotations": [] }, "current_period": { "from": "", "to": "" }, "previous_period": { "from": "", "to": "" }, "metrics": { "total_events": { "current": 1, "previous": 1, "change": 1, "change_pct": null }, "unique_users": { "current": 1, "previous": 1, "change": 1, "change_pct": null }, "total_sessions": { "current": 1, "previous": 1, "change": 1, "change_pct": null }, "bounce_rate": { "current": 1, "previous": 1, "change": 1, "change_pct": null }, "avg_duration": { "current": 1, "previous": 1, "change": 1, "change_pct": null } }, "trend": "growing" } ``` ##### Status: 400 Invalid period ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 401 Missing or invalid API key ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Entry/exit page stats - **Method:**Β `GET` - **Path:**Β `/pages` - **Tags:**Β Analytics Returns top entry pages, exit pages, or both β€” with session count, bounce rate, and average duration per page. `bounce_rate` is computed from event names at query time. A session is a bounce when it has only non-interactive events: `page_view`, `$impression`, `$scroll_depth`, `$error`, `$time_on_page`, `$performance`, `$web_vitals`. **CLI:** `npx --yes @agent-analytics/cli@0.5.34 pages my-site --type entry` #### Responses ##### Status: 200 Page stats ###### Content-Type: application/json - **`entry_pages`** `array` **Items:** - **`avg_duration`** `number` β€” Average session duration in milliseconds - **`avg_events`** `number` - **`bounce_rate`** `number` β€” Bounce rate computed from event names at query time. A session is a bounce when it has only non-interactive events: \`page\_view\`, \`$impression\`, \`$scroll\_depth\`, \`$error\`, \`$time\_on\_page\`, \`$performance\`, \`$web\_vitals\`. - **`bounces`** `integer` - **`page`** `string` - **`sessions`** `integer` - **`exit_pages`** `array` **Items:** - **`avg_duration`** `number` β€” Average session duration in milliseconds - **`avg_events`** `number` - **`bounce_rate`** `number` β€” Bounce rate computed from event names at query time. A session is a bounce when it has only non-interactive events: \`page\_view\`, \`$impression\`, \`$scroll\_depth\`, \`$error\`, \`$time\_on\_page\`, \`$performance\`, \`$web\_vitals\`. - **`bounces`** `integer` - **`page`** `string` - **`sessions`** `integer` - **`project`** `string` - **`project_context`** `object` - **`activation_events`** `array`, default: `[]` β€” Event names that define activation or the main success path. **Items:** `string` - **`annotations`** `array`, default: `[]` β€” Major date annotations. Project-scoped analytics responses include only annotations inside the requested date range plus one day before and after. **Items:** - **`occurred_at` (required)** `string`, format: `date-time` β€” ISO-8601 datetime when a major product change happened. Stored as a UTC ISO string. - **`title` (required)** `string` β€” Short annotation title for a meaningful product, pricing, release, landing-page, onboarding, feature, or experiment change. - **`note`** `string` β€” Optional short note. Do not store commit logs, PII, secrets, or long release notes. - **`glossary`** `array`, default: `[]` **Items:** - **`definition` (required)** `string` β€” Short meaning that helps an agent interpret analytics results. - **`event_name` (required)** `string` β€” Event name this glossary entry explains. Use \`/properties\` or \`/properties/received\` to inspect current project event names before updating. - **`term` (required)** `string` β€” Human or product term for the event. - **`goals`** `array`, default: `[]` **Items:** `string` **Example:** ```json { "project": "", "project_context": { "goals": [ "Increase activated Agent Analytics accounts" ], "activation_events": [ "signup_completed", "project_created", "first_event_received" ], "glossary": [], "annotations": [] }, "entry_pages": [ { "page": "/pricing", "sessions": 1, "bounces": 1, "bounce_rate": 0.45, "avg_duration": 1, "avg_events": 1 } ], "exit_pages": [ { "page": "/pricing", "sessions": 1, "bounces": 1, "bounce_rate": 0.45, "avg_duration": 1, "avg_events": 1 } ] } ``` ##### Status: 400 Invalid page type ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 401 Missing or invalid API key ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Session duration histogram - **Method:**Β `GET` - **Path:**Β `/sessions/distribution` - **Tags:**Β Analytics Returns a histogram of session durations in predefined buckets, with the median bucket and engaged session percentage (sessions >= 30 seconds). `bounces` in each bucket are computed from event names at query time. A session is a bounce when it has only non-interactive events: `page_view`, `$impression`, `$scroll_depth`, `$error`, `$time_on_page`, `$performance`, `$web_vitals`. **CLI:** `npx --yes @agent-analytics/cli@0.5.34 sessions distribution my-site` #### Responses ##### Status: 200 Session duration distribution ###### Content-Type: application/json - **`distribution`** `array` **Items:** - **`avg_events`** `number` - **`bounces`** `integer` β€” Number of bounce sessions in this duration bucket (computed from event names at query time). - **`bucket`** `string`, possible values: `"0s", "1-10s", "10-30s", "30-60s", "1-3m", "3-10m", "10m+"` - **`pct`** `number` β€” Percentage of total sessions - **`sessions`** `integer` - **`engaged_pct`** `number` β€” Percentage of sessions >= 30 seconds - **`median_bucket`** `string | null` - **`project`** `string` - **`project_context`** `object` - **`activation_events`** `array`, default: `[]` β€” Event names that define activation or the main success path. **Items:** `string` - **`annotations`** `array`, default: `[]` β€” Major date annotations. Project-scoped analytics responses include only annotations inside the requested date range plus one day before and after. **Items:** - **`occurred_at` (required)** `string`, format: `date-time` β€” ISO-8601 datetime when a major product change happened. Stored as a UTC ISO string. - **`title` (required)** `string` β€” Short annotation title for a meaningful product, pricing, release, landing-page, onboarding, feature, or experiment change. - **`note`** `string` β€” Optional short note. Do not store commit logs, PII, secrets, or long release notes. - **`glossary`** `array`, default: `[]` **Items:** - **`definition` (required)** `string` β€” Short meaning that helps an agent interpret analytics results. - **`event_name` (required)** `string` β€” Event name this glossary entry explains. Use \`/properties\` or \`/properties/received\` to inspect current project event names before updating. - **`term` (required)** `string` β€” Human or product term for the event. - **`goals`** `array`, default: `[]` **Items:** `string` **Example:** ```json { "project": "", "project_context": { "goals": [ "Increase activated Agent Analytics accounts" ], "activation_events": [ "signup_completed", "project_created", "first_event_received" ], "glossary": [], "annotations": [] }, "distribution": [ { "bucket": "0s", "sessions": 1, "bounces": 1, "avg_events": 1, "pct": 1 } ], "median_bucket": null, "engaged_pct": 1 } ``` ##### Status: 401 Missing or invalid API key ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Bounded session path analysis - **Method:**Β `POST` - **Path:**Β `/paths` - **Tags:**Β Paths Analyze session-local journeys from entry pages through mixed page and event nodes, ending in `goal`, `drop_off`, or `truncated`. Each entry page also includes an `exit_pages` attribution table so agents can connect landing-page behavior to the pages where sessions actually ended. This endpoint is explicitly bounded: - fixed `since` values only: `7d`, `14d`, `30d`, `90d` - `max_steps` is capped at 5 - `entry_limit` is capped at 20 - `path_limit` is capped at 10 - `candidate_session_cap` is capped at 10,000 - implementation is limited to two D1 read queries, with Worker-side tree assembly Session attribution is local to the session: the `goal_event` only counts if it occurs in the same session as the entry page. Non-converting terminal nodes are split by `exit_page`, so a branch can show whether the drop-off happened on `/pricing`, `/checkout`, or another exit page. **CLI:** `npx --yes @agent-analytics/cli@0.5.34 paths my-site --goal signup --since 30d --max-steps 5` #### Request Body ##### Content-Type: application/json - **`goal_event` (required)** `string` β€” Goal event that must occur in the same session - **`project` (required)** `string` β€” Project name - **`candidate_session_cap`** `integer`, default: `5000` β€” Max sessions scanned before Worker-side path assembly - **`entry_limit`** `integer`, default: `10` β€” Max entry pages to include - **`max_steps`** `integer`, default: `5` β€” Max mixed page/event steps before the path is marked truncated - **`path_limit`** `integer`, default: `5` β€” Max children kept per tree node after aggregation - **`since`** `string`, possible values: `"7d", "14d", "30d", "90d"`, default: `"30d"` β€” Fixed lookback window for bounded path analysis **Example:** ```json { "project": "my-site", "goal_event": "signup", "since": "30d", "max_steps": 5, "entry_limit": 10, "path_limit": 5, "candidate_session_cap": 5000 } ``` #### Responses ##### Status: 200 Aggregated session path tree by entry page ###### Content-Type: application/json - **`bounds`** `object` - **`candidate_session_cap`** `integer` - **`entry_limit`** `integer` - **`max_steps`** `integer` - **`path_limit`** `integer` - **`entry_paths`** `array` **Items:** - **`conversion_rate`** `number` - **`conversions`** `integer` - **`entry_page`** `string` - **`exit_pages`** `array` β€” Exit pages reached by sessions that started on this entry page, with conversion and drop-off attribution. **Items:** - **`conversion_rate`** `number` - **`conversions`** `integer` - **`drop_off_rate`** `number` - **`drop_offs`** `integer` - **`exit_page`** `string` - **`sessions`** `integer` - **`sessions`** `integer` - **`tree`** `array` **Items:** - **`children`** `array` β€” Child path nodes. The runtime shape matches \`PathNode\`; the schema avoids a circular \`$ref\` so generated docs can render reliably. **Items:** - **`conversion_rate`** `number` - **`conversions`** `integer` - **`exit_page`** `string | null` β€” Present on \`drop\_off\` and \`truncated\` terminal nodes to tie path drop-off behavior to the actual session exit page. - **`sessions`** `integer` - **`type`** `string`, possible values: `"page", "event", "goal", "drop_off", "truncated"` - **`value`** `string` β€” For \`drop\_off\` and \`truncated\` terminal nodes, this is the exit page when known, otherwise \`unknown\`. - **`goal_event`** `string` - **`period`** `object` - **`from`** `string`, format: `date` - **`to`** `string`, format: `date` - **`project`** `string` - **`project_context`** `object` - **`activation_events`** `array`, default: `[]` β€” Event names that define activation or the main success path. **Items:** `string` - **`annotations`** `array`, default: `[]` β€” Major date annotations. Project-scoped analytics responses include only annotations inside the requested date range plus one day before and after. **Items:** - **`occurred_at` (required)** `string`, format: `date-time` β€” ISO-8601 datetime when a major product change happened. Stored as a UTC ISO string. - **`title` (required)** `string` β€” Short annotation title for a meaningful product, pricing, release, landing-page, onboarding, feature, or experiment change. - **`note`** `string` β€” Optional short note. Do not store commit logs, PII, secrets, or long release notes. - **`glossary`** `array`, default: `[]` **Items:** - **`definition` (required)** `string` β€” Short meaning that helps an agent interpret analytics results. - **`event_name` (required)** `string` β€” Event name this glossary entry explains. Use \`/properties\` or \`/properties/received\` to inspect current project event names before updating. - **`term` (required)** `string` β€” Human or product term for the event. - **`goals`** `array`, default: `[]` **Items:** `string` **Example:** ```json { "project": "my-site", "project_context": { "goals": [ "Increase activated Agent Analytics accounts" ], "activation_events": [ "signup_completed", "project_created", "first_event_received" ], "glossary": [], "annotations": [] }, "goal_event": "signup", "period": { "from": "2026-03-11", "to": "2026-04-10" }, "bounds": { "max_steps": 5, "entry_limit": 10, "path_limit": 5, "candidate_session_cap": 5000 }, "entry_paths": [ { "entry_page": "/landing", "sessions": 120, "conversions": 32, "conversion_rate": 0.267, "exit_pages": [ { "exit_page": "/pricing", "sessions": 42, "conversions": 13, "conversion_rate": 0.31, "drop_offs": 29, "drop_off_rate": 0.69 } ], "tree": [ { "type": "page", "value": "/pricing", "exit_page": "/pricing", "sessions": 42, "conversions": 13, "conversion_rate": 0.31, "children": [ { "additionalProperty": "anything" } ] } ] } ] } ``` ##### Status: 400 Validation error for out-of-range bounds or missing goal\_event ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 401 Missing or invalid API key ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 404 Project not found ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Day-of-week x hour traffic grid - **Method:**Β `GET` - **Path:**Β `/heatmap` - **Tags:**Β Analytics Returns a grid of events by day-of-week and hour-of-day (UTC), with peak detection. Useful for understanding when your users are most active. **CLI:** `npx --yes @agent-analytics/cli@0.5.34 heatmap my-site` #### Responses ##### Status: 200 Heatmap grid ###### Content-Type: application/json - **`busiest_day`** `string | null` - **`busiest_hour`** `integer | null` - **`heatmap`** `array` **Items:** - **`day`** `integer` β€” Day of week (0=Sunday, 6=Saturday) - **`day_name`** `string` - **`events`** `integer` - **`hour`** `integer` β€” Hour of day (0-23) - **`users`** `integer` - **`peak`** `object | null` - **`day`** `integer` - **`day_name`** `string` - **`events`** `integer` - **`hour`** `integer` - **`users`** `integer` - **`project`** `string` - **`project_context`** `object` - **`activation_events`** `array`, default: `[]` β€” Event names that define activation or the main success path. **Items:** `string` - **`annotations`** `array`, default: `[]` β€” Major date annotations. Project-scoped analytics responses include only annotations inside the requested date range plus one day before and after. **Items:** - **`occurred_at` (required)** `string`, format: `date-time` β€” ISO-8601 datetime when a major product change happened. Stored as a UTC ISO string. - **`title` (required)** `string` β€” Short annotation title for a meaningful product, pricing, release, landing-page, onboarding, feature, or experiment change. - **`note`** `string` β€” Optional short note. Do not store commit logs, PII, secrets, or long release notes. - **`glossary`** `array`, default: `[]` **Items:** - **`definition` (required)** `string` β€” Short meaning that helps an agent interpret analytics results. - **`event_name` (required)** `string` β€” Event name this glossary entry explains. Use \`/properties\` or \`/properties/received\` to inspect current project event names before updating. - **`term` (required)** `string` β€” Human or product term for the event. - **`goals`** `array`, default: `[]` **Items:** `string` **Example:** ```json { "project": "", "project_context": { "goals": [ "Increase activated Agent Analytics accounts" ], "activation_events": [ "signup_completed", "project_created", "first_event_received" ], "glossary": [], "annotations": [] }, "heatmap": [ { "day": 1, "day_name": "Monday", "hour": 1, "events": 1, "users": 1 } ], "peak": { "day": 1, "day_name": "", "hour": 1, "events": 1, "users": 1 }, "busiest_day": "Monday", "busiest_hour": 14 } ``` ##### Status: 401 Missing or invalid API key ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Funnel analysis - **Method:**Β `POST` - **Path:**Β `/funnel` - **Tags:**Β Funnels Ad-hoc funnel analysis: track where users drop off across a sequence of 2-8 events. Each step can have optional property filters (e.g. only count `page_view` events where `path=/pricing`). The conversion window limits how long users have from entering step 1 to completing the final step. Step 1 is capped at 10,000 users to prevent unbounded scans. **CLI:** `npx --yes @agent-analytics/cli@0.5.34 funnel my-site --steps "page_view,signup,purchase" --window 168 --breakdown country` #### Request Body ##### Content-Type: application/json - **`project` (required)** `string` β€” Project name - **`steps` (required)** `array` β€” Funnel steps (2-8). Each step has an event name and optional property filters. **Items:** - **`event` (required)** `string` β€” Event name for this step - **`filters`** `array` β€” Optional property filters for this step **Items:** - **`op` (required)** `string`, possible values: `"eq", "neq", "contains"` β€” Filter operator - **`property` (required)** `string` β€” Property key (alphanumeric + underscores, max 128 chars) - **`value` (required)** `string` β€” Filter value - **`breakdown`** `string` β€” Optional property key to segment funnel by (e.g. 'variant', 'country'). Extracted from step 1 events only. - **`breakdown_limit`** `number`, default: `10` β€” Max breakdown groups, ordered by step 1 users descending (1-50, default 10) - **`conversion_window_hours`** `number`, default: `168` β€” Max hours from step 1 entry to final step (1-8760, default 168 = 7 days) - **`count_by`** `string`, possible values: `"user_id", "session_id"`, default: `"user_id"` β€” Count by unique users or sessions - **`since`** `string`, default: `"30d"` β€” Lookback period (ISO date or shorthand like '30d'). Default: 30d **Example:** ```json { "project": "my-site", "steps": [ { "event": "page_view", "filters": [ { "property": "path", "op": "eq", "value": "/pricing" } ] } ], "conversion_window_hours": 168, "since": "30d", "count_by": "user_id", "breakdown": "country", "breakdown_limit": 10 } ``` #### Responses ##### Status: 200 Funnel analysis results ###### Content-Type: application/json - **`breakdowns`** `array` β€” Per-group funnel results (only present when \`breakdown\` param is set). Ordered by step 1 users descending. **Items:** - **`overall_conversion_rate`** `number` β€” End-to-end conversion for this group - **`steps`** `array` β€” Same shape as top-level steps array **Items:** - **`avg_time_to_next_ms`** `number | null` - **`conversion_rate`** `number` - **`drop_off_rate`** `number` - **`event`** `string` - **`step`** `integer` - **`users`** `integer` - **`value`** `string | null` β€” Breakdown property value (null for events missing the property) - **`overall_conversion_rate`** `number` β€” Fraction of step 1 users that completed the final step - **`project_context`** `object` - **`activation_events`** `array`, default: `[]` β€” Event names that define activation or the main success path. **Items:** `string` - **`annotations`** `array`, default: `[]` β€” Major date annotations. Project-scoped analytics responses include only annotations inside the requested date range plus one day before and after. **Items:** - **`occurred_at` (required)** `string`, format: `date-time` β€” ISO-8601 datetime when a major product change happened. Stored as a UTC ISO string. - **`title` (required)** `string` β€” Short annotation title for a meaningful product, pricing, release, landing-page, onboarding, feature, or experiment change. - **`note`** `string` β€” Optional short note. Do not store commit logs, PII, secrets, or long release notes. - **`glossary`** `array`, default: `[]` **Items:** - **`definition` (required)** `string` β€” Short meaning that helps an agent interpret analytics results. - **`event_name` (required)** `string` β€” Event name this glossary entry explains. Use \`/properties\` or \`/properties/received\` to inspect current project event names before updating. - **`term` (required)** `string` β€” Human or product term for the event. - **`goals`** `array`, default: `[]` **Items:** `string` - **`steps`** `array` **Items:** - **`avg_time_to_next_ms`** `number | null` β€” Average time in ms from this step to the next step (null for last step) - **`conversion_rate`** `number` β€” Fraction of users from previous step that reached this step (step 1 is always 1.0) - **`drop_off_rate`** `number` β€” Fraction of users lost from previous step (step 1 is always 0) - **`event`** `string` - **`step`** `integer` - **`users`** `integer` β€” Number of users (or sessions) that reached this step **Example:** ```json { "project_context": { "goals": [ "Increase activated Agent Analytics accounts" ], "activation_events": [ "signup_completed", "project_created", "first_event_received" ], "glossary": [], "annotations": [] }, "steps": [ { "step": 1, "event": "page_view", "users": 500, "conversion_rate": 0.6, "drop_off_rate": 0.4, "avg_time_to_next_ms": 3600000 } ], "overall_conversion_rate": 0.12, "breakdowns": [ { "value": "US", "steps": [ { "step": 1, "event": "", "users": 1, "conversion_rate": 1, "drop_off_rate": 1, "avg_time_to_next_ms": null } ], "overall_conversion_rate": 0.15 } ] } ``` ##### Status: 400 Validation error (invalid steps, filters, window, or count\_by) ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 401 Missing or invalid API key ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 404 Project not found ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Cohort retention analysis - **Method:**Β `GET` - **Path:**Β `/retention` - **Tags:**Β Analytics Track what percentage of users return over time using cohort analysis. "Of users who first appeared in week X, what % came back in subsequent weeks?" By default uses session-based retention β€” a user is "retained" if they have any return visit (session) in a subsequent period. When `event` is specified, switches to event-based retention and only counts that specific event for first-seen and return. Capped at 10,000 users per query. Older cohorts appear first (top-down). **CLI:** `npx --yes @agent-analytics/cli@0.5.34 retention my-site --period week --cohorts 8` #### Responses ##### Status: 200 Cohort retention data ###### Content-Type: application/json - **`average_rates`** `array` β€” Weighted average retention rate per period offset (weighted by cohort size) **Items:** `number` - **`cohorts`** `array` **Items:** - **`date`** `string`, format: `date` β€” Start date of this cohort period - **`rates`** `array` β€” Retention rate per period (retained\[i] / users, rounded to 3 decimals) **Items:** `number` - **`retained`** `array` β€” Users active in each subsequent period (index 0 = full cohort) **Items:** `integer` - **`users`** `integer` β€” Number of users who first appeared in this period - **`period`** `string`, possible values: `"day", "week", "month"` - **`project_context`** `object` - **`activation_events`** `array`, default: `[]` β€” Event names that define activation or the main success path. **Items:** `string` - **`annotations`** `array`, default: `[]` β€” Major date annotations. Project-scoped analytics responses include only annotations inside the requested date range plus one day before and after. **Items:** - **`occurred_at` (required)** `string`, format: `date-time` β€” ISO-8601 datetime when a major product change happened. Stored as a UTC ISO string. - **`title` (required)** `string` β€” Short annotation title for a meaningful product, pricing, release, landing-page, onboarding, feature, or experiment change. - **`note`** `string` β€” Optional short note. Do not store commit logs, PII, secrets, or long release notes. - **`glossary`** `array`, default: `[]` **Items:** - **`definition` (required)** `string` β€” Short meaning that helps an agent interpret analytics results. - **`event_name` (required)** `string` β€” Event name this glossary entry explains. Use \`/properties\` or \`/properties/received\` to inspect current project event names before updating. - **`term` (required)** `string` β€” Human or product term for the event. - **`goals`** `array`, default: `[]` **Items:** `string` - **`users_analyzed`** `integer` β€” Total users across all cohorts (capped at 10K per query) **Example:** ```json { "project_context": { "goals": [ "Increase activated Agent Analytics accounts" ], "activation_events": [ "signup_completed", "project_created", "first_event_received" ], "glossary": [], "annotations": [] }, "period": "week", "cohorts": [ { "date": "2026-01-27", "users": 142, "retained": [ 142, 64, 55, 46 ], "rates": [ 1, 0.451, 0.387, 0.324 ] } ], "average_rates": [ 1, 0.441, 0.373, 0.324 ], "users_analyzed": 560 } ``` ##### Status: 400 Invalid period or cohorts value ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 401 Missing or invalid API key ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 404 Project not found ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Live event stream (SSE) - **Method:**Β `GET` - **Path:**Β `/stream` - **Tags:**Β Streaming Server-Sent Events stream of real-time events as they arrive. Events are delivered as `event: track` SSE messages. Optionally filter by event name and/or property values. The stream sends a `:heartbeat` comment every 30 seconds as a keepalive. Auto-disconnects after 30 minutes of no matching events. Supports agent-session bearer auth (`Authorization: Bearer aas_...`) or API key auth (`X-API-Key: aak_...`). **curl example:** ```bash curl -N "https://api.agentanalytics.sh/stream?project=my-site&events=page_view,signup" \ -H "Authorization: Bearer aas_..." ``` #### Responses ##### Status: 200 SSE event stream ###### Content-Type: text/event-stream `string` β€” SSE stream with events: - \`event: connected\` β€” sent once on connection with active filters - \`event: track\` β€” each matching event with \`id\` for reconnection - \`:heartbeat\` β€” keepalive comment every 30s **Example:** ```json true ``` ##### Status: 401 Missing or invalid account auth ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 404 Project not found ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 429 Too many concurrent streams (max 10 per account) ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Live snapshot (real-time) - **Method:**Β `GET` - **Path:**Β `/live` - **Tags:**Β Streaming Returns a point-in-time snapshot of active visitors, sessions, events per minute, top pages, top events, and recent events. Reads from an in-memory ring buffer β€” no D1 query. Data is available only while events are being streamed (the ring buffer evicts events older than 5 minutes). Supports agent-session bearer auth (`Authorization: Bearer aas_...`) or API key auth (`X-API-Key: aak_...`). **curl example:** ```bash curl "https://api.agentanalytics.sh/live?project=my-site&window=60" \ -H "Authorization: Bearer aas_..." ``` #### Responses ##### Status: 200 Live snapshot ###### Content-Type: application/json - **`active_sessions`** `integer` β€” Unique session\_ids in the time window - **`active_visitors`** `integer` β€” Unique user\_ids in the time window - **`events_per_minute`** `integer` - **`project`** `string` - **`project_context`** `object` - **`activation_events`** `array`, default: `[]` β€” Event names that define activation or the main success path. **Items:** `string` - **`annotations`** `array`, default: `[]` β€” Major date annotations. Project-scoped analytics responses include only annotations inside the requested date range plus one day before and after. **Items:** - **`occurred_at` (required)** `string`, format: `date-time` β€” ISO-8601 datetime when a major product change happened. Stored as a UTC ISO string. - **`title` (required)** `string` β€” Short annotation title for a meaningful product, pricing, release, landing-page, onboarding, feature, or experiment change. - **`note`** `string` β€” Optional short note. Do not store commit logs, PII, secrets, or long release notes. - **`glossary`** `array`, default: `[]` **Items:** - **`definition` (required)** `string` β€” Short meaning that helps an agent interpret analytics results. - **`event_name` (required)** `string` β€” Event name this glossary entry explains. Use \`/properties\` or \`/properties/received\` to inspect current project event names before updating. - **`term` (required)** `string` β€” Human or product term for the event. - **`goals`** `array`, default: `[]` **Items:** `string` - **`recent_events`** `array` β€” Last 10 events, newest first **Items:** - **`event`** `string` - **`properties`** `object | null` - **`timestamp`** `number` - **`user_id`** `string | null` - **`timestamp`** `number` - **`top_events`** `array` **Items:** - **`count`** `integer` - **`event`** `string` - **`top_pages`** `array` **Items:** - **`path`** `string` - **`visitors`** `integer` - **`window_seconds`** `integer` **Example:** ```json { "project": "my-site", "project_context": { "goals": [ "Increase activated Agent Analytics accounts" ], "activation_events": [ "signup_completed", "project_created", "first_event_received" ], "glossary": [], "annotations": [] }, "window_seconds": 60, "timestamp": 1708000060000, "active_visitors": 12, "active_sessions": 8, "events_per_minute": 47, "top_pages": [ { "path": "/", "visitors": 5 } ], "top_events": [ { "event": "page_view", "count": 32 } ], "recent_events": [ { "event": "", "properties": null, "user_id": null, "timestamp": 1 } ] } ``` ##### Status: 401 Missing or invalid account auth ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 404 Project not found ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Create public landing-page website analysis preview - **Method:**Β `POST` - **Path:**Β `/website-scans` - **Tags:**Β Website Analysis Creates the public landing-page website analysis preview. Requests are root-domain only and return a preview plus a one-analysis `rst_*` resume token. They do not create `aas_*` agent sessions. Public product copy should frame this as the fastest path to useful analytics, not as a generic audit. Recommendations include implementation hints that map to supported tracker.js capabilities instead of duplicate custom events for automatic signals. #### Request Body ##### Content-Type: application/json - **`url` (required)** `string` β€” Website URL to analyze. Anonymous requests are normalized to the root domain. - **`full`** `boolean`, default: `false` β€” Request full analysis. Requires account auth. - **`mode`** `string`, possible values: `"preview", "full"` β€” Alternative way to request preview or full analysis. - **`project`** `string` β€” Project name or id. Required for signed-in portal scans and full analyses; the URL hostname must match the project's configured \`allowed\_origins\`. **Example:** ```json { "url": "https://example.com/pricing", "full": false, "mode": "preview", "project": "my-site" } ``` #### Responses ##### Status: 200 Preview or full website analysis ###### Content-Type: application/json - **`agent_handoff`** `object` - **`analysis_id`** `string` - **`label`** `string` - **`prompt`** `string` - **`resume_token`** `string | null` - **`analysis_id`** `string` - **`cached`** `boolean` - **`hostname`** `string` - **`mode`** `string` - **`normalized_url`** `string` - **`ok`** `boolean` - **`preview`** `object` β€” Decision-oriented instrumentation plan. Preview responses cap \`minimum\_viable\_instrumentation\` at 3-5 events; full results cap it at 5-8 events. Recommendations are tracker-aware and should not spend custom event slots on automatic page\_view, attribution, device, geography, session, or visitor fields. - **`advanced_tracking_later`** `array` β€” Agent Analytics tracker capabilities to consider after the first useful page event is installed. **Items:** - **`capability`** `string` - **`implementation_hint`** `string` - **`why`** `string` - **`after_install_agent_behavior`** `array` **Items:** `string` - **`analytics_detected`** `object` β€” Supporting context only; the recommendation does not lead with detected providers. - **`business_events_later`** `array` β€” Valuable inferred product, backend, or post-signup events that are not part of the first supplied-page install list. **Items:** - **`event`** `string` - **`where_to_instrument`** `string` - **`why`** `string` - **`current_blindspots`** `array` **Items:** `string` - **`framing`** `string` - **`goal_driven_funnels`** `array` **Items:** - **`bottleneck_detection`** `string` - **`decision`** `string` - **`name`** `string` - **`steps`** `array` **Items:** `string` - **`hostname`** `string` - **`minimum_viable_instrumentation`** `array` **Items:** - **`agent_capability_after_install` (required)** `string` - **`current_blindspot` (required)** `string` - **`event` (required)** `string` β€” Stable snake\_case custom event name. Recommendations should not duplicate automatic tracker signals such as page\_view. - **`implementation_hint` (required)** `string` β€” Tracker-aware implementation guidance, for example data-aa-event attributes, data-aa-impression attributes, window\.aa.track(...), server-side tracking for durable outcomes, aa.identify()/aa.set(...) after auth, or script opt-ins when they unlock a concrete decision. - **`priority` (required)** `integer` - **`properties` (required)** `array` β€” Practical property names to capture with the event. Automatic tracker properties such as path, referrer, UTMs, device fields, country, session IDs, and first-touch attribution are already present on every event. **Items:** `string` - **`unlocks_questions` (required)** `array` **Items:** `string` - **`why_this_matters_now` (required)** `string` - **`normalized_url`** `string` - **`not_needed_yet`** `array` **Items:** - **`event`** `string` - **`reason`** `string` - **`revisit_when`** `string` - **`suggested_ab_tests`** `array` β€” Compact experiment ideas tied to the recommended page UI events. **Items:** - **`hypothesis`** `string` - **`name`** `string` - **`success_event`** `string` - **`variants`** `array` **Items:** `string` - **`result`** `object` β€” Decision-oriented instrumentation plan. Preview responses cap \`minimum\_viable\_instrumentation\` at 3-5 events; full results cap it at 5-8 events. Recommendations are tracker-aware and should not spend custom event slots on automatic page\_view, attribution, device, geography, session, or visitor fields. - **`advanced_tracking_later`** `array` β€” Agent Analytics tracker capabilities to consider after the first useful page event is installed. **Items:** - **`capability`** `string` - **`implementation_hint`** `string` - **`why`** `string` - **`after_install_agent_behavior`** `array` **Items:** `string` - **`analytics_detected`** `object` β€” Supporting context only; the recommendation does not lead with detected providers. - **`business_events_later`** `array` β€” Valuable inferred product, backend, or post-signup events that are not part of the first supplied-page install list. **Items:** - **`event`** `string` - **`where_to_instrument`** `string` - **`why`** `string` - **`current_blindspots`** `array` **Items:** `string` - **`framing`** `string` - **`goal_driven_funnels`** `array` **Items:** - **`bottleneck_detection`** `string` - **`decision`** `string` - **`name`** `string` - **`steps`** `array` **Items:** `string` - **`hostname`** `string` - **`minimum_viable_instrumentation`** `array` **Items:** - **`agent_capability_after_install` (required)** `string` - **`current_blindspot` (required)** `string` - **`event` (required)** `string` β€” Stable snake\_case custom event name. Recommendations should not duplicate automatic tracker signals such as page\_view. - **`implementation_hint` (required)** `string` β€” Tracker-aware implementation guidance, for example data-aa-event attributes, data-aa-impression attributes, window\.aa.track(...), server-side tracking for durable outcomes, aa.identify()/aa.set(...) after auth, or script opt-ins when they unlock a concrete decision. - **`priority` (required)** `integer` - **`properties` (required)** `array` β€” Practical property names to capture with the event. Automatic tracker properties such as path, referrer, UTMs, device fields, country, session IDs, and first-touch attribution are already present on every event. **Items:** `string` - **`unlocks_questions` (required)** `array` **Items:** `string` - **`why_this_matters_now` (required)** `string` - **`normalized_url`** `string` - **`not_needed_yet`** `array` **Items:** - **`event`** `string` - **`reason`** `string` - **`revisit_when`** `string` - **`suggested_ab_tests`** `array` β€” Compact experiment ideas tied to the recommended page UI events. **Items:** - **`hypothesis`** `string` - **`name`** `string` - **`success_event`** `string` - **`variants`** `array` **Items:** `string` - **`resume_token`** `string` β€” Present only when creating a new anonymous preview. Store the token securely; the server stores only its hash. - **`status`** `string`, possible values: `"pending", "running", "succeeded", "failed"` **Example:** ```json { "ok": true, "analysis_id": "scan_...", "status": "succeeded", "mode": "anonymous_preview", "normalized_url": "https://example.com/", "hostname": "example.com", "cached": true, "resume_token": "rst_...", "preview": { "framing": "fastest_path_to_useful_analytics", "normalized_url": "https://example.com/", "hostname": "example.com", "current_blindspots": [ "" ], "minimum_viable_instrumentation": [ { "event": "signup_started", "priority": 1, "why_this_matters_now": "This marks the moment intent becomes commitment.", "current_blindspot": "You cannot see whether CTA clicks turn into signup attempts.", "unlocks_questions": [ "Which pages create signup starts?", "Where does signup intent drop?" ], "agent_capability_after_install": "Your agent can detect where intent drops before account creation.", "properties": [ "page_path", "entry_source", "auth_method" ], "implementation_hint": "" } ], "not_needed_yet": [ { "event": "", "reason": "", "revisit_when": "" } ], "goal_driven_funnels": [ { "name": "", "steps": [ "" ], "decision": "", "bottleneck_detection": "" } ], "after_install_agent_behavior": [ "" ], "business_events_later": [ { "event": "", "why": "", "where_to_instrument": "" } ], "advanced_tracking_later": [ { "capability": "data-aa-impression", "why": "", "implementation_hint": "" } ], "suggested_ab_tests": [ { "name": "", "hypothesis": "", "variants": [ "" ], "success_event": "" } ], "analytics_detected": {} }, "result": { "framing": "fastest_path_to_useful_analytics", "normalized_url": "https://example.com/", "hostname": "example.com", "current_blindspots": [ "" ], "minimum_viable_instrumentation": [ { "event": "signup_started", "priority": 1, "why_this_matters_now": "This marks the moment intent becomes commitment.", "current_blindspot": "You cannot see whether CTA clicks turn into signup attempts.", "unlocks_questions": [ "Which pages create signup starts?", "Where does signup intent drop?" ], "agent_capability_after_install": "Your agent can detect where intent drops before account creation.", "properties": [ "page_path", "entry_source", "auth_method" ], "implementation_hint": "" } ], "not_needed_yet": [ { "event": "", "reason": "", "revisit_when": "" } ], "goal_driven_funnels": [ { "name": "", "steps": [ "" ], "decision": "", "bottleneck_detection": "" } ], "after_install_agent_behavior": [ "" ], "business_events_later": [ { "event": "", "why": "", "where_to_instrument": "" } ], "advanced_tracking_later": [ { "capability": "data-aa-impression", "why": "", "implementation_hint": "" } ], "suggested_ab_tests": [ { "name": "", "hypothesis": "", "variants": [ "" ], "success_event": "" } ], "analytics_detected": {} }, "agent_handoff": { "label": "Give your agent analytics judgment", "analysis_id": "", "resume_token": null, "prompt": "" } } ``` ##### Status: 400 Invalid or unsafe website URL, missing project context, or project/domain mismatch ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 401 Login required for full analysis ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 429 Anonymous analyzer busy, cooldown active, or quota reached ###### Content-Type: application/json **All of:** - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message * **`retry_after_seconds`** `integer` **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required", "retry_after_seconds": 30 } ``` ##### Status: 502 Downstream scanner failed safely ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Create authenticated npx website analysis - **Method:**Β `POST` - **Path:**Β `/cli/website-scans` - **Tags:**Β Website Analysis Creates an authenticated website analysis for the npx CLI. This endpoint never falls back to the public Turnstile-protected landing-page scan path. Normal accounts must include `project`, and the analyzed hostname must match that project's configured `allowed_origins`. Complimentary Pro accounts identified by `entitlement_source='complimentary'` may omit `project`, may scan outside a requested project's origins, and are not subject to signed-in scan quotas or provider daily caps. #### Request Body ##### Content-Type: application/json - **`url` (required)** `string` β€” Website URL to analyze. Anonymous requests are normalized to the root domain. - **`full`** `boolean`, default: `false` β€” Request full analysis. Requires account auth. - **`mode`** `string`, possible values: `"preview", "full"` β€” Alternative way to request preview or full analysis. - **`project`** `string` β€” Project name or id. Required for signed-in portal scans and full analyses; the URL hostname must match the project's configured \`allowed\_origins\`. **Example:** ```json { "url": "https://example.com/pricing", "full": false, "mode": "preview", "project": "my-site" } ``` #### Responses ##### Status: 200 Preview or full website analysis ###### Content-Type: application/json - **`agent_handoff`** `object` - **`analysis_id`** `string` - **`label`** `string` - **`prompt`** `string` - **`resume_token`** `string | null` - **`analysis_id`** `string` - **`cached`** `boolean` - **`hostname`** `string` - **`mode`** `string` - **`normalized_url`** `string` - **`ok`** `boolean` - **`preview`** `object` β€” Decision-oriented instrumentation plan. Preview responses cap \`minimum\_viable\_instrumentation\` at 3-5 events; full results cap it at 5-8 events. Recommendations are tracker-aware and should not spend custom event slots on automatic page\_view, attribution, device, geography, session, or visitor fields. - **`advanced_tracking_later`** `array` β€” Agent Analytics tracker capabilities to consider after the first useful page event is installed. **Items:** - **`capability`** `string` - **`implementation_hint`** `string` - **`why`** `string` - **`after_install_agent_behavior`** `array` **Items:** `string` - **`analytics_detected`** `object` β€” Supporting context only; the recommendation does not lead with detected providers. - **`business_events_later`** `array` β€” Valuable inferred product, backend, or post-signup events that are not part of the first supplied-page install list. **Items:** - **`event`** `string` - **`where_to_instrument`** `string` - **`why`** `string` - **`current_blindspots`** `array` **Items:** `string` - **`framing`** `string` - **`goal_driven_funnels`** `array` **Items:** - **`bottleneck_detection`** `string` - **`decision`** `string` - **`name`** `string` - **`steps`** `array` **Items:** `string` - **`hostname`** `string` - **`minimum_viable_instrumentation`** `array` **Items:** - **`agent_capability_after_install` (required)** `string` - **`current_blindspot` (required)** `string` - **`event` (required)** `string` β€” Stable snake\_case custom event name. Recommendations should not duplicate automatic tracker signals such as page\_view. - **`implementation_hint` (required)** `string` β€” Tracker-aware implementation guidance, for example data-aa-event attributes, data-aa-impression attributes, window\.aa.track(...), server-side tracking for durable outcomes, aa.identify()/aa.set(...) after auth, or script opt-ins when they unlock a concrete decision. - **`priority` (required)** `integer` - **`properties` (required)** `array` β€” Practical property names to capture with the event. Automatic tracker properties such as path, referrer, UTMs, device fields, country, session IDs, and first-touch attribution are already present on every event. **Items:** `string` - **`unlocks_questions` (required)** `array` **Items:** `string` - **`why_this_matters_now` (required)** `string` - **`normalized_url`** `string` - **`not_needed_yet`** `array` **Items:** - **`event`** `string` - **`reason`** `string` - **`revisit_when`** `string` - **`suggested_ab_tests`** `array` β€” Compact experiment ideas tied to the recommended page UI events. **Items:** - **`hypothesis`** `string` - **`name`** `string` - **`success_event`** `string` - **`variants`** `array` **Items:** `string` - **`result`** `object` β€” Decision-oriented instrumentation plan. Preview responses cap \`minimum\_viable\_instrumentation\` at 3-5 events; full results cap it at 5-8 events. Recommendations are tracker-aware and should not spend custom event slots on automatic page\_view, attribution, device, geography, session, or visitor fields. - **`advanced_tracking_later`** `array` β€” Agent Analytics tracker capabilities to consider after the first useful page event is installed. **Items:** - **`capability`** `string` - **`implementation_hint`** `string` - **`why`** `string` - **`after_install_agent_behavior`** `array` **Items:** `string` - **`analytics_detected`** `object` β€” Supporting context only; the recommendation does not lead with detected providers. - **`business_events_later`** `array` β€” Valuable inferred product, backend, or post-signup events that are not part of the first supplied-page install list. **Items:** - **`event`** `string` - **`where_to_instrument`** `string` - **`why`** `string` - **`current_blindspots`** `array` **Items:** `string` - **`framing`** `string` - **`goal_driven_funnels`** `array` **Items:** - **`bottleneck_detection`** `string` - **`decision`** `string` - **`name`** `string` - **`steps`** `array` **Items:** `string` - **`hostname`** `string` - **`minimum_viable_instrumentation`** `array` **Items:** - **`agent_capability_after_install` (required)** `string` - **`current_blindspot` (required)** `string` - **`event` (required)** `string` β€” Stable snake\_case custom event name. Recommendations should not duplicate automatic tracker signals such as page\_view. - **`implementation_hint` (required)** `string` β€” Tracker-aware implementation guidance, for example data-aa-event attributes, data-aa-impression attributes, window\.aa.track(...), server-side tracking for durable outcomes, aa.identify()/aa.set(...) after auth, or script opt-ins when they unlock a concrete decision. - **`priority` (required)** `integer` - **`properties` (required)** `array` β€” Practical property names to capture with the event. Automatic tracker properties such as path, referrer, UTMs, device fields, country, session IDs, and first-touch attribution are already present on every event. **Items:** `string` - **`unlocks_questions` (required)** `array` **Items:** `string` - **`why_this_matters_now` (required)** `string` - **`normalized_url`** `string` - **`not_needed_yet`** `array` **Items:** - **`event`** `string` - **`reason`** `string` - **`revisit_when`** `string` - **`suggested_ab_tests`** `array` β€” Compact experiment ideas tied to the recommended page UI events. **Items:** - **`hypothesis`** `string` - **`name`** `string` - **`success_event`** `string` - **`variants`** `array` **Items:** `string` - **`resume_token`** `string` β€” Present only when creating a new anonymous preview. Store the token securely; the server stores only its hash. - **`status`** `string`, possible values: `"pending", "running", "succeeded", "failed"` **Example:** ```json { "ok": true, "analysis_id": "scan_...", "status": "succeeded", "mode": "anonymous_preview", "normalized_url": "https://example.com/", "hostname": "example.com", "cached": true, "resume_token": "rst_...", "preview": { "framing": "fastest_path_to_useful_analytics", "normalized_url": "https://example.com/", "hostname": "example.com", "current_blindspots": [ "" ], "minimum_viable_instrumentation": [ { "event": "signup_started", "priority": 1, "why_this_matters_now": "This marks the moment intent becomes commitment.", "current_blindspot": "You cannot see whether CTA clicks turn into signup attempts.", "unlocks_questions": [ "Which pages create signup starts?", "Where does signup intent drop?" ], "agent_capability_after_install": "Your agent can detect where intent drops before account creation.", "properties": [ "page_path", "entry_source", "auth_method" ], "implementation_hint": "" } ], "not_needed_yet": [ { "event": "", "reason": "", "revisit_when": "" } ], "goal_driven_funnels": [ { "name": "", "steps": [ "" ], "decision": "", "bottleneck_detection": "" } ], "after_install_agent_behavior": [ "" ], "business_events_later": [ { "event": "", "why": "", "where_to_instrument": "" } ], "advanced_tracking_later": [ { "capability": "data-aa-impression", "why": "", "implementation_hint": "" } ], "suggested_ab_tests": [ { "name": "", "hypothesis": "", "variants": [ "" ], "success_event": "" } ], "analytics_detected": {} }, "result": { "framing": "fastest_path_to_useful_analytics", "normalized_url": "https://example.com/", "hostname": "example.com", "current_blindspots": [ "" ], "minimum_viable_instrumentation": [ { "event": "signup_started", "priority": 1, "why_this_matters_now": "This marks the moment intent becomes commitment.", "current_blindspot": "You cannot see whether CTA clicks turn into signup attempts.", "unlocks_questions": [ "Which pages create signup starts?", "Where does signup intent drop?" ], "agent_capability_after_install": "Your agent can detect where intent drops before account creation.", "properties": [ "page_path", "entry_source", "auth_method" ], "implementation_hint": "" } ], "not_needed_yet": [ { "event": "", "reason": "", "revisit_when": "" } ], "goal_driven_funnels": [ { "name": "", "steps": [ "" ], "decision": "", "bottleneck_detection": "" } ], "after_install_agent_behavior": [ "" ], "business_events_later": [ { "event": "", "why": "", "where_to_instrument": "" } ], "advanced_tracking_later": [ { "capability": "data-aa-impression", "why": "", "implementation_hint": "" } ], "suggested_ab_tests": [ { "name": "", "hypothesis": "", "variants": [ "" ], "success_event": "" } ], "analytics_detected": {} }, "agent_handoff": { "label": "Give your agent analytics judgment", "analysis_id": "", "resume_token": null, "prompt": "" } } ``` ##### Status: 400 Invalid or unsafe website URL, missing project context, or project/domain mismatch ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 401 Login required for authenticated website analysis ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 429 Scanner busy, provider cap active, or quota reached ###### Content-Type: application/json **All of:** - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message * **`retry_after_seconds`** `integer` **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required", "retry_after_seconds": 30 } ``` ##### Status: 502 Downstream scanner failed safely ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Resume a website analysis - **Method:**Β `GET` - **Path:**Β `/website-scans/{id}` - **Tags:**Β Website Analysis Returns a previously created analysis. Account owners can read their own analyses. Anonymous previews require the matching `resume_token` query parameter. #### Responses ##### Status: 200 Website analysis ###### Content-Type: application/json - **`agent_handoff`** `object` - **`analysis_id`** `string` - **`label`** `string` - **`prompt`** `string` - **`resume_token`** `string | null` - **`analysis_id`** `string` - **`cached`** `boolean` - **`hostname`** `string` - **`mode`** `string` - **`normalized_url`** `string` - **`ok`** `boolean` - **`preview`** `object` β€” Decision-oriented instrumentation plan. Preview responses cap \`minimum\_viable\_instrumentation\` at 3-5 events; full results cap it at 5-8 events. Recommendations are tracker-aware and should not spend custom event slots on automatic page\_view, attribution, device, geography, session, or visitor fields. - **`advanced_tracking_later`** `array` β€” Agent Analytics tracker capabilities to consider after the first useful page event is installed. **Items:** - **`capability`** `string` - **`implementation_hint`** `string` - **`why`** `string` - **`after_install_agent_behavior`** `array` **Items:** `string` - **`analytics_detected`** `object` β€” Supporting context only; the recommendation does not lead with detected providers. - **`business_events_later`** `array` β€” Valuable inferred product, backend, or post-signup events that are not part of the first supplied-page install list. **Items:** - **`event`** `string` - **`where_to_instrument`** `string` - **`why`** `string` - **`current_blindspots`** `array` **Items:** `string` - **`framing`** `string` - **`goal_driven_funnels`** `array` **Items:** - **`bottleneck_detection`** `string` - **`decision`** `string` - **`name`** `string` - **`steps`** `array` **Items:** `string` - **`hostname`** `string` - **`minimum_viable_instrumentation`** `array` **Items:** - **`agent_capability_after_install` (required)** `string` - **`current_blindspot` (required)** `string` - **`event` (required)** `string` β€” Stable snake\_case custom event name. Recommendations should not duplicate automatic tracker signals such as page\_view. - **`implementation_hint` (required)** `string` β€” Tracker-aware implementation guidance, for example data-aa-event attributes, data-aa-impression attributes, window\.aa.track(...), server-side tracking for durable outcomes, aa.identify()/aa.set(...) after auth, or script opt-ins when they unlock a concrete decision. - **`priority` (required)** `integer` - **`properties` (required)** `array` β€” Practical property names to capture with the event. Automatic tracker properties such as path, referrer, UTMs, device fields, country, session IDs, and first-touch attribution are already present on every event. **Items:** `string` - **`unlocks_questions` (required)** `array` **Items:** `string` - **`why_this_matters_now` (required)** `string` - **`normalized_url`** `string` - **`not_needed_yet`** `array` **Items:** - **`event`** `string` - **`reason`** `string` - **`revisit_when`** `string` - **`suggested_ab_tests`** `array` β€” Compact experiment ideas tied to the recommended page UI events. **Items:** - **`hypothesis`** `string` - **`name`** `string` - **`success_event`** `string` - **`variants`** `array` **Items:** `string` - **`result`** `object` β€” Decision-oriented instrumentation plan. Preview responses cap \`minimum\_viable\_instrumentation\` at 3-5 events; full results cap it at 5-8 events. Recommendations are tracker-aware and should not spend custom event slots on automatic page\_view, attribution, device, geography, session, or visitor fields. - **`advanced_tracking_later`** `array` β€” Agent Analytics tracker capabilities to consider after the first useful page event is installed. **Items:** - **`capability`** `string` - **`implementation_hint`** `string` - **`why`** `string` - **`after_install_agent_behavior`** `array` **Items:** `string` - **`analytics_detected`** `object` β€” Supporting context only; the recommendation does not lead with detected providers. - **`business_events_later`** `array` β€” Valuable inferred product, backend, or post-signup events that are not part of the first supplied-page install list. **Items:** - **`event`** `string` - **`where_to_instrument`** `string` - **`why`** `string` - **`current_blindspots`** `array` **Items:** `string` - **`framing`** `string` - **`goal_driven_funnels`** `array` **Items:** - **`bottleneck_detection`** `string` - **`decision`** `string` - **`name`** `string` - **`steps`** `array` **Items:** `string` - **`hostname`** `string` - **`minimum_viable_instrumentation`** `array` **Items:** - **`agent_capability_after_install` (required)** `string` - **`current_blindspot` (required)** `string` - **`event` (required)** `string` β€” Stable snake\_case custom event name. Recommendations should not duplicate automatic tracker signals such as page\_view. - **`implementation_hint` (required)** `string` β€” Tracker-aware implementation guidance, for example data-aa-event attributes, data-aa-impression attributes, window\.aa.track(...), server-side tracking for durable outcomes, aa.identify()/aa.set(...) after auth, or script opt-ins when they unlock a concrete decision. - **`priority` (required)** `integer` - **`properties` (required)** `array` β€” Practical property names to capture with the event. Automatic tracker properties such as path, referrer, UTMs, device fields, country, session IDs, and first-touch attribution are already present on every event. **Items:** `string` - **`unlocks_questions` (required)** `array` **Items:** `string` - **`why_this_matters_now` (required)** `string` - **`normalized_url`** `string` - **`not_needed_yet`** `array` **Items:** - **`event`** `string` - **`reason`** `string` - **`revisit_when`** `string` - **`suggested_ab_tests`** `array` β€” Compact experiment ideas tied to the recommended page UI events. **Items:** - **`hypothesis`** `string` - **`name`** `string` - **`success_event`** `string` - **`variants`** `array` **Items:** `string` - **`resume_token`** `string` β€” Present only when creating a new anonymous preview. Store the token securely; the server stores only its hash. - **`status`** `string`, possible values: `"pending", "running", "succeeded", "failed"` **Example:** ```json { "ok": true, "analysis_id": "scan_...", "status": "succeeded", "mode": "anonymous_preview", "normalized_url": "https://example.com/", "hostname": "example.com", "cached": true, "resume_token": "rst_...", "preview": { "framing": "fastest_path_to_useful_analytics", "normalized_url": "https://example.com/", "hostname": "example.com", "current_blindspots": [ "" ], "minimum_viable_instrumentation": [ { "event": "signup_started", "priority": 1, "why_this_matters_now": "This marks the moment intent becomes commitment.", "current_blindspot": "You cannot see whether CTA clicks turn into signup attempts.", "unlocks_questions": [ "Which pages create signup starts?", "Where does signup intent drop?" ], "agent_capability_after_install": "Your agent can detect where intent drops before account creation.", "properties": [ "page_path", "entry_source", "auth_method" ], "implementation_hint": "" } ], "not_needed_yet": [ { "event": "", "reason": "", "revisit_when": "" } ], "goal_driven_funnels": [ { "name": "", "steps": [ "" ], "decision": "", "bottleneck_detection": "" } ], "after_install_agent_behavior": [ "" ], "business_events_later": [ { "event": "", "why": "", "where_to_instrument": "" } ], "advanced_tracking_later": [ { "capability": "data-aa-impression", "why": "", "implementation_hint": "" } ], "suggested_ab_tests": [ { "name": "", "hypothesis": "", "variants": [ "" ], "success_event": "" } ], "analytics_detected": {} }, "result": { "framing": "fastest_path_to_useful_analytics", "normalized_url": "https://example.com/", "hostname": "example.com", "current_blindspots": [ "" ], "minimum_viable_instrumentation": [ { "event": "signup_started", "priority": 1, "why_this_matters_now": "This marks the moment intent becomes commitment.", "current_blindspot": "You cannot see whether CTA clicks turn into signup attempts.", "unlocks_questions": [ "Which pages create signup starts?", "Where does signup intent drop?" ], "agent_capability_after_install": "Your agent can detect where intent drops before account creation.", "properties": [ "page_path", "entry_source", "auth_method" ], "implementation_hint": "" } ], "not_needed_yet": [ { "event": "", "reason": "", "revisit_when": "" } ], "goal_driven_funnels": [ { "name": "", "steps": [ "" ], "decision": "", "bottleneck_detection": "" } ], "after_install_agent_behavior": [ "" ], "business_events_later": [ { "event": "", "why": "", "where_to_instrument": "" } ], "advanced_tracking_later": [ { "capability": "data-aa-impression", "why": "", "implementation_hint": "" } ], "suggested_ab_tests": [ { "name": "", "hypothesis": "", "variants": [ "" ], "success_event": "" } ], "analytics_detected": {} }, "agent_handoff": { "label": "Give your agent analytics judgment", "analysis_id": "", "resume_token": null, "prompt": "" } } ``` ##### Status: 404 Analysis not found or token/account mismatch ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Claim and upgrade an analysis - **Method:**Β `POST` - **Path:**Β `/website-scans/{id}/upgrade` - **Tags:**Β Website Analysis Claims an anonymous preview for the authenticated account and returns the full instrumentation plan. If the analysis is already owned by the account, the resume token is not required. Upgrades must include `project`; the analysis hostname must match that project's configured `allowed_origins`. A resume token alone cannot attach an analysis to a project. #### Request Body ##### Content-Type: application/json - **`project`** `string` β€” Required project name or id used while upgrading. The analysis hostname must match the project's configured \`allowed\_origins\`. - **`resume_token`** `string` β€” One-analysis \`rst\_\*\` resume token from an anonymous preview. **Example:** ```json { "resume_token": "rst_...", "project": "my-site" } ``` #### Responses ##### Status: 200 Full website analysis ###### Content-Type: application/json - **`agent_handoff`** `object` - **`analysis_id`** `string` - **`label`** `string` - **`prompt`** `string` - **`resume_token`** `string | null` - **`analysis_id`** `string` - **`cached`** `boolean` - **`hostname`** `string` - **`mode`** `string` - **`normalized_url`** `string` - **`ok`** `boolean` - **`preview`** `object` β€” Decision-oriented instrumentation plan. Preview responses cap \`minimum\_viable\_instrumentation\` at 3-5 events; full results cap it at 5-8 events. Recommendations are tracker-aware and should not spend custom event slots on automatic page\_view, attribution, device, geography, session, or visitor fields. - **`advanced_tracking_later`** `array` β€” Agent Analytics tracker capabilities to consider after the first useful page event is installed. **Items:** - **`capability`** `string` - **`implementation_hint`** `string` - **`why`** `string` - **`after_install_agent_behavior`** `array` **Items:** `string` - **`analytics_detected`** `object` β€” Supporting context only; the recommendation does not lead with detected providers. - **`business_events_later`** `array` β€” Valuable inferred product, backend, or post-signup events that are not part of the first supplied-page install list. **Items:** - **`event`** `string` - **`where_to_instrument`** `string` - **`why`** `string` - **`current_blindspots`** `array` **Items:** `string` - **`framing`** `string` - **`goal_driven_funnels`** `array` **Items:** - **`bottleneck_detection`** `string` - **`decision`** `string` - **`name`** `string` - **`steps`** `array` **Items:** `string` - **`hostname`** `string` - **`minimum_viable_instrumentation`** `array` **Items:** - **`agent_capability_after_install` (required)** `string` - **`current_blindspot` (required)** `string` - **`event` (required)** `string` β€” Stable snake\_case custom event name. Recommendations should not duplicate automatic tracker signals such as page\_view. - **`implementation_hint` (required)** `string` β€” Tracker-aware implementation guidance, for example data-aa-event attributes, data-aa-impression attributes, window\.aa.track(...), server-side tracking for durable outcomes, aa.identify()/aa.set(...) after auth, or script opt-ins when they unlock a concrete decision. - **`priority` (required)** `integer` - **`properties` (required)** `array` β€” Practical property names to capture with the event. Automatic tracker properties such as path, referrer, UTMs, device fields, country, session IDs, and first-touch attribution are already present on every event. **Items:** `string` - **`unlocks_questions` (required)** `array` **Items:** `string` - **`why_this_matters_now` (required)** `string` - **`normalized_url`** `string` - **`not_needed_yet`** `array` **Items:** - **`event`** `string` - **`reason`** `string` - **`revisit_when`** `string` - **`suggested_ab_tests`** `array` β€” Compact experiment ideas tied to the recommended page UI events. **Items:** - **`hypothesis`** `string` - **`name`** `string` - **`success_event`** `string` - **`variants`** `array` **Items:** `string` - **`result`** `object` β€” Decision-oriented instrumentation plan. Preview responses cap \`minimum\_viable\_instrumentation\` at 3-5 events; full results cap it at 5-8 events. Recommendations are tracker-aware and should not spend custom event slots on automatic page\_view, attribution, device, geography, session, or visitor fields. - **`advanced_tracking_later`** `array` β€” Agent Analytics tracker capabilities to consider after the first useful page event is installed. **Items:** - **`capability`** `string` - **`implementation_hint`** `string` - **`why`** `string` - **`after_install_agent_behavior`** `array` **Items:** `string` - **`analytics_detected`** `object` β€” Supporting context only; the recommendation does not lead with detected providers. - **`business_events_later`** `array` β€” Valuable inferred product, backend, or post-signup events that are not part of the first supplied-page install list. **Items:** - **`event`** `string` - **`where_to_instrument`** `string` - **`why`** `string` - **`current_blindspots`** `array` **Items:** `string` - **`framing`** `string` - **`goal_driven_funnels`** `array` **Items:** - **`bottleneck_detection`** `string` - **`decision`** `string` - **`name`** `string` - **`steps`** `array` **Items:** `string` - **`hostname`** `string` - **`minimum_viable_instrumentation`** `array` **Items:** - **`agent_capability_after_install` (required)** `string` - **`current_blindspot` (required)** `string` - **`event` (required)** `string` β€” Stable snake\_case custom event name. Recommendations should not duplicate automatic tracker signals such as page\_view. - **`implementation_hint` (required)** `string` β€” Tracker-aware implementation guidance, for example data-aa-event attributes, data-aa-impression attributes, window\.aa.track(...), server-side tracking for durable outcomes, aa.identify()/aa.set(...) after auth, or script opt-ins when they unlock a concrete decision. - **`priority` (required)** `integer` - **`properties` (required)** `array` β€” Practical property names to capture with the event. Automatic tracker properties such as path, referrer, UTMs, device fields, country, session IDs, and first-touch attribution are already present on every event. **Items:** `string` - **`unlocks_questions` (required)** `array` **Items:** `string` - **`why_this_matters_now` (required)** `string` - **`normalized_url`** `string` - **`not_needed_yet`** `array` **Items:** - **`event`** `string` - **`reason`** `string` - **`revisit_when`** `string` - **`suggested_ab_tests`** `array` β€” Compact experiment ideas tied to the recommended page UI events. **Items:** - **`hypothesis`** `string` - **`name`** `string` - **`success_event`** `string` - **`variants`** `array` **Items:** `string` - **`resume_token`** `string` β€” Present only when creating a new anonymous preview. Store the token securely; the server stores only its hash. - **`status`** `string`, possible values: `"pending", "running", "succeeded", "failed"` **Example:** ```json { "ok": true, "analysis_id": "scan_...", "status": "succeeded", "mode": "anonymous_preview", "normalized_url": "https://example.com/", "hostname": "example.com", "cached": true, "resume_token": "rst_...", "preview": { "framing": "fastest_path_to_useful_analytics", "normalized_url": "https://example.com/", "hostname": "example.com", "current_blindspots": [ "" ], "minimum_viable_instrumentation": [ { "event": "signup_started", "priority": 1, "why_this_matters_now": "This marks the moment intent becomes commitment.", "current_blindspot": "You cannot see whether CTA clicks turn into signup attempts.", "unlocks_questions": [ "Which pages create signup starts?", "Where does signup intent drop?" ], "agent_capability_after_install": "Your agent can detect where intent drops before account creation.", "properties": [ "page_path", "entry_source", "auth_method" ], "implementation_hint": "" } ], "not_needed_yet": [ { "event": "", "reason": "", "revisit_when": "" } ], "goal_driven_funnels": [ { "name": "", "steps": [ "" ], "decision": "", "bottleneck_detection": "" } ], "after_install_agent_behavior": [ "" ], "business_events_later": [ { "event": "", "why": "", "where_to_instrument": "" } ], "advanced_tracking_later": [ { "capability": "data-aa-impression", "why": "", "implementation_hint": "" } ], "suggested_ab_tests": [ { "name": "", "hypothesis": "", "variants": [ "" ], "success_event": "" } ], "analytics_detected": {} }, "result": { "framing": "fastest_path_to_useful_analytics", "normalized_url": "https://example.com/", "hostname": "example.com", "current_blindspots": [ "" ], "minimum_viable_instrumentation": [ { "event": "signup_started", "priority": 1, "why_this_matters_now": "This marks the moment intent becomes commitment.", "current_blindspot": "You cannot see whether CTA clicks turn into signup attempts.", "unlocks_questions": [ "Which pages create signup starts?", "Where does signup intent drop?" ], "agent_capability_after_install": "Your agent can detect where intent drops before account creation.", "properties": [ "page_path", "entry_source", "auth_method" ], "implementation_hint": "" } ], "not_needed_yet": [ { "event": "", "reason": "", "revisit_when": "" } ], "goal_driven_funnels": [ { "name": "", "steps": [ "" ], "decision": "", "bottleneck_detection": "" } ], "after_install_agent_behavior": [ "" ], "business_events_later": [ { "event": "", "why": "", "where_to_instrument": "" } ], "advanced_tracking_later": [ { "capability": "data-aa-impression", "why": "", "implementation_hint": "" } ], "suggested_ab_tests": [ { "name": "", "hypothesis": "", "variants": [ "" ], "success_event": "" } ], "analytics_detected": {} }, "agent_handoff": { "label": "Give your agent analytics judgment", "analysis_id": "", "resume_token": null, "prompt": "" } } ``` ##### Status: 401 Login required ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 404 Analysis not found or resume token mismatch ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 429 Monthly full-analysis quota reached ###### Content-Type: application/json **All of:** - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message * **`retry_after_seconds`** `integer` **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required", "retry_after_seconds": 30 } ``` ### Get project analytics context - **Method:**Β `GET` - **Path:**Β `/project-context` - **Tags:**Β Project Context Returns compact project goals, activation events, event-name glossary entries, and date annotations. Project-scoped analytics result endpoints include this data as `project_context` when it is non-empty. Direct `GET /project-context` returns all stored annotations. Analytics result endpoints include only annotations inside the requested analytics date range plus one day before and after. Use `/properties` or `/properties/received` to inspect current event names before building or refreshing glossary entries. #### Responses ##### Status: 200 Project context ###### Content-Type: application/json - **`project` (required)** `string` - **`project_context` (required)** `object` - **`activation_events`** `array`, default: `[]` β€” Event names that define activation or the main success path. **Items:** `string` - **`annotations`** `array`, default: `[]` β€” Major date annotations. Project-scoped analytics responses include only annotations inside the requested date range plus one day before and after. **Items:** - **`occurred_at` (required)** `string`, format: `date-time` β€” ISO-8601 datetime when a major product change happened. Stored as a UTC ISO string. - **`title` (required)** `string` β€” Short annotation title for a meaningful product, pricing, release, landing-page, onboarding, feature, or experiment change. - **`note`** `string` β€” Optional short note. Do not store commit logs, PII, secrets, or long release notes. - **`glossary`** `array`, default: `[]` **Items:** - **`definition` (required)** `string` β€” Short meaning that helps an agent interpret analytics results. - **`event_name` (required)** `string` β€” Event name this glossary entry explains. Use \`/properties\` or \`/properties/received\` to inspect current project event names before updating. - **`term` (required)** `string` β€” Human or product term for the event. - **`goals`** `array`, default: `[]` **Items:** `string` - **`project_id` (required)** `string` - **`ok`** `boolean` β€” Present on successful updates. **Example:** ```json { "ok": true, "project": "my-site", "project_id": "proj_123", "project_context": { "goals": [ "Increase activated Agent Analytics accounts" ], "activation_events": [ "signup_completed", "project_created", "first_event_received" ], "glossary": [], "annotations": [] } } ``` ##### Status: 401 Auth required ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 404 Project not found or unauthorized ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Set project analytics context - **Method:**Β `PUT` - **Path:**Β `/project-context` - **Tags:**Β Project Context Replaces the compact context for one project. Keep entries short because the context is returned with project-scoped analytics results for agents. The encoded JSON request body is limited to 512KB. Each glossary entry must include `event_name`; agents should use `/properties` or `/properties/received` first to discover current project event names. Annotations are for major product changes such as landing page, pricing, onboarding, feature, release, or experiment changes. Do not store git commit logs, PII, secrets, noisy edits, or long release notes. **CLI:** `npx --yes @agent-analytics/cli@0.5.34 context set my-site --json '{"goals":["Improve activation"],"activation_events":["signup_completed"],"glossary":[{"event_name":"signup_completed","term":"Signup","definition":"A verified account completed signup."}],"annotations":[{"occurred_at":"2026-04-25T13:00:00.000Z","title":"Changed pricing page offer","note":"Moved annual plan discount above the fold."}]}'` #### Request Body ##### Content-Type: application/json - **`project` (required)** `string` β€” Project name or ID. - **`activation_events`** `array`, default: `[]` β€” Event names that define activation or the main success path. **Items:** `string` - **`annotations`** `array`, default: `[]` β€” Major date annotations. Use sparingly for human-meaningful changes, not git commit logs. **Items:** - **`occurred_at` (required)** `string`, format: `date-time` β€” ISO-8601 datetime when a major product change happened. Stored as a UTC ISO string. - **`title` (required)** `string` β€” Short annotation title for a meaningful product, pricing, release, landing-page, onboarding, feature, or experiment change. - **`note`** `string` β€” Optional short note. Do not store commit logs, PII, secrets, or long release notes. - **`glossary`** `array`, default: `[]` **Items:** - **`definition` (required)** `string` β€” Short meaning that helps an agent interpret analytics results. - **`event_name` (required)** `string` β€” Event name this glossary entry explains. Use \`/properties\` or \`/properties/received\` to inspect current project event names before updating. - **`term` (required)** `string` β€” Human or product term for the event. - **`goals`** `array`, default: `[]` **Items:** `string` **Example:** ```json { "project": "my-site", "goals": [ "Increase activated Agent Analytics accounts" ], "activation_events": [ "signup_completed", "project_created", "first_event_received" ], "glossary": [], "annotations": [] } ``` #### Responses ##### Status: 200 Project context updated ###### Content-Type: application/json - **`project` (required)** `string` - **`project_context` (required)** `object` - **`activation_events`** `array`, default: `[]` β€” Event names that define activation or the main success path. **Items:** `string` - **`annotations`** `array`, default: `[]` β€” Major date annotations. Project-scoped analytics responses include only annotations inside the requested date range plus one day before and after. **Items:** - **`occurred_at` (required)** `string`, format: `date-time` β€” ISO-8601 datetime when a major product change happened. Stored as a UTC ISO string. - **`title` (required)** `string` β€” Short annotation title for a meaningful product, pricing, release, landing-page, onboarding, feature, or experiment change. - **`note`** `string` β€” Optional short note. Do not store commit logs, PII, secrets, or long release notes. - **`glossary`** `array`, default: `[]` **Items:** - **`definition` (required)** `string` β€” Short meaning that helps an agent interpret analytics results. - **`event_name` (required)** `string` β€” Event name this glossary entry explains. Use \`/properties\` or \`/properties/received\` to inspect current project event names before updating. - **`term` (required)** `string` β€” Human or product term for the event. - **`goals`** `array`, default: `[]` **Items:** `string` - **`project_id` (required)** `string` - **`ok`** `boolean` β€” Present on successful updates. **Example:** ```json { "ok": true, "project": "my-site", "project_id": "proj_123", "project_context": { "goals": [ "Increase activated Agent Analytics accounts" ], "activation_events": [ "signup_completed", "project_created", "first_event_received" ], "glossary": [], "annotations": [] } } ``` ##### Status: 400 Invalid body or context limits exceeded ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 401 Auth required ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 404 Project not found or unauthorized ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Get account portfolio context - **Method:**Β `GET` - **Path:**Β `/portfolio-context` - **Tags:**Β Project Context Returns compact account-level goals, surface roles, shared milestones, and glossary for related projects. This is interpretive context only; it does not replace per-project activation definitions. #### Responses ##### Status: 200 Portfolio context ###### Content-Type: application/json - **`account_id` (required)** `string` - **`portfolio_context` (required)** `object` - **`glossary`** `array`, default: `[]` **Items:** - **`definition`** `string` - **`term`** `string` - **`goals`** `array`, default: `[]` **Items:** `string` - **`shared_milestones`** `array`, default: `[]` **Items:** `string` - **`surface_roles`** `array`, default: `[]` **Items:** - **`project`** `string` - **`role`** `string` - **`ok`** `boolean` β€” Present on successful updates. **Example:** ```json { "ok": true, "account_id": "acc_123", "portfolio_context": { "goals": [ "Increase qualified users who reach setup" ], "surface_roles": [], "shared_milestones": [ "qualified_click_to_product", "signup", "project_created" ], "glossary": [] } } ``` ##### Status: 401 Auth required ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Set account portfolio context - **Method:**Β `PUT` - **Path:**Β `/portfolio-context` - **Tags:**Β Project Context Replaces account-level portfolio context. Use this for shared goals and surface roles across related projects; do not store PII, secrets, or long release notes. #### Request Body ##### Content-Type: application/json - **`glossary`** `array`, default: `[]` **Items:** - **`definition`** `string` - **`term`** `string` - **`goals`** `array`, default: `[]` **Items:** `string` - **`shared_milestones`** `array`, default: `[]` **Items:** `string` - **`surface_roles`** `array`, default: `[]` **Items:** - **`project`** `string` - **`role`** `string` **Example:** ```json { "goals": [ "Increase qualified users who reach setup" ], "surface_roles": [], "shared_milestones": [ "qualified_click_to_product", "signup", "project_created" ], "glossary": [] } ``` #### Responses ##### Status: 200 Portfolio context updated ###### Content-Type: application/json - **`account_id` (required)** `string` - **`portfolio_context` (required)** `object` - **`glossary`** `array`, default: `[]` **Items:** - **`definition`** `string` - **`term`** `string` - **`goals`** `array`, default: `[]` **Items:** `string` - **`shared_milestones`** `array`, default: `[]` **Items:** `string` - **`surface_roles`** `array`, default: `[]` **Items:** - **`project`** `string` - **`role`** `string` - **`ok`** `boolean` β€” Present on successful updates. **Example:** ```json { "ok": true, "account_id": "acc_123", "portfolio_context": { "goals": [ "Increase qualified users who reach setup" ], "surface_roles": [], "shared_milestones": [ "qualified_click_to_product", "signup", "project_created" ], "glossary": [] } } ``` ##### Status: 400 Invalid body or context limits exceeded ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 401 Auth required ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### List identity lookup portfolios - **Method:**Β `GET` - **Path:**Β `/portfolios` - **Tags:**Β Projects Lists named project portfolios used to scope privacy-first HMAC email lookup across related projects. #### Responses ##### Status: 200 Portfolio list ###### Content-Type: application/json - **`portfolios`** `array` **Items:** - **`account_id`** `string` - **`created_at`** `integer`, format: `int64` - **`id`** `string` - **`members`** `array` **Items:** - **`added_at`** `integer`, format: `int64` - **`project`** `string` - **`project_id`** `string` - **`name`** `string` - **`slug`** `string` - **`updated_at`** `integer`, format: `int64` **Example:** ```json { "portfolios": [ { "id": "pf_abc123", "account_id": "acc_123", "slug": "growth-system", "name": "Growth system", "created_at": 1, "updated_at": 1, "members": [ { "project_id": "", "project": "", "added_at": 1 } ] } ] } ``` ### Create an identity lookup portfolio - **Method:**Β `POST` - **Path:**Β `/portfolios` - **Tags:**Β Projects Creates a named portfolio and optional project membership list. Existing member projects require `allow_move: true` before they can be moved from another portfolio. #### Request Body ##### Content-Type: application/json - **`name` (required)** `string` - **`slug` (required)** `string` - **`allow_move`** `boolean`, default: `false` - **`projects`** `array` **Items:** `string` **Example:** ```json { "slug": "growth-system", "name": "Growth system", "projects": [ "agentanalytics.sh", "docs.agentanalytics.sh" ], "allow_move": false } ``` #### Responses ##### Status: 201 Portfolio created ###### Content-Type: application/json - **`ok`** `boolean` - **`portfolio`** `object` - **`account_id`** `string` - **`created_at`** `integer`, format: `int64` - **`id`** `string` - **`members`** `array` **Items:** - **`added_at`** `integer`, format: `int64` - **`project`** `string` - **`project_id`** `string` - **`name`** `string` - **`slug`** `string` - **`updated_at`** `integer`, format: `int64` **Example:** ```json { "ok": true, "portfolio": { "id": "pf_abc123", "account_id": "acc_123", "slug": "growth-system", "name": "Growth system", "created_at": 1, "updated_at": 1, "members": [ { "project_id": "", "project": "", "added_at": 1 } ] } } ``` ##### Status: 400 Invalid body ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 401 Auth required ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 409 Slug or membership conflict ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Get an identity lookup portfolio - **Method:**Β `GET` - **Path:**Β `/portfolios/{idOrSlug}` - **Tags:**Β Projects #### Responses ##### Status: 200 Portfolio ###### Content-Type: application/json - **`portfolio`** `object` - **`account_id`** `string` - **`created_at`** `integer`, format: `int64` - **`id`** `string` - **`members`** `array` **Items:** - **`added_at`** `integer`, format: `int64` - **`project`** `string` - **`project_id`** `string` - **`name`** `string` - **`slug`** `string` - **`updated_at`** `integer`, format: `int64` **Example:** ```json { "portfolio": { "id": "pf_abc123", "account_id": "acc_123", "slug": "growth-system", "name": "Growth system", "created_at": 1, "updated_at": 1, "members": [ { "project_id": "", "project": "", "added_at": 1 } ] } } ``` ### Update an identity lookup portfolio - **Method:**Β `PATCH` - **Path:**Β `/portfolios/{idOrSlug}` - **Tags:**Β Projects Updates a portfolio name and/or replaces its project membership. Portfolio slugs are immutable. #### Request Body ##### Content-Type: application/json - **`allow_move`** `boolean` - **`name`** `string` - **`projects`** `array` **Items:** `string` **Example:** ```json { "name": "", "projects": [ "" ], "allow_move": true } ``` #### Responses ##### Status: 200 Portfolio updated ###### Content-Type: application/json - **`ok`** `boolean` - **`portfolio`** `object` - **`account_id`** `string` - **`created_at`** `integer`, format: `int64` - **`id`** `string` - **`members`** `array` **Items:** - **`added_at`** `integer`, format: `int64` - **`project`** `string` - **`project_id`** `string` - **`name`** `string` - **`slug`** `string` - **`updated_at`** `integer`, format: `int64` **Example:** ```json { "ok": true, "portfolio": { "id": "pf_abc123", "account_id": "acc_123", "slug": "growth-system", "name": "Growth system", "created_at": 1, "updated_at": 1, "members": [ { "project_id": "", "project": "", "added_at": 1 } ] } } ``` ##### Status: 400 Invalid body ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 401 Auth required ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 404 Portfolio not found ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 409 Membership conflict ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Delete an empty identity lookup portfolio - **Method:**Β `DELETE` - **Path:**Β `/portfolios/{idOrSlug}` - **Tags:**Β Projects Deletes a portfolio only when it has no member projects. #### Responses ##### Status: 200 Portfolio deleted ###### Content-Type: application/json - **`ok`** `boolean` **Example:** ```json { "ok": true } ``` ##### Status: 401 Auth required ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 404 Portfolio not found ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 409 Portfolio has members ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### List all projects - **Method:**Β `GET` - **Path:**Β `/projects` - **Tags:**Β Projects Returns all projects under your account with event/read counts and tier info. **CLI:** `npx --yes @agent-analytics/cli@0.5.34 projects` #### Responses ##### Status: 200 Project list ###### Content-Type: application/json - **`has_api_key`** `boolean` - **`projects`** `array` **Items:** - **`allowed_origins`** `string` - **`id`** `string` - **`name`** `string` - **`project_token`** `string` - **`source_scan_id`** `string | null` β€” Website analysis id linked during project creation, when present. - **`total_events`** `integer` - **`total_reads`** `integer` - **`tier`** `string`, possible values: `"free", "pro"` **Example:** ```json { "projects": [ { "id": "", "name": "my-site", "project_token": "aat_...", "allowed_origins": "*", "total_events": 1, "total_reads": 1, "source_scan_id": null } ], "has_api_key": true, "tier": "free" } ``` ##### Status: 401 Missing or invalid API key ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Create a new project - **Method:**Β `POST` - **Path:**Β `/projects` - **Tags:**Β Projects Creates a new project and provisions a D1 database if needed. Returns the project token and a ready-to-use tracking snippet. Project names must be alphanumeric with hyphens, underscores, or dots (max 64 chars). If a project with the same name already exists, returns the existing project (idempotent). Pass `source_scan_id` when creating the project from a website analysis so activation can be tied back to the recommended instrumentation plan. **CLI:** `npx --yes @agent-analytics/cli@0.5.34 create my-new-site --domain https://example.com --source-scan scan_...` #### Request Body ##### Content-Type: application/json - **`name` (required)** `string` β€” Project name (alphanumeric, hyphens, underscores, dots; max 64 chars) - **`allowed_origins`** `string`, default: `"*"` β€” Allowed origins for CORS. Use \`\*\` for any origin. - **`source_scan_id`** `string` β€” Optional website analysis id to link to this project. Requires account ownership and hostname/origin match. **Example:** ```json { "name": "my-new-site", "allowed_origins": "https://example.com", "source_scan_id": "scan_..." } ``` #### Responses ##### Status: 200 Project already exists (returned existing project) ###### Content-Type: application/json - **`existing`** `boolean` - **`id`** `string` - **`name`** `string` - **`project_token`** `string` **Example:** ```json { "id": "", "name": "", "project_token": "", "existing": true } ``` ##### Status: 201 Project created ###### Content-Type: application/json - **`allowed_origins`** `string` - **`api_example`** `string` β€” Example curl command for querying stats - **`id`** `string` - **`name`** `string` - **`project_token`** `string` - **`snippet`** `string` β€” Ready-to-use HTML tracking snippet - **`source_scan_id`** `string | null` **Example:** ```json { "id": "", "name": "", "project_token": "aat_...", "allowed_origins": "", "source_scan_id": null, "snippet": "", "api_example": "" } ``` ##### Status: 400 Missing name or invalid project name ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 401 Missing or invalid API key ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 409 Duplicate origin ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Get project details - **Method:**Β `GET` - **Path:**Β `/projects/{id}` - **Tags:**Β Projects Returns a single project with its configuration and today's usage stats. #### Responses ##### Status: 200 Project details ###### Content-Type: application/json - **`allowed_origins`** `string` - **`id`** `string` - **`name`** `string` - **`project_token`** `string` - **`usage_today`** `object` **Example:** ```json { "id": "", "name": "", "project_token": "", "allowed_origins": "", "usage_today": {} } ``` ##### Status: 401 Missing or invalid API key ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 403 Not your project ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 404 Project not found ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Update a project - **Method:**Β `PATCH` - **Path:**Β `/projects/{id}` - **Tags:**Β Projects Update a project's name and/or allowed origins. **Note:** Project name cannot be changed after events have been recorded. #### Request Body ##### Content-Type: application/json - **`allowed_origins`** `string` β€” New allowed origins - **`name`** `string` β€” New project name **Example:** ```json { "name": "", "allowed_origins": "" } ``` #### Responses ##### Status: 200 Updated project ###### Content-Type: application/json - **`allowed_origins`** `string` - **`id`** `string` - **`name`** `string` - **`project_token`** `string` **Example:** ```json { "id": "", "name": "", "project_token": "", "allowed_origins": "" } ``` ##### Status: 400 Invalid name or no fields to update ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 401 Missing or invalid API key ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 409 Name locked (events recorded) or duplicate name/origin ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Delete a project - **Method:**Β `DELETE` - **Path:**Β `/projects/{id}` - **Tags:**Β Projects Soft-deletes a project. Revokes the project token (no new events can be written). Event data is preserved in the database but no longer accessible via API. #### Responses ##### Status: 200 Project deleted ###### Content-Type: application/json - **`deleted`** `string` β€” Project ID - **`ok`** `boolean` **Example:** ```json { "ok": true, "deleted": "" } ``` ##### Status: 401 Missing or invalid API key ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 403 Not your project ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 404 Project not found ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Get account info - **Method:**Β `GET` - **Path:**Β `/account` - **Tags:**Β Account Returns your account details, tier, limits, and project count. **CLI:** `npx --yes @agent-analytics/cli@0.5.34 whoami` #### Responses ##### Status: 200 Account info ###### Content-Type: application/json - **`created_at`** `string` - **`email`** `string` - **`github_login`** `string | null` - **`id`** `string` - **`monthly_spend_cap_dollars`** `number | null` - **`projects_count`** `integer` - **`tier`** `string`, possible values: `"free", "pro"` - **`tier_limits`** `object` - **`max_events_per_month`** `integer` - **`max_projects`** `integer` - **`max_reads_per_month`** `integer` - **`rate_limit_rpm`** `integer` - **`retention_days`** `integer` **Example:** ```json { "id": "acc_free123", "email": "free@example.com", "github_login": "freeuser", "tier": "free", "created_at": "2026-02-01T12:00:00.000Z", "projects_count": 2, "tier_limits": { "max_events_per_month": 100000, "max_projects": 2, "max_reads_per_month": 500, "retention_days": 90, "rate_limit_rpm": 10 }, "monthly_spend_cap_dollars": null } ``` ##### Status: 401 Missing or invalid API key ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Filtered automated traffic for one project - **Method:**Β `GET` - **Path:**Β `/bot-traffic` - **Tags:**Β Analytics Returns a project-scoped summary of automated traffic that reached Agent Analytics and was filtered out of normal analytics. This endpoint reports daily aggregates only: automated request count, dropped event count, category breakdown, top actors, and a zero-filled time series for the selected period. This is **not** full site bot visibility like CDN logs. It only includes automated requests that actually reached `POST /track` or `POST /track/batch`. **CLI:** `npx --yes @agent-analytics/cli@0.5.34 bot-traffic my-site --period 7d --limit 5` **MCP:** `bot_traffic_overview` #### Responses ##### Status: 200 Project bot traffic overview ###### Content-Type: application/json - **`actors`** `array` **Items:** - **`actor`** `string` - **`category`** `string` - **`dropped_events`** `integer` - **`last_seen_at`** `object` - **`requests`** `integer` - **`categories`** `array` **Items:** - **`category`** `string` - **`dropped_events`** `integer` - **`requests`** `integer` - **`share_pct`** `number` - **`period`** `object` - **`from`** `string`, format: `date` - **`label`** `string`, possible values: `"1d", "7d", "14d", "30d", "90d"` - **`previous_from`** `string`, format: `date` - **`previous_to`** `string`, format: `date` - **`to`** `string`, format: `date` - **`project`** `string` - **`project_context`** `object` - **`activation_events`** `array`, default: `[]` β€” Event names that define activation or the main success path. **Items:** `string` - **`annotations`** `array`, default: `[]` β€” Major date annotations. Project-scoped analytics responses include only annotations inside the requested date range plus one day before and after. **Items:** - **`occurred_at` (required)** `string`, format: `date-time` β€” ISO-8601 datetime when a major product change happened. Stored as a UTC ISO string. - **`title` (required)** `string` β€” Short annotation title for a meaningful product, pricing, release, landing-page, onboarding, feature, or experiment change. - **`note`** `string` β€” Optional short note. Do not store commit logs, PII, secrets, or long release notes. - **`glossary`** `array`, default: `[]` **Items:** - **`definition` (required)** `string` β€” Short meaning that helps an agent interpret analytics results. - **`event_name` (required)** `string` β€” Event name this glossary entry explains. Use \`/properties\` or \`/properties/received\` to inspect current project event names before updating. - **`term` (required)** `string` β€” Human or product term for the event. - **`goals`** `array`, default: `[]` **Items:** `string` - **`scope`** `string`, possible values: `"project"` - **`summary`** `object` - **`automated_requests`** `object` - **`change`** `integer` - **`change_pct`** `object` - **`current`** `integer` - **`previous`** `integer` - **`dropped_events`** `object` - **`change`** `integer` - **`change_pct`** `object` - **`current`** `integer` - **`previous`** `integer` - **`last_seen_at`** `object` - **`time_series`** `array` **Items:** - **`date`** `string`, format: `date` - **`dropped_events`** `integer` - **`requests`** `integer` **Example:** ```json { "scope": "project", "project": "my-site", "project_context": { "goals": [ "Increase activated Agent Analytics accounts" ], "activation_events": [ "signup_completed", "project_created", "first_event_received" ], "glossary": [], "annotations": [] }, "period": { "label": "7d", "from": "2026-03-03", "to": "2026-03-09", "previous_from": "2026-02-24", "previous_to": "2026-03-02" }, "summary": { "automated_requests": { "current": 5, "previous": 1, "change": 4, "change_pct": 400 }, "dropped_events": { "current": 5, "previous": 1, "change": 4, "change_pct": 400 }, "last_seen_at": 1773459600000 }, "categories": [ { "category": "ai_agent", "requests": 3, "dropped_events": 5, "share_pct": 60 } ], "actors": [ { "actor": "ChatGPT-User", "category": "ai_agent", "requests": 3, "dropped_events": 5, "last_seen_at": 1773459600000 } ], "time_series": [ { "date": "2026-03-13", "requests": 5, "dropped_events": 7 } ] } ``` ##### Status: 400 Invalid period or missing project ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 401 Missing or invalid API key ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 404 Project not found or unauthorized ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Historical all-sites overview - **Method:**Β `GET` - **Path:**Β `/account/all-sites` - **Tags:**Β Account Returns a lightweight historical summary across all active projects in your account. This endpoint is optimized for a single account-level dashboard view: total event trend, active project count, daily event time series, and a top-project list. Use `/live` for a real-time snapshot of one project. Use project-scoped endpoints like `/stats` and `/insights` when you want deeper analysis for one project. **CLI:** `npx --yes @agent-analytics/cli@0.5.34 all-sites --period 7d` #### Responses ##### Status: 200 Account-wide historical overview ###### Content-Type: application/json - **`period`** `object` - **`from`** `string`, format: `date` - **`label`** `string`, possible values: `"1d", "7d", "14d", "30d", "90d"` - **`previous_from`** `string`, format: `date` - **`previous_to`** `string`, format: `date` - **`to`** `string`, format: `date` - **`projects`** `array` **Items:** - **`events`** `integer` - **`id`** `string` - **`last_active_date`** `object` - **`name`** `string` - **`share_pct`** `number` - **`remaining_projects`** `integer` - **`scope`** `string`, possible values: `"account"` - **`summary`** `object` - **`active_projects`** `integer` - **`total_events`** `object` - **`change`** `integer` - **`change_pct`** `object` - **`current`** `integer` - **`previous`** `integer` - **`total_projects`** `integer` - **`time_series`** `array` **Items:** - **`date`** `string`, format: `date` - **`events`** `integer` **Example:** ```json { "scope": "account", "period": { "label": "7d", "from": "2026-03-03", "to": "2026-03-09", "previous_from": "2026-02-24", "previous_to": "2026-03-02" }, "summary": { "total_projects": 3, "active_projects": 2, "total_events": { "current": 120, "previous": 90, "change": 30, "change_pct": 33 } }, "time_series": [ { "date": "2026-03-09", "events": 40 } ], "projects": [ { "id": "proj_123", "name": "my-site", "events": 80, "share_pct": 66.7, "last_active_date": "2026-03-09" } ], "remaining_projects": 1 } ``` ##### Status: 400 Invalid period ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 401 Missing or invalid API key ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Filtered automated traffic across all active projects - **Method:**Β `GET` - **Path:**Β `/account/bot-traffic` - **Tags:**Β Account Returns an account-scoped summary of automated traffic that reached Agent Analytics and was filtered out of normal analytics. This endpoint is optimized for a lightweight all-sites view: total filtered requests, dropped events, active-project count, top-project list, category breakdown, and a zero-filled daily time series. Deleted projects are excluded from the totals and rankings. **CLI:** `npx --yes @agent-analytics/cli@0.5.34 bot-traffic --all --period 7d --limit 10` **MCP:** `all_sites_bot_traffic` #### Responses ##### Status: 200 Account-wide bot traffic overview ###### Content-Type: application/json - **`categories`** `array` **Items:** - **`category`** `string` - **`dropped_events`** `integer` - **`requests`** `integer` - **`share_pct`** `number` - **`period`** `object` - **`from`** `string`, format: `date` - **`label`** `string`, possible values: `"1d", "7d", "14d", "30d", "90d"` - **`previous_from`** `string`, format: `date` - **`previous_to`** `string`, format: `date` - **`to`** `string`, format: `date` - **`projects`** `array` **Items:** - **`dropped_events`** `integer` - **`id`** `string` - **`last_seen_at`** `object` - **`name`** `string` - **`requests`** `integer` - **`share_pct`** `number` - **`remaining_projects`** `integer` - **`scope`** `string`, possible values: `"account"` - **`summary`** `object` - **`active_projects`** `integer` - **`automated_requests`** `object` - **`change`** `integer` - **`change_pct`** `object` - **`current`** `integer` - **`previous`** `integer` - **`dropped_events`** `object` - **`change`** `integer` - **`change_pct`** `object` - **`current`** `integer` - **`previous`** `integer` - **`last_seen_at`** `object` - **`total_projects`** `integer` - **`time_series`** `array` **Items:** - **`date`** `string`, format: `date` - **`dropped_events`** `integer` - **`requests`** `integer` **Example:** ```json { "scope": "account", "period": { "label": "7d", "from": "2026-03-03", "to": "2026-03-09", "previous_from": "2026-02-24", "previous_to": "2026-03-02" }, "summary": { "automated_requests": { "current": 5, "previous": 1, "change": 4, "change_pct": 400 }, "dropped_events": { "current": 5, "previous": 1, "change": 4, "change_pct": 400 }, "active_projects": 1, "total_projects": 4, "last_seen_at": 1773459600000 }, "categories": [ { "category": "ai_agent", "requests": 3, "dropped_events": 5, "share_pct": 60 } ], "projects": [ { "id": "proj_123", "name": "my-site", "requests": 3, "dropped_events": 4, "share_pct": 60, "last_seen_at": 1773459600000 } ], "remaining_projects": 3, "time_series": [ { "date": "2026-03-13", "requests": 5, "dropped_events": 7 } ] } ``` ##### Status: 400 Invalid period ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 401 Missing or invalid API key ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### List active and historical agent sessions for the account - **Method:**Β `GET` - **Path:**Β `/account/agent-sessions` - **Tags:**Β Agent Sessions Returns agent sessions created for CLI, MCP, and managed runtimes under the authenticated account. #### Responses ##### Status: 200 Agent sessions for the account ###### Content-Type: application/json - **`sessions`** `array` **Items:** - **`access_expires_at`** `integer` - **`client_instance_id`** `object` - **`client_name`** `object` - **`client_type`** `string` - **`created_at`** `integer` - **`id`** `string` - **`label`** `object` - **`last_used_at`** `integer` - **`refresh_expires_at`** `integer` - **`revoked_at`** `object` - **`scopes`** `array` **Items:** `string` - **`status`** `string`, possible values: `"active", "revoked"` **Example:** ```json { "sessions": [ { "id": "", "client_type": "", "client_name": "", "client_instance_id": "", "label": "", "scopes": [ "" ], "status": "active", "created_at": 1, "last_used_at": 1, "access_expires_at": 1, "refresh_expires_at": 1, "revoked_at": 1 } ] } ``` ##### Status: 401 Missing or invalid account auth ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Revoke and regenerate API key - **Method:**Β `POST` - **Path:**Β `/account/revoke-key` - **Tags:**Β Account Revokes the current API key and generates a new one. The old key stops working immediately. The new key is returned in the response β€” this is the only time it's shown. This route does not accept scoped agent-session bearer tokens. #### Responses ##### Status: 200 New API key ###### Content-Type: application/json - **`api_key`** `string` β€” The new API key. Save this β€” it won't be shown again. - **`ok`** `boolean` **Example:** ```json { "ok": true, "api_key": "aak_..." } ``` ##### Status: 401 Missing or invalid API key ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 403 Agent-session bearer auth is not allowed for raw API-key rotation ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Submit product or workflow feedback - **Method:**Β `POST` - **Path:**Β `/account/feedback` - **Tags:**Β Account Sends feedback about Agent Analytics product gaps, confusing workflows, or missing capabilities to the internal review channel. This endpoint is meant for sanitized summaries of what was hard and what Agent Analytics should have done instead. Do not include private owner details, secrets, API keys, or raw customer data. **CLI:** `npx --yes @agent-analytics/cli@0.5.34 feedback --message "..."` #### Request Body ##### Content-Type: application/json - **`message` (required)** `string` β€” Sanitized summary of the friction, missing capability, or workflow problem. - **`command`** `string` β€” Optional CLI command or workflow step that led to the issue. - **`context`** `string` β€” Optional sanitized context. Do not include private owner details, secrets, or raw customer data. - **`project`** `string` β€” Optional project name for context. **Example:** ```json { "message": "The agent had to calculate funnel drop-off manually instead of using a built-in report.", "project": "my-site", "command": "agent-analytics funnel my-site --steps \"page_view,signup,purchase\"", "context": "The agent understood the goal but had to compute the percentages manually." } ``` #### Responses ##### Status: 200 Feedback accepted ###### Content-Type: application/json - **`ok`** `boolean` **Example:** ```json { "ok": true } ``` ##### Status: 400 Invalid JSON or validation error ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 401 Missing or invalid API key ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Get experiment config for tracker.js - **Method:**Β `GET` - **Path:**Β `/experiments/config` - **Tags:**Β Experiments Returns active experiments for a project, used by `tracker.js` to assign variants client-side. This is a **public** endpoint β€” authenticated by project token (same as `/track`), not API key. You don't call this directly β€” the tracker fetches it automatically on page load. #### Responses ##### Status: 200 Active experiments for this project ###### Content-Type: application/json - **`experiments`** `array` **Items:** - **`key`** `string` - **`variants`** `array` **Items:** - **`key`** `string` - **`weight`** `integer` **Example:** ```json { "experiments": [ { "key": "signup_cta", "variants": [ { "key": "", "weight": 1 } ] } ] } ``` ##### Status: 400 Missing token ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Create an A/B experiment - **Method:**Β `POST` - **Path:**Β `/experiments` - **Tags:**Β Experiments Creates a new experiment for the specified project. **Pro tier only.** Variants are assigned client-side by `tracker.js` using a deterministic hash β€” same user always gets the same variant. Exposure events (`$experiment_exposure`) are tracked automatically. **CLI:** `npx --yes @agent-analytics/cli@0.5.34 experiments create my-site --name signup_cta --variants control,new_cta --goal signup` #### Request Body ##### Content-Type: application/json - **`goal_event` (required)** `string` β€” Event name to measure conversion (max 256 chars) - **`name` (required)** `string` β€” Experiment name (alphanumeric, hyphens, underscores; max 64 chars) - **`project` (required)** `string` β€” Project name - **`variants` (required)** `array` β€” 2-4 variant keys **Items:** `string` - **`weights`** `array` β€” Optional traffic weights per variant (must sum to 100). Defaults to equal split. **Items:** `integer` **Example:** ```json { "project": "my-site", "name": "signup_cta", "variants": [ "control", "new_cta" ], "goal_event": "signup", "weights": [ 50, 50 ] } ``` #### Responses ##### Status: 201 Experiment created ###### Content-Type: application/json - **`account_id`** `string` - **`completed_at`** `string | null` - **`created_at`** `string` - **`goal_event`** `string` - **`id`** `string` - **`name`** `string` - **`project_id`** `string` - **`status`** `string`, possible values: `"active", "paused", "completed"` - **`updated_at`** `string` - **`variants`** `array` **Items:** - **`key`** `string` - **`weight`** `integer` - **`winner`** `string | null` β€” Variant key, set when status is completed **Example:** ```json { "id": "exp_a1b2c3d4e5f6g7h8", "project_id": "", "account_id": "", "name": "signup_cta", "variants": [ { "key": "control", "weight": 50 } ], "goal_event": "signup", "status": "active", "winner": null, "created_at": "", "updated_at": "", "completed_at": null } ``` ##### Status: 400 Validation error (missing fields, invalid variants, duplicate name) ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 401 Missing or invalid API key ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 403 Pro tier required ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 404 Project not found ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 409 Experiment name already exists in this project ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### List experiments - **Method:**Β `GET` - **Path:**Β `/experiments` - **Tags:**Β Experiments Returns all experiments for a project (active, paused, and completed). **CLI:** `npx --yes @agent-analytics/cli@0.5.34 experiments list my-site` #### Responses ##### Status: 200 Experiment list ###### Content-Type: application/json - **`experiments`** `array` **Items:** - **`account_id`** `string` - **`completed_at`** `string | null` - **`created_at`** `string` - **`goal_event`** `string` - **`id`** `string` - **`name`** `string` - **`project_id`** `string` - **`status`** `string`, possible values: `"active", "paused", "completed"` - **`updated_at`** `string` - **`variants`** `array` **Items:** - **`key`** `string` - **`weight`** `integer` - **`winner`** `string | null` β€” Variant key, set when status is completed **Example:** ```json { "experiments": [ { "id": "exp_a1b2c3d4e5f6g7h8", "project_id": "", "account_id": "", "name": "signup_cta", "variants": [ { "key": "control", "weight": 50 } ], "goal_event": "signup", "status": "active", "winner": null, "created_at": "", "updated_at": "", "completed_at": null } ] } ``` ##### Status: 400 Missing project parameter ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 401 Missing or invalid API key ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 404 Project not found ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Get experiment with live results - **Method:**Β `GET` - **Path:**Β `/experiments/{id}` - **Tags:**Β Experiments Returns experiment config plus live Bayesian A/B test results. Results include `probability_best` (probability each variant is the winner), `lift` (relative improvement over baseline), `sufficient_data` (whether enough exposures exist), and a human-readable `recommendation`. The system needs \~100 exposures per variant before results are statistically significant. **CLI:** `npx --yes @agent-analytics/cli@0.5.34 experiments get exp_abc123` #### Responses ##### Status: 200 Experiment with results ###### Content-Type: application/json **All of:** - **`account_id`** `string` - **`completed_at`** `string | null` - **`created_at`** `string` - **`goal_event`** `string` - **`id`** `string` - **`name`** `string` - **`project_id`** `string` - **`status`** `string`, possible values: `"active", "paused", "completed"` - **`updated_at`** `string` - **`variants`** `array` **Items:** - **`key`** `string` - **`weight`** `integer` - **`winner`** `string | null` β€” Variant key, set when status is completed * **`results`** `object` - **`lift`** `object` - **`probability_best`** `object` - **`recommendation`** `string` - **`sufficient_data`** `boolean` - **`variants`** `array` **Items:** - **`conversion_rate`** `number` - **`conversions`** `integer` - **`exposures`** `integer` - **`key`** `string` - **`unique_users`** `integer` **Example:** ```json { "id": "exp_a1b2c3d4e5f6g7h8", "project_id": "", "account_id": "", "name": "signup_cta", "variants": [ { "key": "control", "weight": 50 } ], "goal_event": "signup", "status": "active", "winner": null, "created_at": "", "updated_at": "", "completed_at": null, "results": { "variants": [ { "key": "control", "exposures": 520, "unique_users": 480, "conversions": 48, "conversion_rate": 0.1 } ], "probability_best": { "control": 0.06, "new_cta": 0.94 }, "lift": { "control": -0.32, "new_cta": 0.47 }, "sufficient_data": true, "recommendation": "'new_cta' is the winner with 94% probability (47% lift over baseline)" } } ``` ##### Status: 401 Missing or invalid API key ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 403 Not your experiment ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 404 Experiment not found ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Update experiment status - **Method:**Β `PATCH` - **Path:**Β `/experiments/{id}` - **Tags:**Β Experiments Update an experiment's status. Valid status transitions: - `active` β†’ `paused` or `completed` - `paused` β†’ `active` or `completed` - `completed` is terminal (no further changes) When completing, optionally set `winner` to a variant key. **CLI:** - `npx --yes @agent-analytics/cli@0.5.34 experiments pause exp_abc123` - `npx --yes @agent-analytics/cli@0.5.34 experiments resume exp_abc123` - `npx --yes @agent-analytics/cli@0.5.34 experiments complete exp_abc123 --winner new_cta` #### Request Body ##### Content-Type: application/json - **`status`** `string`, possible values: `"active", "paused", "completed"` β€” New status - **`winner`** `string` β€” Variant key to declare as winner (only when completing) **Example:** ```json { "status": "active", "winner": "" } ``` #### Responses ##### Status: 200 Updated experiment ###### Content-Type: application/json - **`account_id`** `string` - **`completed_at`** `string | null` - **`created_at`** `string` - **`goal_event`** `string` - **`id`** `string` - **`name`** `string` - **`project_id`** `string` - **`status`** `string`, possible values: `"active", "paused", "completed"` - **`updated_at`** `string` - **`variants`** `array` **Items:** - **`key`** `string` - **`weight`** `integer` - **`winner`** `string | null` β€” Variant key, set when status is completed **Example:** ```json { "id": "exp_a1b2c3d4e5f6g7h8", "project_id": "", "account_id": "", "name": "signup_cta", "variants": [ { "key": "control", "weight": 50 } ], "goal_event": "signup", "status": "active", "winner": null, "created_at": "", "updated_at": "", "completed_at": null } ``` ##### Status: 400 Invalid status transition or missing status ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 401 Missing or invalid API key ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 403 Not your experiment ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 404 Experiment not found ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### Delete an experiment - **Method:**Β `DELETE` - **Path:**Β `/experiments/{id}` - **Tags:**Β Experiments Permanently deletes an experiment. Event data (exposures, conversions) is preserved in the events table β€” only the experiment config is removed. **CLI:** `npx --yes @agent-analytics/cli@0.5.34 experiments delete exp_abc123` #### Responses ##### Status: 200 Experiment deleted ###### Content-Type: application/json - **`deleted`** `string` β€” Experiment ID - **`ok`** `boolean` **Example:** ```json { "ok": true, "deleted": "" } ``` ##### Status: 401 Missing or invalid API key ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 403 Not your experiment ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ##### Status: 404 Experiment not found ###### Content-Type: application/json - **`error` (required)** `string` β€” Machine-readable error code - **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### JavaScript tracker script - **Method:**Β `GET` - **Path:**Β `/tracker.js` - **Tags:**Β Tracking Returns the lightweight JavaScript tracker used for browser-side analytics. Embed it in your HTML: ```html ``` Required attributes: - `data-project`: project name - `data-token`: project token (`aat_*`) The tracker records an initial page view by default. Automatic `url` and `referrer` values are sanitized to `origin + pathname`; UTM collection is limited to the allowlisted `utm_source`, `utm_medium`, `utm_campaign`, `utm_content`, and `utm_term` parameters. SPA route changes require `data-track-spa="true"` on the script tag or manual `page` calls. Browser, OS, device, language, timezone, session count, and first-touch attribution are collected without cookies. Full tracker documentation now lives in the docs site: #### Responses ##### Status: 200 JavaScript file ###### Content-Type: application/javascript `string` **Example:** ```json true ``` ##### Status: 404 Not found ## Schemas ### Error - **Type:**`object` * **`error` (required)** `string` β€” Machine-readable error code * **`message` (required)** `string` β€” Human-readable error message **Example:** ```json { "error": "AUTH_REQUIRED", "message": "API key required" } ``` ### ProjectContextGlossaryEntry - **Type:**`object` * **`definition` (required)** `string` β€” Short meaning that helps an agent interpret analytics results. * **`event_name` (required)** `string` β€” Event name this glossary entry explains. Use \`/properties\` or \`/properties/received\` to inspect current project event names before updating. * **`term` (required)** `string` β€” Human or product term for the event. **Example:** ```json { "event_name": "first_event_received", "term": "AA Activation", "definition": "Signup, project created, and first event received." } ``` ### ProjectContextAnnotation - **Type:**`object` * **`occurred_at` (required)** `string`, format: `date-time` β€” ISO-8601 datetime when a major product change happened. Stored as a UTC ISO string. * **`title` (required)** `string` β€” Short annotation title for a meaningful product, pricing, release, landing-page, onboarding, feature, or experiment change. * **`note`** `string` β€” Optional short note. Do not store commit logs, PII, secrets, or long release notes. **Example:** ```json { "occurred_at": "2026-04-25T13:00:00.000Z", "title": "Changed pricing page offer", "note": "Moved annual plan discount above the fold." } ``` ### ProjectContext - **Type:**`object` * **`activation_events`** `array`, default: `[]` β€” Event names that define activation or the main success path. **Items:** `string` * **`annotations`** `array`, default: `[]` β€” Major date annotations. Project-scoped analytics responses include only annotations inside the requested date range plus one day before and after. **Items:** - **`occurred_at` (required)** `string`, format: `date-time` β€” ISO-8601 datetime when a major product change happened. Stored as a UTC ISO string. - **`title` (required)** `string` β€” Short annotation title for a meaningful product, pricing, release, landing-page, onboarding, feature, or experiment change. - **`note`** `string` β€” Optional short note. Do not store commit logs, PII, secrets, or long release notes. * **`glossary`** `array`, default: `[]` **Items:** - **`definition` (required)** `string` β€” Short meaning that helps an agent interpret analytics results. - **`event_name` (required)** `string` β€” Event name this glossary entry explains. Use \`/properties\` or \`/properties/received\` to inspect current project event names before updating. - **`term` (required)** `string` β€” Human or product term for the event. * **`goals`** `array`, default: `[]` **Items:** `string` **Example:** ```json { "goals": [ "Increase activated Agent Analytics accounts" ], "activation_events": [ "signup_completed", "project_created", "first_event_received" ], "glossary": [], "annotations": [] } ``` ### ProjectContextRequest - **Type:**`object` * **`project` (required)** `string` β€” Project name or ID. * **`activation_events`** `array`, default: `[]` β€” Event names that define activation or the main success path. **Items:** `string` * **`annotations`** `array`, default: `[]` β€” Major date annotations. Use sparingly for human-meaningful changes, not git commit logs. **Items:** - **`occurred_at` (required)** `string`, format: `date-time` β€” ISO-8601 datetime when a major product change happened. Stored as a UTC ISO string. - **`title` (required)** `string` β€” Short annotation title for a meaningful product, pricing, release, landing-page, onboarding, feature, or experiment change. - **`note`** `string` β€” Optional short note. Do not store commit logs, PII, secrets, or long release notes. * **`glossary`** `array`, default: `[]` **Items:** - **`definition` (required)** `string` β€” Short meaning that helps an agent interpret analytics results. - **`event_name` (required)** `string` β€” Event name this glossary entry explains. Use \`/properties\` or \`/properties/received\` to inspect current project event names before updating. - **`term` (required)** `string` β€” Human or product term for the event. * **`goals`** `array`, default: `[]` **Items:** `string` **Example:** ```json { "project": "my-site", "goals": [ "Increase activated Agent Analytics accounts" ], "activation_events": [ "signup_completed", "project_created", "first_event_received" ], "glossary": [], "annotations": [] } ``` ### ProjectContextResponse - **Type:**`object` * **`project` (required)** `string` * **`project_context` (required)** `object` - **`activation_events`** `array`, default: `[]` β€” Event names that define activation or the main success path. **Items:** `string` - **`annotations`** `array`, default: `[]` β€” Major date annotations. Project-scoped analytics responses include only annotations inside the requested date range plus one day before and after. **Items:** - **`occurred_at` (required)** `string`, format: `date-time` β€” ISO-8601 datetime when a major product change happened. Stored as a UTC ISO string. - **`title` (required)** `string` β€” Short annotation title for a meaningful product, pricing, release, landing-page, onboarding, feature, or experiment change. - **`note`** `string` β€” Optional short note. Do not store commit logs, PII, secrets, or long release notes. - **`glossary`** `array`, default: `[]` **Items:** - **`definition` (required)** `string` β€” Short meaning that helps an agent interpret analytics results. - **`event_name` (required)** `string` β€” Event name this glossary entry explains. Use \`/properties\` or \`/properties/received\` to inspect current project event names before updating. - **`term` (required)** `string` β€” Human or product term for the event. - **`goals`** `array`, default: `[]` **Items:** `string` * **`project_id` (required)** `string` * **`ok`** `boolean` β€” Present on successful updates. **Example:** ```json { "ok": true, "project": "my-site", "project_id": "proj_123", "project_context": { "goals": [ "Increase activated Agent Analytics accounts" ], "activation_events": [ "signup_completed", "project_created", "first_event_received" ], "glossary": [], "annotations": [] } } ``` ### PortfolioContextRole - **Type:**`object` * **`project`** `string` * **`role`** `string` **Example:** ```json { "project": "docs.example.com", "role": "discovery_surface" } ``` ### PortfolioContextGlossaryEntry - **Type:**`object` * **`definition`** `string` * **`term`** `string` **Example:** ```json { "term": "Qualified click", "definition": "A visitor reaches the product with relevant intent." } ``` ### PortfolioContext - **Type:**`object` * **`glossary`** `array`, default: `[]` **Items:** - **`definition`** `string` - **`term`** `string` * **`goals`** `array`, default: `[]` **Items:** `string` * **`shared_milestones`** `array`, default: `[]` **Items:** `string` * **`surface_roles`** `array`, default: `[]` **Items:** - **`project`** `string` - **`role`** `string` **Example:** ```json { "goals": [ "Increase qualified users who reach setup" ], "surface_roles": [], "shared_milestones": [ "qualified_click_to_product", "signup", "project_created" ], "glossary": [] } ``` ### PortfolioContextResponse - **Type:**`object` * **`account_id` (required)** `string` * **`portfolio_context` (required)** `object` - **`glossary`** `array`, default: `[]` **Items:** - **`definition`** `string` - **`term`** `string` - **`goals`** `array`, default: `[]` **Items:** `string` - **`shared_milestones`** `array`, default: `[]` **Items:** `string` - **`surface_roles`** `array`, default: `[]` **Items:** - **`project`** `string` - **`role`** `string` * **`ok`** `boolean` β€” Present on successful updates. **Example:** ```json { "ok": true, "account_id": "acc_123", "portfolio_context": { "goals": [ "Increase qualified users who reach setup" ], "surface_roles": [], "shared_milestones": [ "qualified_click_to_product", "signup", "project_created" ], "glossary": [] } } ``` ### TrackRequest - **Type:**`object` * **`event` (required)** `string` β€” Event name (max 256 chars) * **`token` (required)** `string` β€” Project token (\`aat\_\*\`) * **`properties`** `object | null` β€” Arbitrary key-value properties (max 8KB JSON). The tracker auto-populates \`path\`, \`url\`, \`hostname\`, \`title\`, \`referrer\`, \`screen\`, \`browser\`, \`browser\_version\`, \`os\`, \`device\`, \`language\`, \`timezone\` (IANA), \`utm\_\*\` params, \`session\_count\`, \`days\_since\_first\_visit\`, and \`first\_utm\_\*\` (first-touch attribution). * **`session_id`** `string | null` β€” Session identifier (max 256 chars). The tracker auto-generates one via sessionStorage with 30-min inactivity timeout. * **`timestamp`** `number | null` β€” Unix timestamp in milliseconds. Defaults to \`Date.now()\`. Must be within 30 days ago to 5 minutes in the future. * **`user_id`** `string | null` β€” Anonymous user identifier (max 256 chars). The tracker auto-generates one via localStorage. **Example:** ```json { "token": "aat_51da22cdcab084ae1cdb50fd4841c642f0dafdb1d9adfa6b", "event": "page_view", "properties": { "path": "/pricing", "referrer": "https://google.com", "browser": "Chrome", "os": "macOS" }, "user_id": "usr_abc123", "session_id": "ses_xyz789", "timestamp": 1706745600000 } ``` ### TrackBatchRequest - **Type:**`object` * **`events` (required)** `array` β€” Array of events (max 100 per batch) **Items:** - **`event` (required)** `string` - **`token` (required)** `string` β€” Project token (\`aat\_\*\`). All events must use the same token. - **`properties`** `object | null` - **`session_id`** `string | null` - **`timestamp`** `number | null` - **`user_id`** `string | null` **Example:** ```json { "events": [ { "token": "aat_51da22cdcab084ae1cdb50fd4841c642f0dafdb1d9adfa6b", "event": "page_view", "properties": null, "user_id": null, "session_id": null, "timestamp": null } ] } ``` ### StatsResponse - **Type:**`object` * **`events`** `array` β€” Top event names by count (max 20) **Items:** - **`count`** `integer` - **`event`** `string` - **`unique_users`** `integer` * **`period`** `object` - **`from`** `string` - **`groupBy`** `string`, possible values: `"hour", "day", "week", "month"` - **`to`** `string` * **`project`** `string` * **`project_context`** `object` - **`activation_events`** `array`, default: `[]` β€” Event names that define activation or the main success path. **Items:** `string` - **`annotations`** `array`, default: `[]` β€” Major date annotations. Project-scoped analytics responses include only annotations inside the requested date range plus one day before and after. **Items:** - **`occurred_at` (required)** `string`, format: `date-time` β€” ISO-8601 datetime when a major product change happened. Stored as a UTC ISO string. - **`title` (required)** `string` β€” Short annotation title for a meaningful product, pricing, release, landing-page, onboarding, feature, or experiment change. - **`note`** `string` β€” Optional short note. Do not store commit logs, PII, secrets, or long release notes. - **`glossary`** `array`, default: `[]` **Items:** - **`definition` (required)** `string` β€” Short meaning that helps an agent interpret analytics results. - **`event_name` (required)** `string` β€” Event name this glossary entry explains. Use \`/properties\` or \`/properties/received\` to inspect current project event names before updating. - **`term` (required)** `string` β€” Human or product term for the event. - **`goals`** `array`, default: `[]` **Items:** `string` * **`sessions`** `object` - **`avg_duration`** `integer` β€” Average session duration in milliseconds - **`bounce_rate`** `number` β€” Bounce rate computed from event names at query time. A session is a bounce when it has only non-interactive events: \`page\_view\`, \`$impression\`, \`$scroll\_depth\`, \`$error\`, \`$time\_on\_page\`, \`$performance\`, \`$web\_vitals\`. - **`pages_per_session`** `number` - **`sessions_per_user`** `number` - **`total_sessions`** `integer` * **`timeSeries`** `array` **Items:** - **`bucket`** `string` - **`total_events`** `integer` - **`unique_users`** `integer` * **`totals`** `object` - **`total_events`** `integer` - **`unique_users`** `integer` **Example:** ```json { "project": "my-site", "project_context": { "goals": [ "Increase activated Agent Analytics accounts" ], "activation_events": [ "signup_completed", "project_created", "first_event_received" ], "glossary": [], "annotations": [] }, "period": { "from": "2025-01-01", "to": "2025-01-07", "groupBy": "day" }, "totals": { "unique_users": 142, "total_events": 1247 }, "timeSeries": [ { "bucket": "2025-01-01", "unique_users": 1, "total_events": 1 } ], "events": [ { "event": "page_view", "count": 1, "unique_users": 1 } ], "sessions": { "total_sessions": 1, "bounce_rate": 0.45, "avg_duration": 1, "pages_per_session": 1, "sessions_per_user": 1 } } ``` ### EventRow - **Type:**`object` * **`country`** `string | null` β€” ISO 3166-1 alpha-2 country code derived from the request IP at ingestion time * **`date`** `string` * **`event`** `string` * **`id`** `string` * **`project_id`** `string` * **`properties`** `object | null` * **`session_id`** `string | null` * **`timestamp`** `number` * **`user_id`** `string | null` **Example:** ```json { "id": "", "project_id": "", "event": "", "properties": null, "user_id": null, "session_id": null, "timestamp": 1, "date": "", "country": "US" } ``` ### QueryRequest - **Type:**`object` * **`project` (required)** `string` β€” Project name * **`count_mode`** `string`, possible values: `"raw", "session_then_user"` β€” How \`event\_count\` is aggregated. Default for \`event\_count\`: \`session\_then\_user\`. Session-backed rows count by session, no-session rows fall back to user only when that user has no session-backed row in the same group, and fully anonymous rows fall back to event id. Ignored for queries without \`event\_count\`. Use \`raw\` to count ingested rows without dedupe. * **`date_from`** `string` β€” Start date (ISO 8601 or \`Nd\` shorthand). Defaults to 7 days ago. * **`date_to`** `string` β€” End date (ISO 8601). Defaults to today. * **`email`** `string`, format: `email` β€” Optional raw email for authenticated lookup. Send only in the HTTPS POST body. The API normalizes it, computes a scoped HMAC lookup index server-side, and does not store raw email in event rows or profile traits. * **`filters`** `array` **Items:** - **`field`** `string` β€” Field to filter on. Built-in: \`event\`, \`user\_id\`, \`date\`, \`country\`, \`session\_id\`, \`timestamp\`. You can also filter on any \`properties.\*\` field, including first-touch attribution fields like \`properties.first\_utm\_source\`. - **`op`** `string`, possible values: `"eq", "neq", "gt", "lt", "gte", "lte", "contains"` - **`value`** `object` β€” Value to compare against * **`group_by`** `array`, default: `[]` β€” Built-in fields to group results by. Property-based grouping such as \`properties.hostname\` is not supported. **Items:** `string`, possible values: `"event", "date", "user_id", "session_id", "country"` * **`limit`** `integer`, default: `100` * **`metrics`** `array`, default: `["event_count"]` β€” Metrics to compute **Items:** `string`, possible values: `"event_count", "unique_users", "session_count", "bounce_rate", "avg_duration"` * **`order`** `string`, possible values: `"asc", "desc"`, default: `"desc"` * **`order_by`** `string`, possible values: `"event_count", "unique_users", "session_count", "date", "event"` β€” Field to sort by **Example:** ```json { "project": "my-site", "metrics": [ "event_count" ], "group_by": [], "filters": [ { "field": "event", "op": "eq", "value": "page_view" } ], "date_from": "2025-01-01", "date_to": "2025-01-07", "count_mode": "raw", "email": "alice@example.com", "order_by": "event_count", "order": "desc", "limit": 100 } ``` ### QueryResponse - **Type:**`object` * **`count`** `integer` * **`group_by`** `array` **Items:** `string` * **`metrics`** `array` **Items:** `string` * **`period`** `object` - **`from`** `string` - **`to`** `string` * **`project`** `string` * **`project_context`** `object` - **`activation_events`** `array`, default: `[]` β€” Event names that define activation or the main success path. **Items:** `string` - **`annotations`** `array`, default: `[]` β€” Major date annotations. Project-scoped analytics responses include only annotations inside the requested date range plus one day before and after. **Items:** - **`occurred_at` (required)** `string`, format: `date-time` β€” ISO-8601 datetime when a major product change happened. Stored as a UTC ISO string. - **`title` (required)** `string` β€” Short annotation title for a meaningful product, pricing, release, landing-page, onboarding, feature, or experiment change. - **`note`** `string` β€” Optional short note. Do not store commit logs, PII, secrets, or long release notes. - **`glossary`** `array`, default: `[]` **Items:** - **`definition` (required)** `string` β€” Short meaning that helps an agent interpret analytics results. - **`event_name` (required)** `string` β€” Event name this glossary entry explains. Use \`/properties\` or \`/properties/received\` to inspect current project event names before updating. - **`term` (required)** `string` β€” Human or product term for the event. - **`goals`** `array`, default: `[]` **Items:** `string` * **`rows`** `array` **Items:** **Example:** ```json { "project": "", "project_context": { "goals": [ "Increase activated Agent Analytics accounts" ], "activation_events": [ "signup_completed", "project_created", "first_event_received" ], "glossary": [], "annotations": [] }, "period": { "from": "", "to": "" }, "metrics": [ "" ], "group_by": [ "" ], "rows": [ { "additionalProperty": "anything" } ], "count": 1 } ``` ### IdentityLookupRequest - **Type:**`object` **Any of:** **Example:** ```json { "project": "my-site", "user_id": "user_12345", "email": "alice@example.com", "event": "signup", "since": "30d", "limit": 100 } ``` ### JourneyResponse - **Type:**`object` * **`events`** `array` **Items:** - **`country`** `string | null` β€” ISO 3166-1 alpha-2 country code derived from the request IP at ingestion time - **`date`** `string` - **`event`** `string` - **`id`** `string` - **`project_id`** `string` - **`properties`** `object | null` - **`session_id`** `string | null` - **`timestamp`** `number` - **`user_id`** `string | null` * **`profiles`** `array` **Items:** * **`project`** `string` * **`user_id`** `string | null` **Example:** ```json { "project": "", "user_id": null, "profiles": [ { "additionalProperty": "anything" } ], "events": [ { "id": "", "project_id": "", "event": "", "properties": null, "user_id": null, "session_id": null, "timestamp": 1, "date": "", "country": "US" } ] } ``` ### Portfolio - **Type:**`object` * **`account_id`** `string` * **`created_at`** `integer`, format: `int64` * **`id`** `string` * **`members`** `array` **Items:** - **`added_at`** `integer`, format: `int64` - **`project`** `string` - **`project_id`** `string` * **`name`** `string` * **`slug`** `string` * **`updated_at`** `integer`, format: `int64` **Example:** ```json { "id": "pf_abc123", "account_id": "acc_123", "slug": "growth-system", "name": "Growth system", "created_at": 1, "updated_at": 1, "members": [ { "project_id": "", "project": "", "added_at": 1 } ] } ``` ### SessionRow - **Type:**`object` * **`date`** `string` * **`duration`** `integer` β€” Duration in milliseconds * **`end_time`** `number` * **`entry_page`** `string | null` * **`event_count`** `integer` * **`exit_page`** `string | null` * **`has_replay`** `boolean` β€” Present for callers with replay read authority. True when the session has at least one playable replay segment. * **`is_bounce`** `integer`, possible values: `0, 1` β€” Computed from event names at query time. \`1\` means the session has only non-interactive events: \`page\_view\`, \`$impression\`, \`$scroll\_depth\`, \`$error\`, \`$time\_on\_page\`, \`$performance\`, \`$web\_vitals\`. * **`project_id`** `string` * **`replay_count`** `integer` β€” Number of playable replay segments linked to this analytics session. * **`replays`** `array` β€” Bounded replay summaries. Omitted when the caller does not have replay read authority. **Items:** - **`analytics_session_id`** `string` - **`committed_bytes`** `integer`, format: `int64` - **`ended_at`** `integer | null`, format: `int64` - **`event_count`** `integer` - **`has_full_snapshot`** `boolean` - **`id`** `string` - **`project_id`** `string` - **`started_at`** `integer`, format: `int64` - **`status`** `string`, possible values: `"recording", "complete", "incomplete", "deleting", "deleted"` - **`stop_reason`** `string | null` * **`session_id`** `string` * **`start_time`** `number` * **`user_id`** `string | null` **Example:** ```json { "session_id": "", "user_id": null, "project_id": "", "start_time": 1, "end_time": 1, "duration": 1, "entry_page": null, "exit_page": null, "event_count": 1, "is_bounce": 0, "has_replay": true, "replay_count": 1, "replays": [ { "id": "rpl_abc123", "project_id": "", "analytics_session_id": "", "status": "recording", "started_at": 1, "ended_at": null, "committed_bytes": 1, "event_count": 1, "has_full_snapshot": true, "stop_reason": null } ], "date": "" } ``` ### ReplaySummary - **Type:**`object` * **`analytics_session_id`** `string` * **`committed_bytes`** `integer`, format: `int64` * **`ended_at`** `integer | null`, format: `int64` * **`event_count`** `integer` * **`has_full_snapshot`** `boolean` * **`id`** `string` * **`project_id`** `string` * **`started_at`** `integer`, format: `int64` * **`status`** `string`, possible values: `"recording", "complete", "incomplete", "deleting", "deleted"` * **`stop_reason`** `string | null` **Example:** ```json { "id": "rpl_abc123", "project_id": "", "analytics_session_id": "", "status": "recording", "started_at": 1, "ended_at": null, "committed_bytes": 1, "event_count": 1, "has_full_snapshot": true, "stop_reason": null } ``` ### BreakdownResponse - **Type:**`object` * **`event`** `string | null` * **`project`** `string` * **`project_context`** `object` - **`activation_events`** `array`, default: `[]` β€” Event names that define activation or the main success path. **Items:** `string` - **`annotations`** `array`, default: `[]` β€” Major date annotations. Project-scoped analytics responses include only annotations inside the requested date range plus one day before and after. **Items:** - **`occurred_at` (required)** `string`, format: `date-time` β€” ISO-8601 datetime when a major product change happened. Stored as a UTC ISO string. - **`title` (required)** `string` β€” Short annotation title for a meaningful product, pricing, release, landing-page, onboarding, feature, or experiment change. - **`note`** `string` β€” Optional short note. Do not store commit logs, PII, secrets, or long release notes. - **`glossary`** `array`, default: `[]` **Items:** - **`definition` (required)** `string` β€” Short meaning that helps an agent interpret analytics results. - **`event_name` (required)** `string` β€” Event name this glossary entry explains. Use \`/properties\` or \`/properties/received\` to inspect current project event names before updating. - **`term` (required)** `string` β€” Human or product term for the event. - **`goals`** `array`, default: `[]` **Items:** `string` * **`property`** `string` * **`total_events`** `integer` * **`total_with_property`** `integer` * **`values`** `array` **Items:** - **`count`** `integer` - **`unique_users`** `integer` - **`value`** `string` **Example:** ```json { "project": "", "project_context": { "goals": [ "Increase activated Agent Analytics accounts" ], "activation_events": [ "signup_completed", "project_created", "first_event_received" ], "glossary": [], "annotations": [] }, "property": "path", "event": null, "values": [ { "value": "/pricing", "count": 342, "unique_users": 201 } ], "total_events": 1, "total_with_property": 1 } ``` ### InsightsResponse - **Type:**`object` * **`current_period`** `object` - **`from`** `string` - **`to`** `string` * **`metrics`** `object` - **`avg_duration`** `object` - **`change`** `number` - **`change_pct`** `integer | null` β€” Percentage change. Null when previous period was 0 but current is > 0. - **`current`** `number` - **`previous`** `number` - **`bounce_rate`** `object` - **`change`** `number` - **`change_pct`** `integer | null` β€” Percentage change. Null when previous period was 0 but current is > 0. - **`current`** `number` - **`previous`** `number` - **`total_events`** `object` - **`change`** `number` - **`change_pct`** `integer | null` β€” Percentage change. Null when previous period was 0 but current is > 0. - **`current`** `number` - **`previous`** `number` - **`total_sessions`** `object` - **`change`** `number` - **`change_pct`** `integer | null` β€” Percentage change. Null when previous period was 0 but current is > 0. - **`current`** `number` - **`previous`** `number` - **`unique_users`** `object` - **`change`** `number` - **`change_pct`** `integer | null` β€” Percentage change. Null when previous period was 0 but current is > 0. - **`current`** `number` - **`previous`** `number` * **`previous_period`** `object` - **`from`** `string` - **`to`** `string` * **`project`** `string` * **`project_context`** `object` - **`activation_events`** `array`, default: `[]` β€” Event names that define activation or the main success path. **Items:** `string` - **`annotations`** `array`, default: `[]` β€” Major date annotations. Project-scoped analytics responses include only annotations inside the requested date range plus one day before and after. **Items:** - **`occurred_at` (required)** `string`, format: `date-time` β€” ISO-8601 datetime when a major product change happened. Stored as a UTC ISO string. - **`title` (required)** `string` β€” Short annotation title for a meaningful product, pricing, release, landing-page, onboarding, feature, or experiment change. - **`note`** `string` β€” Optional short note. Do not store commit logs, PII, secrets, or long release notes. - **`glossary`** `array`, default: `[]` **Items:** - **`definition` (required)** `string` β€” Short meaning that helps an agent interpret analytics results. - **`event_name` (required)** `string` β€” Event name this glossary entry explains. Use \`/properties\` or \`/properties/received\` to inspect current project event names before updating. - **`term` (required)** `string` β€” Human or product term for the event. - **`goals`** `array`, default: `[]` **Items:** `string` * **`trend`** `string`, possible values: `"growing", "stable", "declining"` **Example:** ```json { "project": "", "project_context": { "goals": [ "Increase activated Agent Analytics accounts" ], "activation_events": [ "signup_completed", "project_created", "first_event_received" ], "glossary": [], "annotations": [] }, "current_period": { "from": "", "to": "" }, "previous_period": { "from": "", "to": "" }, "metrics": { "total_events": { "current": 1, "previous": 1, "change": 1, "change_pct": null }, "unique_users": { "current": 1, "previous": 1, "change": 1, "change_pct": null }, "total_sessions": { "current": 1, "previous": 1, "change": 1, "change_pct": null }, "bounce_rate": { "current": 1, "previous": 1, "change": 1, "change_pct": null }, "avg_duration": { "current": 1, "previous": 1, "change": 1, "change_pct": null } }, "trend": "growing" } ``` ### DeltaMetric - **Type:**`object` * **`change`** `number` * **`change_pct`** `integer | null` β€” Percentage change. Null when previous period was 0 but current is > 0. * **`current`** `number` * **`previous`** `number` **Example:** ```json { "current": 1, "previous": 1, "change": 1, "change_pct": null } ``` ### PagesResponse - **Type:**`object` * **`entry_pages`** `array` **Items:** - **`avg_duration`** `number` β€” Average session duration in milliseconds - **`avg_events`** `number` - **`bounce_rate`** `number` β€” Bounce rate computed from event names at query time. A session is a bounce when it has only non-interactive events: \`page\_view\`, \`$impression\`, \`$scroll\_depth\`, \`$error\`, \`$time\_on\_page\`, \`$performance\`, \`$web\_vitals\`. - **`bounces`** `integer` - **`page`** `string` - **`sessions`** `integer` * **`exit_pages`** `array` **Items:** - **`avg_duration`** `number` β€” Average session duration in milliseconds - **`avg_events`** `number` - **`bounce_rate`** `number` β€” Bounce rate computed from event names at query time. A session is a bounce when it has only non-interactive events: \`page\_view\`, \`$impression\`, \`$scroll\_depth\`, \`$error\`, \`$time\_on\_page\`, \`$performance\`, \`$web\_vitals\`. - **`bounces`** `integer` - **`page`** `string` - **`sessions`** `integer` * **`project`** `string` * **`project_context`** `object` - **`activation_events`** `array`, default: `[]` β€” Event names that define activation or the main success path. **Items:** `string` - **`annotations`** `array`, default: `[]` β€” Major date annotations. Project-scoped analytics responses include only annotations inside the requested date range plus one day before and after. **Items:** - **`occurred_at` (required)** `string`, format: `date-time` β€” ISO-8601 datetime when a major product change happened. Stored as a UTC ISO string. - **`title` (required)** `string` β€” Short annotation title for a meaningful product, pricing, release, landing-page, onboarding, feature, or experiment change. - **`note`** `string` β€” Optional short note. Do not store commit logs, PII, secrets, or long release notes. - **`glossary`** `array`, default: `[]` **Items:** - **`definition` (required)** `string` β€” Short meaning that helps an agent interpret analytics results. - **`event_name` (required)** `string` β€” Event name this glossary entry explains. Use \`/properties\` or \`/properties/received\` to inspect current project event names before updating. - **`term` (required)** `string` β€” Human or product term for the event. - **`goals`** `array`, default: `[]` **Items:** `string` **Example:** ```json { "project": "", "project_context": { "goals": [ "Increase activated Agent Analytics accounts" ], "activation_events": [ "signup_completed", "project_created", "first_event_received" ], "glossary": [], "annotations": [] }, "entry_pages": [ { "page": "/pricing", "sessions": 1, "bounces": 1, "bounce_rate": 0.45, "avg_duration": 1, "avg_events": 1 } ], "exit_pages": [ { "page": "/pricing", "sessions": 1, "bounces": 1, "bounce_rate": 0.45, "avg_duration": 1, "avg_events": 1 } ] } ``` ### PathsRequest - **Type:**`object` * **`goal_event` (required)** `string` β€” Goal event that must occur in the same session * **`project` (required)** `string` β€” Project name * **`candidate_session_cap`** `integer`, default: `5000` β€” Max sessions scanned before Worker-side path assembly * **`entry_limit`** `integer`, default: `10` β€” Max entry pages to include * **`max_steps`** `integer`, default: `5` β€” Max mixed page/event steps before the path is marked truncated * **`path_limit`** `integer`, default: `5` β€” Max children kept per tree node after aggregation * **`since`** `string`, possible values: `"7d", "14d", "30d", "90d"`, default: `"30d"` β€” Fixed lookback window for bounded path analysis **Example:** ```json { "project": "my-site", "goal_event": "signup", "since": "30d", "max_steps": 5, "entry_limit": 10, "path_limit": 5, "candidate_session_cap": 5000 } ``` ### PathsBounds - **Type:**`object` * **`candidate_session_cap`** `integer` * **`entry_limit`** `integer` * **`max_steps`** `integer` * **`path_limit`** `integer` **Example:** ```json { "max_steps": 5, "entry_limit": 10, "path_limit": 5, "candidate_session_cap": 5000 } ``` ### PathNode - **Type:**`object` * **`children`** `array` β€” Child path nodes. The runtime shape matches \`PathNode\`; the schema avoids a circular \`$ref\` so generated docs can render reliably. **Items:** * **`conversion_rate`** `number` * **`conversions`** `integer` * **`exit_page`** `string | null` β€” Present on \`drop\_off\` and \`truncated\` terminal nodes to tie path drop-off behavior to the actual session exit page. * **`sessions`** `integer` * **`type`** `string`, possible values: `"page", "event", "goal", "drop_off", "truncated"` * **`value`** `string` β€” For \`drop\_off\` and \`truncated\` terminal nodes, this is the exit page when known, otherwise \`unknown\`. **Example:** ```json { "type": "page", "value": "/pricing", "exit_page": "/pricing", "sessions": 42, "conversions": 13, "conversion_rate": 0.31, "children": [ { "additionalProperty": "anything" } ] } ``` ### PathExitPage - **Type:**`object` * **`conversion_rate`** `number` * **`conversions`** `integer` * **`drop_off_rate`** `number` * **`drop_offs`** `integer` * **`exit_page`** `string` * **`sessions`** `integer` **Example:** ```json { "exit_page": "/pricing", "sessions": 42, "conversions": 13, "conversion_rate": 0.31, "drop_offs": 29, "drop_off_rate": 0.69 } ``` ### PathEntry - **Type:**`object` * **`conversion_rate`** `number` * **`conversions`** `integer` * **`entry_page`** `string` * **`exit_pages`** `array` β€” Exit pages reached by sessions that started on this entry page, with conversion and drop-off attribution. **Items:** - **`conversion_rate`** `number` - **`conversions`** `integer` - **`drop_off_rate`** `number` - **`drop_offs`** `integer` - **`exit_page`** `string` - **`sessions`** `integer` * **`sessions`** `integer` * **`tree`** `array` **Items:** - **`children`** `array` β€” Child path nodes. The runtime shape matches \`PathNode\`; the schema avoids a circular \`$ref\` so generated docs can render reliably. **Items:** - **`conversion_rate`** `number` - **`conversions`** `integer` - **`exit_page`** `string | null` β€” Present on \`drop\_off\` and \`truncated\` terminal nodes to tie path drop-off behavior to the actual session exit page. - **`sessions`** `integer` - **`type`** `string`, possible values: `"page", "event", "goal", "drop_off", "truncated"` - **`value`** `string` β€” For \`drop\_off\` and \`truncated\` terminal nodes, this is the exit page when known, otherwise \`unknown\`. **Example:** ```json { "entry_page": "/landing", "sessions": 120, "conversions": 32, "conversion_rate": 0.267, "exit_pages": [ { "exit_page": "/pricing", "sessions": 42, "conversions": 13, "conversion_rate": 0.31, "drop_offs": 29, "drop_off_rate": 0.69 } ], "tree": [ { "type": "page", "value": "/pricing", "exit_page": "/pricing", "sessions": 42, "conversions": 13, "conversion_rate": 0.31, "children": [ { "additionalProperty": "anything" } ] } ] } ``` ### PathsResponse - **Type:**`object` * **`bounds`** `object` - **`candidate_session_cap`** `integer` - **`entry_limit`** `integer` - **`max_steps`** `integer` - **`path_limit`** `integer` * **`entry_paths`** `array` **Items:** - **`conversion_rate`** `number` - **`conversions`** `integer` - **`entry_page`** `string` - **`exit_pages`** `array` β€” Exit pages reached by sessions that started on this entry page, with conversion and drop-off attribution. **Items:** - **`conversion_rate`** `number` - **`conversions`** `integer` - **`drop_off_rate`** `number` - **`drop_offs`** `integer` - **`exit_page`** `string` - **`sessions`** `integer` - **`sessions`** `integer` - **`tree`** `array` **Items:** - **`children`** `array` β€” Child path nodes. The runtime shape matches \`PathNode\`; the schema avoids a circular \`$ref\` so generated docs can render reliably. **Items:** - **`conversion_rate`** `number` - **`conversions`** `integer` - **`exit_page`** `string | null` β€” Present on \`drop\_off\` and \`truncated\` terminal nodes to tie path drop-off behavior to the actual session exit page. - **`sessions`** `integer` - **`type`** `string`, possible values: `"page", "event", "goal", "drop_off", "truncated"` - **`value`** `string` β€” For \`drop\_off\` and \`truncated\` terminal nodes, this is the exit page when known, otherwise \`unknown\`. * **`goal_event`** `string` * **`period`** `object` - **`from`** `string`, format: `date` - **`to`** `string`, format: `date` * **`project`** `string` * **`project_context`** `object` - **`activation_events`** `array`, default: `[]` β€” Event names that define activation or the main success path. **Items:** `string` - **`annotations`** `array`, default: `[]` β€” Major date annotations. Project-scoped analytics responses include only annotations inside the requested date range plus one day before and after. **Items:** - **`occurred_at` (required)** `string`, format: `date-time` β€” ISO-8601 datetime when a major product change happened. Stored as a UTC ISO string. - **`title` (required)** `string` β€” Short annotation title for a meaningful product, pricing, release, landing-page, onboarding, feature, or experiment change. - **`note`** `string` β€” Optional short note. Do not store commit logs, PII, secrets, or long release notes. - **`glossary`** `array`, default: `[]` **Items:** - **`definition` (required)** `string` β€” Short meaning that helps an agent interpret analytics results. - **`event_name` (required)** `string` β€” Event name this glossary entry explains. Use \`/properties\` or \`/properties/received\` to inspect current project event names before updating. - **`term` (required)** `string` β€” Human or product term for the event. - **`goals`** `array`, default: `[]` **Items:** `string` **Example:** ```json { "project": "my-site", "project_context": { "goals": [ "Increase activated Agent Analytics accounts" ], "activation_events": [ "signup_completed", "project_created", "first_event_received" ], "glossary": [], "annotations": [] }, "goal_event": "signup", "period": { "from": "2026-03-11", "to": "2026-04-10" }, "bounds": { "max_steps": 5, "entry_limit": 10, "path_limit": 5, "candidate_session_cap": 5000 }, "entry_paths": [ { "entry_page": "/landing", "sessions": 120, "conversions": 32, "conversion_rate": 0.267, "exit_pages": [ { "exit_page": "/pricing", "sessions": 42, "conversions": 13, "conversion_rate": 0.31, "drop_offs": 29, "drop_off_rate": 0.69 } ], "tree": [ { "type": "page", "value": "/pricing", "exit_page": "/pricing", "sessions": 42, "conversions": 13, "conversion_rate": 0.31, "children": [ { "additionalProperty": "anything" } ] } ] } ] } ``` ### PageRow - **Type:**`object` * **`avg_duration`** `number` β€” Average session duration in milliseconds * **`avg_events`** `number` * **`bounce_rate`** `number` β€” Bounce rate computed from event names at query time. A session is a bounce when it has only non-interactive events: \`page\_view\`, \`$impression\`, \`$scroll\_depth\`, \`$error\`, \`$time\_on\_page\`, \`$performance\`, \`$web\_vitals\`. * **`bounces`** `integer` * **`page`** `string` * **`sessions`** `integer` **Example:** ```json { "page": "/pricing", "sessions": 1, "bounces": 1, "bounce_rate": 0.45, "avg_duration": 1, "avg_events": 1 } ``` ### SessionDistributionResponse - **Type:**`object` * **`distribution`** `array` **Items:** - **`avg_events`** `number` - **`bounces`** `integer` β€” Number of bounce sessions in this duration bucket (computed from event names at query time). - **`bucket`** `string`, possible values: `"0s", "1-10s", "10-30s", "30-60s", "1-3m", "3-10m", "10m+"` - **`pct`** `number` β€” Percentage of total sessions - **`sessions`** `integer` * **`engaged_pct`** `number` β€” Percentage of sessions >= 30 seconds * **`median_bucket`** `string | null` * **`project`** `string` * **`project_context`** `object` - **`activation_events`** `array`, default: `[]` β€” Event names that define activation or the main success path. **Items:** `string` - **`annotations`** `array`, default: `[]` β€” Major date annotations. Project-scoped analytics responses include only annotations inside the requested date range plus one day before and after. **Items:** - **`occurred_at` (required)** `string`, format: `date-time` β€” ISO-8601 datetime when a major product change happened. Stored as a UTC ISO string. - **`title` (required)** `string` β€” Short annotation title for a meaningful product, pricing, release, landing-page, onboarding, feature, or experiment change. - **`note`** `string` β€” Optional short note. Do not store commit logs, PII, secrets, or long release notes. - **`glossary`** `array`, default: `[]` **Items:** - **`definition` (required)** `string` β€” Short meaning that helps an agent interpret analytics results. - **`event_name` (required)** `string` β€” Event name this glossary entry explains. Use \`/properties\` or \`/properties/received\` to inspect current project event names before updating. - **`term` (required)** `string` β€” Human or product term for the event. - **`goals`** `array`, default: `[]` **Items:** `string` **Example:** ```json { "project": "", "project_context": { "goals": [ "Increase activated Agent Analytics accounts" ], "activation_events": [ "signup_completed", "project_created", "first_event_received" ], "glossary": [], "annotations": [] }, "distribution": [ { "bucket": "0s", "sessions": 1, "bounces": 1, "avg_events": 1, "pct": 1 } ], "median_bucket": null, "engaged_pct": 1 } ``` ### HeatmapResponse - **Type:**`object` * **`busiest_day`** `string | null` * **`busiest_hour`** `integer | null` * **`heatmap`** `array` **Items:** - **`day`** `integer` β€” Day of week (0=Sunday, 6=Saturday) - **`day_name`** `string` - **`events`** `integer` - **`hour`** `integer` β€” Hour of day (0-23) - **`users`** `integer` * **`peak`** `object | null` - **`day`** `integer` - **`day_name`** `string` - **`events`** `integer` - **`hour`** `integer` - **`users`** `integer` * **`project`** `string` * **`project_context`** `object` - **`activation_events`** `array`, default: `[]` β€” Event names that define activation or the main success path. **Items:** `string` - **`annotations`** `array`, default: `[]` β€” Major date annotations. Project-scoped analytics responses include only annotations inside the requested date range plus one day before and after. **Items:** - **`occurred_at` (required)** `string`, format: `date-time` β€” ISO-8601 datetime when a major product change happened. Stored as a UTC ISO string. - **`title` (required)** `string` β€” Short annotation title for a meaningful product, pricing, release, landing-page, onboarding, feature, or experiment change. - **`note`** `string` β€” Optional short note. Do not store commit logs, PII, secrets, or long release notes. - **`glossary`** `array`, default: `[]` **Items:** - **`definition` (required)** `string` β€” Short meaning that helps an agent interpret analytics results. - **`event_name` (required)** `string` β€” Event name this glossary entry explains. Use \`/properties\` or \`/properties/received\` to inspect current project event names before updating. - **`term` (required)** `string` β€” Human or product term for the event. - **`goals`** `array`, default: `[]` **Items:** `string` **Example:** ```json { "project": "", "project_context": { "goals": [ "Increase activated Agent Analytics accounts" ], "activation_events": [ "signup_completed", "project_created", "first_event_received" ], "glossary": [], "annotations": [] }, "heatmap": [ { "day": 1, "day_name": "Monday", "hour": 1, "events": 1, "users": 1 } ], "peak": { "day": 1, "day_name": "", "hour": 1, "events": 1, "users": 1 }, "busiest_day": "Monday", "busiest_hour": 14 } ``` ### FunnelRequest - **Type:**`object` * **`project` (required)** `string` β€” Project name * **`steps` (required)** `array` β€” Funnel steps (2-8). Each step has an event name and optional property filters. **Items:** - **`event` (required)** `string` β€” Event name for this step - **`filters`** `array` β€” Optional property filters for this step **Items:** - **`op` (required)** `string`, possible values: `"eq", "neq", "contains"` β€” Filter operator - **`property` (required)** `string` β€” Property key (alphanumeric + underscores, max 128 chars) - **`value` (required)** `string` β€” Filter value * **`breakdown`** `string` β€” Optional property key to segment funnel by (e.g. 'variant', 'country'). Extracted from step 1 events only. * **`breakdown_limit`** `number`, default: `10` β€” Max breakdown groups, ordered by step 1 users descending (1-50, default 10) * **`conversion_window_hours`** `number`, default: `168` β€” Max hours from step 1 entry to final step (1-8760, default 168 = 7 days) * **`count_by`** `string`, possible values: `"user_id", "session_id"`, default: `"user_id"` β€” Count by unique users or sessions * **`since`** `string`, default: `"30d"` β€” Lookback period (ISO date or shorthand like '30d'). Default: 30d **Example:** ```json { "project": "my-site", "steps": [ { "event": "page_view", "filters": [ { "property": "path", "op": "eq", "value": "/pricing" } ] } ], "conversion_window_hours": 168, "since": "30d", "count_by": "user_id", "breakdown": "country", "breakdown_limit": 10 } ``` ### FunnelResponse - **Type:**`object` * **`breakdowns`** `array` β€” Per-group funnel results (only present when \`breakdown\` param is set). Ordered by step 1 users descending. **Items:** - **`overall_conversion_rate`** `number` β€” End-to-end conversion for this group - **`steps`** `array` β€” Same shape as top-level steps array **Items:** - **`avg_time_to_next_ms`** `number | null` - **`conversion_rate`** `number` - **`drop_off_rate`** `number` - **`event`** `string` - **`step`** `integer` - **`users`** `integer` - **`value`** `string | null` β€” Breakdown property value (null for events missing the property) * **`overall_conversion_rate`** `number` β€” Fraction of step 1 users that completed the final step * **`project_context`** `object` - **`activation_events`** `array`, default: `[]` β€” Event names that define activation or the main success path. **Items:** `string` - **`annotations`** `array`, default: `[]` β€” Major date annotations. Project-scoped analytics responses include only annotations inside the requested date range plus one day before and after. **Items:** - **`occurred_at` (required)** `string`, format: `date-time` β€” ISO-8601 datetime when a major product change happened. Stored as a UTC ISO string. - **`title` (required)** `string` β€” Short annotation title for a meaningful product, pricing, release, landing-page, onboarding, feature, or experiment change. - **`note`** `string` β€” Optional short note. Do not store commit logs, PII, secrets, or long release notes. - **`glossary`** `array`, default: `[]` **Items:** - **`definition` (required)** `string` β€” Short meaning that helps an agent interpret analytics results. - **`event_name` (required)** `string` β€” Event name this glossary entry explains. Use \`/properties\` or \`/properties/received\` to inspect current project event names before updating. - **`term` (required)** `string` β€” Human or product term for the event. - **`goals`** `array`, default: `[]` **Items:** `string` * **`steps`** `array` **Items:** - **`avg_time_to_next_ms`** `number | null` β€” Average time in ms from this step to the next step (null for last step) - **`conversion_rate`** `number` β€” Fraction of users from previous step that reached this step (step 1 is always 1.0) - **`drop_off_rate`** `number` β€” Fraction of users lost from previous step (step 1 is always 0) - **`event`** `string` - **`step`** `integer` - **`users`** `integer` β€” Number of users (or sessions) that reached this step **Example:** ```json { "project_context": { "goals": [ "Increase activated Agent Analytics accounts" ], "activation_events": [ "signup_completed", "project_created", "first_event_received" ], "glossary": [], "annotations": [] }, "steps": [ { "step": 1, "event": "page_view", "users": 500, "conversion_rate": 0.6, "drop_off_rate": 0.4, "avg_time_to_next_ms": 3600000 } ], "overall_conversion_rate": 0.12, "breakdowns": [ { "value": "US", "steps": [ { "step": 1, "event": "", "users": 1, "conversion_rate": 1, "drop_off_rate": 1, "avg_time_to_next_ms": null } ], "overall_conversion_rate": 0.15 } ] } ``` ### RetentionResponse - **Type:**`object` * **`average_rates`** `array` β€” Weighted average retention rate per period offset (weighted by cohort size) **Items:** `number` * **`cohorts`** `array` **Items:** - **`date`** `string`, format: `date` β€” Start date of this cohort period - **`rates`** `array` β€” Retention rate per period (retained\[i] / users, rounded to 3 decimals) **Items:** `number` - **`retained`** `array` β€” Users active in each subsequent period (index 0 = full cohort) **Items:** `integer` - **`users`** `integer` β€” Number of users who first appeared in this period * **`period`** `string`, possible values: `"day", "week", "month"` * **`project_context`** `object` - **`activation_events`** `array`, default: `[]` β€” Event names that define activation or the main success path. **Items:** `string` - **`annotations`** `array`, default: `[]` β€” Major date annotations. Project-scoped analytics responses include only annotations inside the requested date range plus one day before and after. **Items:** - **`occurred_at` (required)** `string`, format: `date-time` β€” ISO-8601 datetime when a major product change happened. Stored as a UTC ISO string. - **`title` (required)** `string` β€” Short annotation title for a meaningful product, pricing, release, landing-page, onboarding, feature, or experiment change. - **`note`** `string` β€” Optional short note. Do not store commit logs, PII, secrets, or long release notes. - **`glossary`** `array`, default: `[]` **Items:** - **`definition` (required)** `string` β€” Short meaning that helps an agent interpret analytics results. - **`event_name` (required)** `string` β€” Event name this glossary entry explains. Use \`/properties\` or \`/properties/received\` to inspect current project event names before updating. - **`term` (required)** `string` β€” Human or product term for the event. - **`goals`** `array`, default: `[]` **Items:** `string` * **`users_analyzed`** `integer` β€” Total users across all cohorts (capped at 10K per query) **Example:** ```json { "project_context": { "goals": [ "Increase activated Agent Analytics accounts" ], "activation_events": [ "signup_completed", "project_created", "first_event_received" ], "glossary": [], "annotations": [] }, "period": "week", "cohorts": [ { "date": "2026-01-27", "users": 142, "retained": [ 142, 64, 55, 46 ], "rates": [ 1, 0.451, 0.387, 0.324 ] } ], "average_rates": [ 1, 0.441, 0.373, 0.324 ], "users_analyzed": 560 } ``` ### Project - **Type:**`object` * **`allowed_origins`** `string` * **`id`** `string` * **`name`** `string` * **`project_token`** `string` * **`source_scan_id`** `string | null` β€” Website analysis id linked during project creation, when present. * **`total_events`** `integer` * **`total_reads`** `integer` **Example:** ```json { "id": "", "name": "my-site", "project_token": "aat_...", "allowed_origins": "*", "total_events": 1, "total_reads": 1, "source_scan_id": null } ``` ### WebsiteScanCreateRequest - **Type:**`object` * **`url` (required)** `string` β€” Website URL to analyze. Anonymous requests are normalized to the root domain. * **`full`** `boolean`, default: `false` β€” Request full analysis. Requires account auth. * **`mode`** `string`, possible values: `"preview", "full"` β€” Alternative way to request preview or full analysis. * **`project`** `string` β€” Project name or id. Required for signed-in portal scans and full analyses; the URL hostname must match the project's configured \`allowed\_origins\`. **Example:** ```json { "url": "https://example.com/pricing", "full": false, "mode": "preview", "project": "my-site" } ``` ### WebsiteScanUpgradeRequest - **Type:**`object` * **`project`** `string` β€” Required project name or id used while upgrading. The analysis hostname must match the project's configured \`allowed\_origins\`. * **`resume_token`** `string` β€” One-analysis \`rst\_\*\` resume token from an anonymous preview. **Example:** ```json { "resume_token": "rst_...", "project": "my-site" } ``` ### WebsiteScanEventRecommendation - **Type:**`object` * **`agent_capability_after_install` (required)** `string` * **`current_blindspot` (required)** `string` * **`event` (required)** `string` β€” Stable snake\_case custom event name. Recommendations should not duplicate automatic tracker signals such as page\_view. * **`implementation_hint` (required)** `string` β€” Tracker-aware implementation guidance, for example data-aa-event attributes, data-aa-impression attributes, window\.aa.track(...), server-side tracking for durable outcomes, aa.identify()/aa.set(...) after auth, or script opt-ins when they unlock a concrete decision. * **`priority` (required)** `integer` * **`properties` (required)** `array` β€” Practical property names to capture with the event. Automatic tracker properties such as path, referrer, UTMs, device fields, country, session IDs, and first-touch attribution are already present on every event. **Items:** `string` * **`unlocks_questions` (required)** `array` **Items:** `string` * **`why_this_matters_now` (required)** `string` **Example:** ```json { "event": "signup_started", "priority": 1, "why_this_matters_now": "This marks the moment intent becomes commitment.", "current_blindspot": "You cannot see whether CTA clicks turn into signup attempts.", "unlocks_questions": [ "Which pages create signup starts?", "Where does signup intent drop?" ], "agent_capability_after_install": "Your agent can detect where intent drops before account creation.", "properties": [ "page_path", "entry_source", "auth_method" ], "implementation_hint": "" } ``` ### WebsiteScanResult - **Type:**`object` Decision-oriented instrumentation plan. Preview responses cap `minimum_viable_instrumentation` at 3-5 events; full results cap it at 5-8 events. Recommendations are tracker-aware and should not spend custom event slots on automatic page\_view, attribution, device, geography, session, or visitor fields. - **`advanced_tracking_later`** `array` β€” Agent Analytics tracker capabilities to consider after the first useful page event is installed. **Items:** - **`capability`** `string` - **`implementation_hint`** `string` - **`why`** `string` - **`after_install_agent_behavior`** `array` **Items:** `string` - **`analytics_detected`** `object` β€” Supporting context only; the recommendation does not lead with detected providers. - **`business_events_later`** `array` β€” Valuable inferred product, backend, or post-signup events that are not part of the first supplied-page install list. **Items:** - **`event`** `string` - **`where_to_instrument`** `string` - **`why`** `string` - **`current_blindspots`** `array` **Items:** `string` - **`framing`** `string` - **`goal_driven_funnels`** `array` **Items:** - **`bottleneck_detection`** `string` - **`decision`** `string` - **`name`** `string` - **`steps`** `array` **Items:** `string` - **`hostname`** `string` - **`minimum_viable_instrumentation`** `array` **Items:** - **`agent_capability_after_install` (required)** `string` - **`current_blindspot` (required)** `string` - **`event` (required)** `string` β€” Stable snake\_case custom event name. Recommendations should not duplicate automatic tracker signals such as page\_view. - **`implementation_hint` (required)** `string` β€” Tracker-aware implementation guidance, for example data-aa-event attributes, data-aa-impression attributes, window\.aa.track(...), server-side tracking for durable outcomes, aa.identify()/aa.set(...) after auth, or script opt-ins when they unlock a concrete decision. - **`priority` (required)** `integer` - **`properties` (required)** `array` β€” Practical property names to capture with the event. Automatic tracker properties such as path, referrer, UTMs, device fields, country, session IDs, and first-touch attribution are already present on every event. **Items:** `string` - **`unlocks_questions` (required)** `array` **Items:** `string` - **`why_this_matters_now` (required)** `string` - **`normalized_url`** `string` - **`not_needed_yet`** `array` **Items:** - **`event`** `string` - **`reason`** `string` - **`revisit_when`** `string` - **`suggested_ab_tests`** `array` β€” Compact experiment ideas tied to the recommended page UI events. **Items:** - **`hypothesis`** `string` - **`name`** `string` - **`success_event`** `string` - **`variants`** `array` **Items:** `string` **Example:** ```json { "framing": "fastest_path_to_useful_analytics", "normalized_url": "https://example.com/", "hostname": "example.com", "current_blindspots": [ "" ], "minimum_viable_instrumentation": [ { "event": "signup_started", "priority": 1, "why_this_matters_now": "This marks the moment intent becomes commitment.", "current_blindspot": "You cannot see whether CTA clicks turn into signup attempts.", "unlocks_questions": [ "Which pages create signup starts?", "Where does signup intent drop?" ], "agent_capability_after_install": "Your agent can detect where intent drops before account creation.", "properties": [ "page_path", "entry_source", "auth_method" ], "implementation_hint": "" } ], "not_needed_yet": [ { "event": "", "reason": "", "revisit_when": "" } ], "goal_driven_funnels": [ { "name": "", "steps": [ "" ], "decision": "", "bottleneck_detection": "" } ], "after_install_agent_behavior": [ "" ], "business_events_later": [ { "event": "", "why": "", "where_to_instrument": "" } ], "advanced_tracking_later": [ { "capability": "data-aa-impression", "why": "", "implementation_hint": "" } ], "suggested_ab_tests": [ { "name": "", "hypothesis": "", "variants": [ "" ], "success_event": "" } ], "analytics_detected": {} } ``` ### WebsiteScanResponse - **Type:**`object` * **`agent_handoff`** `object` - **`analysis_id`** `string` - **`label`** `string` - **`prompt`** `string` - **`resume_token`** `string | null` * **`analysis_id`** `string` * **`cached`** `boolean` * **`hostname`** `string` * **`mode`** `string` * **`normalized_url`** `string` * **`ok`** `boolean` * **`preview`** `object` β€” Decision-oriented instrumentation plan. Preview responses cap \`minimum\_viable\_instrumentation\` at 3-5 events; full results cap it at 5-8 events. Recommendations are tracker-aware and should not spend custom event slots on automatic page\_view, attribution, device, geography, session, or visitor fields. - **`advanced_tracking_later`** `array` β€” Agent Analytics tracker capabilities to consider after the first useful page event is installed. **Items:** - **`capability`** `string` - **`implementation_hint`** `string` - **`why`** `string` - **`after_install_agent_behavior`** `array` **Items:** `string` - **`analytics_detected`** `object` β€” Supporting context only; the recommendation does not lead with detected providers. - **`business_events_later`** `array` β€” Valuable inferred product, backend, or post-signup events that are not part of the first supplied-page install list. **Items:** - **`event`** `string` - **`where_to_instrument`** `string` - **`why`** `string` - **`current_blindspots`** `array` **Items:** `string` - **`framing`** `string` - **`goal_driven_funnels`** `array` **Items:** - **`bottleneck_detection`** `string` - **`decision`** `string` - **`name`** `string` - **`steps`** `array` **Items:** `string` - **`hostname`** `string` - **`minimum_viable_instrumentation`** `array` **Items:** - **`agent_capability_after_install` (required)** `string` - **`current_blindspot` (required)** `string` - **`event` (required)** `string` β€” Stable snake\_case custom event name. Recommendations should not duplicate automatic tracker signals such as page\_view. - **`implementation_hint` (required)** `string` β€” Tracker-aware implementation guidance, for example data-aa-event attributes, data-aa-impression attributes, window\.aa.track(...), server-side tracking for durable outcomes, aa.identify()/aa.set(...) after auth, or script opt-ins when they unlock a concrete decision. - **`priority` (required)** `integer` - **`properties` (required)** `array` β€” Practical property names to capture with the event. Automatic tracker properties such as path, referrer, UTMs, device fields, country, session IDs, and first-touch attribution are already present on every event. **Items:** `string` - **`unlocks_questions` (required)** `array` **Items:** `string` - **`why_this_matters_now` (required)** `string` - **`normalized_url`** `string` - **`not_needed_yet`** `array` **Items:** - **`event`** `string` - **`reason`** `string` - **`revisit_when`** `string` - **`suggested_ab_tests`** `array` β€” Compact experiment ideas tied to the recommended page UI events. **Items:** - **`hypothesis`** `string` - **`name`** `string` - **`success_event`** `string` - **`variants`** `array` **Items:** `string` * **`result`** `object` β€” Decision-oriented instrumentation plan. Preview responses cap \`minimum\_viable\_instrumentation\` at 3-5 events; full results cap it at 5-8 events. Recommendations are tracker-aware and should not spend custom event slots on automatic page\_view, attribution, device, geography, session, or visitor fields. - **`advanced_tracking_later`** `array` β€” Agent Analytics tracker capabilities to consider after the first useful page event is installed. **Items:** - **`capability`** `string` - **`implementation_hint`** `string` - **`why`** `string` - **`after_install_agent_behavior`** `array` **Items:** `string` - **`analytics_detected`** `object` β€” Supporting context only; the recommendation does not lead with detected providers. - **`business_events_later`** `array` β€” Valuable inferred product, backend, or post-signup events that are not part of the first supplied-page install list. **Items:** - **`event`** `string` - **`where_to_instrument`** `string` - **`why`** `string` - **`current_blindspots`** `array` **Items:** `string` - **`framing`** `string` - **`goal_driven_funnels`** `array` **Items:** - **`bottleneck_detection`** `string` - **`decision`** `string` - **`name`** `string` - **`steps`** `array` **Items:** `string` - **`hostname`** `string` - **`minimum_viable_instrumentation`** `array` **Items:** - **`agent_capability_after_install` (required)** `string` - **`current_blindspot` (required)** `string` - **`event` (required)** `string` β€” Stable snake\_case custom event name. Recommendations should not duplicate automatic tracker signals such as page\_view. - **`implementation_hint` (required)** `string` β€” Tracker-aware implementation guidance, for example data-aa-event attributes, data-aa-impression attributes, window\.aa.track(...), server-side tracking for durable outcomes, aa.identify()/aa.set(...) after auth, or script opt-ins when they unlock a concrete decision. - **`priority` (required)** `integer` - **`properties` (required)** `array` β€” Practical property names to capture with the event. Automatic tracker properties such as path, referrer, UTMs, device fields, country, session IDs, and first-touch attribution are already present on every event. **Items:** `string` - **`unlocks_questions` (required)** `array` **Items:** `string` - **`why_this_matters_now` (required)** `string` - **`normalized_url`** `string` - **`not_needed_yet`** `array` **Items:** - **`event`** `string` - **`reason`** `string` - **`revisit_when`** `string` - **`suggested_ab_tests`** `array` β€” Compact experiment ideas tied to the recommended page UI events. **Items:** - **`hypothesis`** `string` - **`name`** `string` - **`success_event`** `string` - **`variants`** `array` **Items:** `string` * **`resume_token`** `string` β€” Present only when creating a new anonymous preview. Store the token securely; the server stores only its hash. * **`status`** `string`, possible values: `"pending", "running", "succeeded", "failed"` **Example:** ```json { "ok": true, "analysis_id": "scan_...", "status": "succeeded", "mode": "anonymous_preview", "normalized_url": "https://example.com/", "hostname": "example.com", "cached": true, "resume_token": "rst_...", "preview": { "framing": "fastest_path_to_useful_analytics", "normalized_url": "https://example.com/", "hostname": "example.com", "current_blindspots": [ "" ], "minimum_viable_instrumentation": [ { "event": "signup_started", "priority": 1, "why_this_matters_now": "This marks the moment intent becomes commitment.", "current_blindspot": "You cannot see whether CTA clicks turn into signup attempts.", "unlocks_questions": [ "Which pages create signup starts?", "Where does signup intent drop?" ], "agent_capability_after_install": "Your agent can detect where intent drops before account creation.", "properties": [ "page_path", "entry_source", "auth_method" ], "implementation_hint": "" } ], "not_needed_yet": [ { "event": "", "reason": "", "revisit_when": "" } ], "goal_driven_funnels": [ { "name": "", "steps": [ "" ], "decision": "", "bottleneck_detection": "" } ], "after_install_agent_behavior": [ "" ], "business_events_later": [ { "event": "", "why": "", "where_to_instrument": "" } ], "advanced_tracking_later": [ { "capability": "data-aa-impression", "why": "", "implementation_hint": "" } ], "suggested_ab_tests": [ { "name": "", "hypothesis": "", "variants": [ "" ], "success_event": "" } ], "analytics_detected": {} }, "result": { "framing": "fastest_path_to_useful_analytics", "normalized_url": "https://example.com/", "hostname": "example.com", "current_blindspots": [ "" ], "minimum_viable_instrumentation": [ { "event": "signup_started", "priority": 1, "why_this_matters_now": "This marks the moment intent becomes commitment.", "current_blindspot": "You cannot see whether CTA clicks turn into signup attempts.", "unlocks_questions": [ "Which pages create signup starts?", "Where does signup intent drop?" ], "agent_capability_after_install": "Your agent can detect where intent drops before account creation.", "properties": [ "page_path", "entry_source", "auth_method" ], "implementation_hint": "" } ], "not_needed_yet": [ { "event": "", "reason": "", "revisit_when": "" } ], "goal_driven_funnels": [ { "name": "", "steps": [ "" ], "decision": "", "bottleneck_detection": "" } ], "after_install_agent_behavior": [ "" ], "business_events_later": [ { "event": "", "why": "", "where_to_instrument": "" } ], "advanced_tracking_later": [ { "capability": "data-aa-impression", "why": "", "implementation_hint": "" } ], "suggested_ab_tests": [ { "name": "", "hypothesis": "", "variants": [ "" ], "success_event": "" } ], "analytics_detected": {} }, "agent_handoff": { "label": "Give your agent analytics judgment", "analysis_id": "", "resume_token": null, "prompt": "" } } ``` ### WebsiteScanBusyError - **Type:** **Example:** ### LiveSnapshotResponse - **Type:**`object` * **`active_sessions`** `integer` β€” Unique session\_ids in the time window * **`active_visitors`** `integer` β€” Unique user\_ids in the time window * **`events_per_minute`** `integer` * **`project`** `string` * **`project_context`** `object` - **`activation_events`** `array`, default: `[]` β€” Event names that define activation or the main success path. **Items:** `string` - **`annotations`** `array`, default: `[]` β€” Major date annotations. Project-scoped analytics responses include only annotations inside the requested date range plus one day before and after. **Items:** - **`occurred_at` (required)** `string`, format: `date-time` β€” ISO-8601 datetime when a major product change happened. Stored as a UTC ISO string. - **`title` (required)** `string` β€” Short annotation title for a meaningful product, pricing, release, landing-page, onboarding, feature, or experiment change. - **`note`** `string` β€” Optional short note. Do not store commit logs, PII, secrets, or long release notes. - **`glossary`** `array`, default: `[]` **Items:** - **`definition` (required)** `string` β€” Short meaning that helps an agent interpret analytics results. - **`event_name` (required)** `string` β€” Event name this glossary entry explains. Use \`/properties\` or \`/properties/received\` to inspect current project event names before updating. - **`term` (required)** `string` β€” Human or product term for the event. - **`goals`** `array`, default: `[]` **Items:** `string` * **`recent_events`** `array` β€” Last 10 events, newest first **Items:** - **`event`** `string` - **`properties`** `object | null` - **`timestamp`** `number` - **`user_id`** `string | null` * **`timestamp`** `number` * **`top_events`** `array` **Items:** - **`count`** `integer` - **`event`** `string` * **`top_pages`** `array` **Items:** - **`path`** `string` - **`visitors`** `integer` * **`window_seconds`** `integer` **Example:** ```json { "project": "my-site", "project_context": { "goals": [ "Increase activated Agent Analytics accounts" ], "activation_events": [ "signup_completed", "project_created", "first_event_received" ], "glossary": [], "annotations": [] }, "window_seconds": 60, "timestamp": 1708000060000, "active_visitors": 12, "active_sessions": 8, "events_per_minute": 47, "top_pages": [ { "path": "/", "visitors": 5 } ], "top_events": [ { "event": "page_view", "count": 32 } ], "recent_events": [ { "event": "", "properties": null, "user_id": null, "timestamp": 1 } ] } ``` ### AllSitesPeriod - **Type:**`object` * **`from`** `string`, format: `date` * **`label`** `string`, possible values: `"1d", "7d", "14d", "30d", "90d"` * **`previous_from`** `string`, format: `date` * **`previous_to`** `string`, format: `date` * **`to`** `string`, format: `date` **Example:** ```json { "label": "7d", "from": "2026-03-03", "to": "2026-03-09", "previous_from": "2026-02-24", "previous_to": "2026-03-02" } ``` ### AllSitesMetricDelta - **Type:**`object` * **`change`** `integer` * **`change_pct`** `object` * **`current`** `integer` * **`previous`** `integer` **Example:** ```json { "current": 120, "previous": 90, "change": 30, "change_pct": 33 } ``` ### AllSitesSummary - **Type:**`object` * **`active_projects`** `integer` * **`total_events`** `object` - **`change`** `integer` - **`change_pct`** `object` - **`current`** `integer` - **`previous`** `integer` * **`total_projects`** `integer` **Example:** ```json { "total_projects": 3, "active_projects": 2, "total_events": { "current": 120, "previous": 90, "change": 30, "change_pct": 33 } } ``` ### AllSitesTimeSeriesPoint - **Type:**`object` * **`date`** `string`, format: `date` * **`events`** `integer` **Example:** ```json { "date": "2026-03-09", "events": 40 } ``` ### AllSitesProjectSummary - **Type:**`object` * **`events`** `integer` * **`id`** `string` * **`last_active_date`** `object` * **`name`** `string` * **`share_pct`** `number` **Example:** ```json { "id": "proj_123", "name": "my-site", "events": 80, "share_pct": 66.7, "last_active_date": "2026-03-09" } ``` ### AllSitesOverviewResponse - **Type:**`object` * **`period`** `object` - **`from`** `string`, format: `date` - **`label`** `string`, possible values: `"1d", "7d", "14d", "30d", "90d"` - **`previous_from`** `string`, format: `date` - **`previous_to`** `string`, format: `date` - **`to`** `string`, format: `date` * **`projects`** `array` **Items:** - **`events`** `integer` - **`id`** `string` - **`last_active_date`** `object` - **`name`** `string` - **`share_pct`** `number` * **`remaining_projects`** `integer` * **`scope`** `string`, possible values: `"account"` * **`summary`** `object` - **`active_projects`** `integer` - **`total_events`** `object` - **`change`** `integer` - **`change_pct`** `object` - **`current`** `integer` - **`previous`** `integer` - **`total_projects`** `integer` * **`time_series`** `array` **Items:** - **`date`** `string`, format: `date` - **`events`** `integer` **Example:** ```json { "scope": "account", "period": { "label": "7d", "from": "2026-03-03", "to": "2026-03-09", "previous_from": "2026-02-24", "previous_to": "2026-03-02" }, "summary": { "total_projects": 3, "active_projects": 2, "total_events": { "current": 120, "previous": 90, "change": 30, "change_pct": 33 } }, "time_series": [ { "date": "2026-03-09", "events": 40 } ], "projects": [ { "id": "proj_123", "name": "my-site", "events": 80, "share_pct": 66.7, "last_active_date": "2026-03-09" } ], "remaining_projects": 1 } ``` ### BotTrafficMetricDelta - **Type:**`object` * **`change`** `integer` * **`change_pct`** `object` * **`current`** `integer` * **`previous`** `integer` **Example:** ```json { "current": 5, "previous": 1, "change": 4, "change_pct": 400 } ``` ### BotTrafficTimeSeriesPoint - **Type:**`object` * **`date`** `string`, format: `date` * **`dropped_events`** `integer` * **`requests`** `integer` **Example:** ```json { "date": "2026-03-13", "requests": 5, "dropped_events": 7 } ``` ### BotTrafficCategorySummary - **Type:**`object` * **`category`** `string` * **`dropped_events`** `integer` * **`requests`** `integer` * **`share_pct`** `number` **Example:** ```json { "category": "ai_agent", "requests": 3, "dropped_events": 5, "share_pct": 60 } ``` ### BotTrafficActorSummary - **Type:**`object` * **`actor`** `string` * **`category`** `string` * **`dropped_events`** `integer` * **`last_seen_at`** `object` * **`requests`** `integer` **Example:** ```json { "actor": "ChatGPT-User", "category": "ai_agent", "requests": 3, "dropped_events": 5, "last_seen_at": 1773459600000 } ``` ### BotTrafficProjectSummary - **Type:**`object` * **`dropped_events`** `integer` * **`id`** `string` * **`last_seen_at`** `object` * **`name`** `string` * **`requests`** `integer` * **`share_pct`** `number` **Example:** ```json { "id": "proj_123", "name": "my-site", "requests": 3, "dropped_events": 4, "share_pct": 60, "last_seen_at": 1773459600000 } ``` ### BotTrafficProjectSummaryMetrics - **Type:**`object` * **`automated_requests`** `object` - **`change`** `integer` - **`change_pct`** `object` - **`current`** `integer` - **`previous`** `integer` * **`dropped_events`** `object` - **`change`** `integer` - **`change_pct`** `object` - **`current`** `integer` - **`previous`** `integer` * **`last_seen_at`** `object` **Example:** ```json { "automated_requests": { "current": 5, "previous": 1, "change": 4, "change_pct": 400 }, "dropped_events": { "current": 5, "previous": 1, "change": 4, "change_pct": 400 }, "last_seen_at": 1773459600000 } ``` ### BotTrafficAccountSummary - **Type:**`object` * **`active_projects`** `integer` * **`automated_requests`** `object` - **`change`** `integer` - **`change_pct`** `object` - **`current`** `integer` - **`previous`** `integer` * **`dropped_events`** `object` - **`change`** `integer` - **`change_pct`** `object` - **`current`** `integer` - **`previous`** `integer` * **`last_seen_at`** `object` * **`total_projects`** `integer` **Example:** ```json { "automated_requests": { "current": 5, "previous": 1, "change": 4, "change_pct": 400 }, "dropped_events": { "current": 5, "previous": 1, "change": 4, "change_pct": 400 }, "active_projects": 1, "total_projects": 4, "last_seen_at": 1773459600000 } ``` ### BotTrafficOverviewResponse - **Type:**`object` * **`actors`** `array` **Items:** - **`actor`** `string` - **`category`** `string` - **`dropped_events`** `integer` - **`last_seen_at`** `object` - **`requests`** `integer` * **`categories`** `array` **Items:** - **`category`** `string` - **`dropped_events`** `integer` - **`requests`** `integer` - **`share_pct`** `number` * **`period`** `object` - **`from`** `string`, format: `date` - **`label`** `string`, possible values: `"1d", "7d", "14d", "30d", "90d"` - **`previous_from`** `string`, format: `date` - **`previous_to`** `string`, format: `date` - **`to`** `string`, format: `date` * **`project`** `string` * **`project_context`** `object` - **`activation_events`** `array`, default: `[]` β€” Event names that define activation or the main success path. **Items:** `string` - **`annotations`** `array`, default: `[]` β€” Major date annotations. Project-scoped analytics responses include only annotations inside the requested date range plus one day before and after. **Items:** - **`occurred_at` (required)** `string`, format: `date-time` β€” ISO-8601 datetime when a major product change happened. Stored as a UTC ISO string. - **`title` (required)** `string` β€” Short annotation title for a meaningful product, pricing, release, landing-page, onboarding, feature, or experiment change. - **`note`** `string` β€” Optional short note. Do not store commit logs, PII, secrets, or long release notes. - **`glossary`** `array`, default: `[]` **Items:** - **`definition` (required)** `string` β€” Short meaning that helps an agent interpret analytics results. - **`event_name` (required)** `string` β€” Event name this glossary entry explains. Use \`/properties\` or \`/properties/received\` to inspect current project event names before updating. - **`term` (required)** `string` β€” Human or product term for the event. - **`goals`** `array`, default: `[]` **Items:** `string` * **`scope`** `string`, possible values: `"project"` * **`summary`** `object` - **`automated_requests`** `object` - **`change`** `integer` - **`change_pct`** `object` - **`current`** `integer` - **`previous`** `integer` - **`dropped_events`** `object` - **`change`** `integer` - **`change_pct`** `object` - **`current`** `integer` - **`previous`** `integer` - **`last_seen_at`** `object` * **`time_series`** `array` **Items:** - **`date`** `string`, format: `date` - **`dropped_events`** `integer` - **`requests`** `integer` **Example:** ```json { "scope": "project", "project": "my-site", "project_context": { "goals": [ "Increase activated Agent Analytics accounts" ], "activation_events": [ "signup_completed", "project_created", "first_event_received" ], "glossary": [], "annotations": [] }, "period": { "label": "7d", "from": "2026-03-03", "to": "2026-03-09", "previous_from": "2026-02-24", "previous_to": "2026-03-02" }, "summary": { "automated_requests": { "current": 5, "previous": 1, "change": 4, "change_pct": 400 }, "dropped_events": { "current": 5, "previous": 1, "change": 4, "change_pct": 400 }, "last_seen_at": 1773459600000 }, "categories": [ { "category": "ai_agent", "requests": 3, "dropped_events": 5, "share_pct": 60 } ], "actors": [ { "actor": "ChatGPT-User", "category": "ai_agent", "requests": 3, "dropped_events": 5, "last_seen_at": 1773459600000 } ], "time_series": [ { "date": "2026-03-13", "requests": 5, "dropped_events": 7 } ] } ``` ### AllSitesBotTrafficOverviewResponse - **Type:**`object` * **`categories`** `array` **Items:** - **`category`** `string` - **`dropped_events`** `integer` - **`requests`** `integer` - **`share_pct`** `number` * **`period`** `object` - **`from`** `string`, format: `date` - **`label`** `string`, possible values: `"1d", "7d", "14d", "30d", "90d"` - **`previous_from`** `string`, format: `date` - **`previous_to`** `string`, format: `date` - **`to`** `string`, format: `date` * **`projects`** `array` **Items:** - **`dropped_events`** `integer` - **`id`** `string` - **`last_seen_at`** `object` - **`name`** `string` - **`requests`** `integer` - **`share_pct`** `number` * **`remaining_projects`** `integer` * **`scope`** `string`, possible values: `"account"` * **`summary`** `object` - **`active_projects`** `integer` - **`automated_requests`** `object` - **`change`** `integer` - **`change_pct`** `object` - **`current`** `integer` - **`previous`** `integer` - **`dropped_events`** `object` - **`change`** `integer` - **`change_pct`** `object` - **`current`** `integer` - **`previous`** `integer` - **`last_seen_at`** `object` - **`total_projects`** `integer` * **`time_series`** `array` **Items:** - **`date`** `string`, format: `date` - **`dropped_events`** `integer` - **`requests`** `integer` **Example:** ```json { "scope": "account", "period": { "label": "7d", "from": "2026-03-03", "to": "2026-03-09", "previous_from": "2026-02-24", "previous_to": "2026-03-02" }, "summary": { "automated_requests": { "current": 5, "previous": 1, "change": 4, "change_pct": 400 }, "dropped_events": { "current": 5, "previous": 1, "change": 4, "change_pct": 400 }, "active_projects": 1, "total_projects": 4, "last_seen_at": 1773459600000 }, "categories": [ { "category": "ai_agent", "requests": 3, "dropped_events": 5, "share_pct": 60 } ], "projects": [ { "id": "proj_123", "name": "my-site", "requests": 3, "dropped_events": 4, "share_pct": 60, "last_seen_at": 1773459600000 } ], "remaining_projects": 3, "time_series": [ { "date": "2026-03-13", "requests": 5, "dropped_events": 7 } ] } ``` ### AccountResponse - **Type:**`object` * **`created_at`** `string` * **`email`** `string` * **`github_login`** `string | null` * **`id`** `string` * **`monthly_spend_cap_dollars`** `number | null` * **`projects_count`** `integer` * **`tier`** `string`, possible values: `"free", "pro"` * **`tier_limits`** `object` - **`max_events_per_month`** `integer` - **`max_projects`** `integer` - **`max_reads_per_month`** `integer` - **`rate_limit_rpm`** `integer` - **`retention_days`** `integer` **Example:** ```json { "id": "acc_free123", "email": "free@example.com", "github_login": "freeuser", "tier": "free", "created_at": "2026-02-01T12:00:00.000Z", "projects_count": 2, "tier_limits": { "max_events_per_month": 100000, "max_projects": 2, "max_reads_per_month": 500, "retention_days": 90, "rate_limit_rpm": 10 }, "monthly_spend_cap_dollars": null } ``` ### AgentSessionStartRequest - **Type:**`object` * **`client_type` (required)** `string` β€” Runtime type such as \`cli\`, \`mcp\`, \`paperclip\`, or \`openclaw\`. * **`callback_url`** `string | null` β€” Required for interactive mode. Local loopback callback URL. * **`client_instance_id`** `string | null` * **`client_name`** `string | null` * **`code_challenge`** `string | null` β€” Optional PKCE-style challenge for interactive runtimes. * **`label`** `string | null` * **`metadata`** `object | null` * **`mode`** `string`, possible values: `"interactive", "detached"`, default: `"interactive"` * **`scopes`** `array` **Items:** `string`, possible values: `"account:read", "projects:write", "analytics:read", "experiments:write", "feedback:write", "live:read"` **Example:** ```json { "mode": "interactive", "client_type": "cli", "client_name": "Agent Analytics CLI", "client_instance_id": "pid:12345", "label": "Paperclip Workspace", "callback_url": "http://127.0.0.1:43123/callback", "scopes": [ "account:read" ], "code_challenge": null, "metadata": null } ``` ### AgentSessionStartResponse - **Type:**`object` * **`auth_request_id`** `string` * **`authorize_url`** `string` * **`expires_at`** `integer` * **`mode`** `string`, possible values: `"interactive", "detached"` * **`ok`** `boolean` * **`poll_token`** `string` * **`scopes`** `array` **Items:** `string` **Example:** ```json { "ok": true, "auth_request_id": "req_agent123", "authorize_url": "https://api.agentanalytics.sh/agent-sessions/authorize/req_agent123", "poll_token": "aap_polltoken", "mode": "interactive", "expires_at": 1775079600000, "scopes": [ "" ] } ``` ### AgentSessionPollRequest - **Type:**`object` * **`auth_request_id` (required)** `string` * **`poll_token` (required)** `string` **Example:** ```json { "auth_request_id": "", "poll_token": "" } ``` ### AgentSessionPollResponse - **Type:**`object` * **`account_id`** `object` * **`approved_email`** `object` * **`exchange_code`** `object` * **`status`** `string`, possible values: `"pending", "approved", "exchanged", "revoked", "expired"` **Example:** ```json { "status": "pending", "exchange_code": "", "account_id": "", "approved_email": "" } ``` ### AgentSessionExchangeRequest - **Type:**`object` * **`auth_request_id` (required)** `string` * **`exchange_code` (required)** `string` * **`code_verifier`** `string | null` β€” Required when the auth request was started with a code challenge. **Example:** ```json { "auth_request_id": "", "exchange_code": "", "code_verifier": null } ``` ### AgentSessionIssued - **Type:**`object` * **`access_expires_at`** `integer` * **`access_token`** `string` * **`id`** `string` * **`refresh_expires_at`** `integer` * **`refresh_token`** `string` * **`scopes`** `array` **Items:** `string` **Example:** ```json { "id": "", "access_token": "aas_123", "refresh_token": "aar_123", "access_expires_at": 1, "refresh_expires_at": 1, "scopes": [ "" ] } ``` ### AgentSessionExchangeResponse - **Type:**`object` * **`account`** `object` - **`email`** `string` - **`github_login`** `object` - **`google_name`** `object` - **`id`** `string` - **`tier`** `string`, possible values: `"free", "pro"` * **`agent_session`** `object` - **`access_expires_at`** `integer` - **`access_token`** `string` - **`id`** `string` - **`refresh_expires_at`** `integer` - **`refresh_token`** `string` - **`scopes`** `array` **Items:** `string` * **`ok`** `boolean` **Example:** ```json { "ok": true, "agent_session": { "id": "", "access_token": "aas_123", "refresh_token": "aar_123", "access_expires_at": 1, "refresh_expires_at": 1, "scopes": [ "" ] }, "account": { "id": "", "email": "", "github_login": "", "google_name": "", "tier": "free" } } ``` ### AgentSessionRefreshRequest - **Type:**`object` * **`refresh_token` (required)** `string` **Example:** ```json { "refresh_token": "" } ``` ### AgentSessionRefreshResponse - **Type:**`object` * **`agent_session`** `object` - **`access_expires_at`** `integer` - **`access_token`** `string` - **`account`** `object` - **`email`** `string` - **`github_login`** `object` - **`google_name`** `object` - **`id`** `string` - **`tier`** `string`, possible values: `"free", "pro"` - **`refresh_expires_at`** `integer` - **`refresh_token`** `string` - **`scopes`** `array` **Items:** `string` - **`session_id`** `string` * **`ok`** `boolean` **Example:** ```json { "ok": true, "agent_session": { "session_id": "", "access_token": "", "refresh_token": "", "access_expires_at": 1, "refresh_expires_at": 1, "account": { "id": "", "email": "", "github_login": "", "google_name": "", "tier": "free" }, "scopes": [ "" ] } } ``` ### AgentSessionSummary - **Type:**`object` * **`access_expires_at`** `integer` * **`client_instance_id`** `object` * **`client_name`** `object` * **`client_type`** `string` * **`created_at`** `integer` * **`id`** `string` * **`label`** `object` * **`last_used_at`** `integer` * **`refresh_expires_at`** `integer` * **`revoked_at`** `object` * **`scopes`** `array` **Items:** `string` * **`status`** `string`, possible values: `"active", "revoked"` **Example:** ```json { "id": "", "client_type": "", "client_name": "", "client_instance_id": "", "label": "", "scopes": [ "" ], "status": "active", "created_at": 1, "last_used_at": 1, "access_expires_at": 1, "refresh_expires_at": 1, "revoked_at": 1 } ``` ### FeedbackRequest - **Type:**`object` * **`message` (required)** `string` β€” Sanitized summary of the friction, missing capability, or workflow problem. * **`command`** `string` β€” Optional CLI command or workflow step that led to the issue. * **`context`** `string` β€” Optional sanitized context. Do not include private owner details, secrets, or raw customer data. * **`project`** `string` β€” Optional project name for context. **Example:** ```json { "message": "The agent had to calculate funnel drop-off manually instead of using a built-in report.", "project": "my-site", "command": "agent-analytics funnel my-site --steps \"page_view,signup,purchase\"", "context": "The agent understood the goal but had to compute the percentages manually." } ``` ### Experiment - **Type:**`object` * **`account_id`** `string` * **`completed_at`** `string | null` * **`created_at`** `string` * **`goal_event`** `string` * **`id`** `string` * **`name`** `string` * **`project_id`** `string` * **`status`** `string`, possible values: `"active", "paused", "completed"` * **`updated_at`** `string` * **`variants`** `array` **Items:** - **`key`** `string` - **`weight`** `integer` * **`winner`** `string | null` β€” Variant key, set when status is completed **Example:** ```json { "id": "exp_a1b2c3d4e5f6g7h8", "project_id": "", "account_id": "", "name": "signup_cta", "variants": [ { "key": "control", "weight": 50 } ], "goal_event": "signup", "status": "active", "winner": null, "created_at": "", "updated_at": "", "completed_at": null } ``` ### ExperimentResults - **Type:**`object` * **`lift`** `object` * **`probability_best`** `object` * **`recommendation`** `string` * **`sufficient_data`** `boolean` * **`variants`** `array` **Items:** - **`conversion_rate`** `number` - **`conversions`** `integer` - **`exposures`** `integer` - **`key`** `string` - **`unique_users`** `integer` **Example:** ```json { "variants": [ { "key": "control", "exposures": 520, "unique_users": 480, "conversions": 48, "conversion_rate": 0.1 } ], "probability_best": { "control": 0.06, "new_cta": 0.94 }, "lift": { "control": -0.32, "new_cta": 0.47 }, "sufficient_data": true, "recommendation": "'new_cta' is the winner with 94% probability (47% lift over baseline)" } ``` ## Additional Response Examples ### `GET /account` Status: `200` Β· Content-Type: `application/json` #### freeTier β€” Free tier account ```json { "id": "acc_free123", "email": "free@example.com", "github_login": "freeuser", "tier": "free", "created_at": "2026-02-01T12:00:00.000Z", "projects_count": 2, "tier_limits": { "max_events_per_month": 100000, "max_projects": 2, "max_reads_per_month": 500, "retention_days": 90, "rate_limit_rpm": 10 }, "monthly_spend_cap_dollars": null } ``` #### proTier β€” Pro tier account ```json { "id": "acc_pro123", "email": "pro@example.com", "github_login": "prouser", "tier": "pro", "created_at": "2026-02-01T12:00:00.000Z", "projects_count": 42, "tier_limits": { "max_events_per_month": -1, "max_projects": -1, "max_reads_per_month": -1, "retention_days": 365, "rate_limit_rpm": 1000 }, "monthly_spend_cap_dollars": 50 } ``` ### `GET /bot-traffic` Status: `200` Β· Content-Type: `application/json` #### empty β€” Empty state ```json { "scope": "project", "project": "my-site", "period": { "label": "7d", "from": "2026-03-07", "to": "2026-03-13", "previous_from": "2026-02-28", "previous_to": "2026-03-06" }, "summary": { "automated_requests": { "current": 0, "previous": 0, "change": 0, "change_pct": 0 }, "dropped_events": { "current": 0, "previous": 0, "change": 0, "change_pct": 0 }, "last_seen_at": null }, "categories": [], "actors": [], "time_series": [ { "date": "2026-03-13", "requests": 0, "dropped_events": 0 } ] } ``` #### active β€” Active bot traffic ```json { "scope": "project", "project": "my-site", "period": { "label": "7d", "from": "2026-03-07", "to": "2026-03-13", "previous_from": "2026-02-28", "previous_to": "2026-03-06" }, "summary": { "automated_requests": { "current": 5, "previous": 1, "change": 4, "change_pct": 400 }, "dropped_events": { "current": 7, "previous": 1, "change": 6, "change_pct": 600 }, "last_seen_at": 1773459600000 }, "categories": [ { "category": "ai_agent", "requests": 3, "dropped_events": 5, "share_pct": 60 }, { "category": "search_crawler", "requests": 2, "dropped_events": 2, "share_pct": 40 } ], "actors": [ { "actor": "ChatGPT-User", "category": "ai_agent", "requests": 3, "dropped_events": 5, "last_seen_at": 1773459600000 }, { "actor": "Googlebot", "category": "search_crawler", "requests": 2, "dropped_events": 2, "last_seen_at": 1773456000000 } ], "time_series": [ { "date": "2026-03-13", "requests": 5, "dropped_events": 7 } ] } ```