{"files":{"SKILL.md":"---\nname: agent-analytics-api\ndescription: \"Agent Analytics API skill. Use when working with Agent Analytics for track, stats, events. Covers 32 endpoints.\"\nversion: 1.0.0\ngenerator: lapsh\n---\n\n# Agent Analytics API\nAPI version: 1.0.0\n\n## Auth\nApiKey X-API-Key in header | ApiKey token in query\n\n## Base URL\nhttps://api.agentanalytics.sh\n\n## Setup\n1. Set your API key in the appropriate header\n2. GET /stats -- verify access\n3. POST /track -- create first track\n\n## Endpoints\n\n32 endpoints across 19 groups. See references/api-spec.lap for full details.\n\n### track\n| Method | Path | Description |\n|--------|------|-------------|\n| POST | /track | Track a single event |\n| POST | /track/batch | Track multiple events |\n\n### stats\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /stats | Aggregated stats overview |\n\n### events\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /events | Raw event log |\n\n### query\n| Method | Path | Description |\n|--------|------|-------------|\n| POST | /query | Flexible analytics query |\n\n### properties\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /properties | Discover event names and property keys |\n| GET | /properties/received | Property keys by event name |\n\n### sessions\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /sessions | List sessions |\n| GET | /sessions/distribution | Session duration histogram |\n\n### breakdown\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /breakdown | Top property values |\n\n### insights\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /insights | Period-over-period comparison |\n\n### pages\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /pages | Entry/exit page stats |\n\n### heatmap\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /heatmap | Day-of-week x hour traffic grid |\n\n### funnel\n| Method | Path | Description |\n|--------|------|-------------|\n| POST | /funnel | Funnel analysis |\n\n### retention\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /retention | Cohort retention analysis |\n\n### stream\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /stream | Live event stream (SSE) |\n\n### live\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /live | Live snapshot (real-time) |\n\n### projects\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /projects | List all projects |\n| POST | /projects | Create a new project |\n| GET | /projects/{id} | Get project details |\n| PATCH | /projects/{id} | Update a project |\n| DELETE | /projects/{id} | Delete a project |\n\n### account\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /account | Get account info |\n| POST | /account/revoke-key | Revoke and regenerate API key |\n\n### experiments\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /experiments/config | Get experiment config for tracker.js |\n| POST | /experiments | Create an A/B experiment |\n| GET | /experiments | List experiments |\n| GET | /experiments/{id} | Get experiment with live results |\n| PATCH | /experiments/{id} | Update experiment status |\n| DELETE | /experiments/{id} | Delete an experiment |\n\n### health\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /health | Health check |\n\n### tracker.js\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /tracker.js | JavaScript tracker script |\n\n## Common Questions\n\nMatch user requests to endpoints in references/api-spec.lap. Key patterns:\n- \"Create a track?\" -> POST /track\n- \"Create a batch?\" -> POST /track/batch\n- \"List all stats?\" -> GET /stats\n- \"List all events?\" -> GET /events\n- \"Create a query?\" -> POST /query\n- \"List all properties?\" -> GET /properties\n- \"List all received?\" -> GET /properties/received\n- \"List all sessions?\" -> GET /sessions\n- \"List all breakdown?\" -> GET /breakdown\n- \"List all insights?\" -> GET /insights\n- \"List all pages?\" -> GET /pages\n- \"List all distribution?\" -> GET /sessions/distribution\n- \"List all heatmap?\" -> GET /heatmap\n- \"Create a funnel?\" -> POST /funnel\n- \"List all retention?\" -> GET /retention\n- \"List all stream?\" -> GET /stream\n- \"List all live?\" -> GET /live\n- \"List all projects?\" -> GET /projects\n- \"Create a project?\" -> POST /projects\n- \"Get project details?\" -> GET /projects/{id}\n- \"Partially update a project?\" -> PATCH /projects/{id}\n- \"Delete a project?\" -> DELETE /projects/{id}\n- \"List all account?\" -> GET /account\n- \"Create a revoke-key?\" -> POST /account/revoke-key\n- \"List all config?\" -> GET /experiments/config\n- \"Create a experiment?\" -> POST /experiments\n- \"List all experiments?\" -> GET /experiments\n- \"Get experiment details?\" -> GET /experiments/{id}\n- \"Partially update a experiment?\" -> PATCH /experiments/{id}\n- \"Delete a experiment?\" -> DELETE /experiments/{id}\n- \"List all health?\" -> GET /health\n- \"List all tracker.js?\" -> GET /tracker.js\n- \"How to authenticate?\" -> See Auth section\n\n## Response Tips\n- Check response schemas in references/api-spec.lap for field details\n- List endpoints may support pagination; check for limit, offset, or cursor params\n- Create/update endpoints typically return the created/updated object\n\n## CLI\n\n```bash\n# Update this spec to the latest version\nnpx @lap-platform/lapsh get agent-analytics-api -o references/api-spec.lap\n\n# Search for related APIs\nnpx @lap-platform/lapsh search agent-analytics-api\n```\n\n## References\n- Full spec: See references/api-spec.lap for complete endpoint details, parameter tables, and response schemas\n\n> Generated from the official API spec by [LAP](https://lap.sh)\n","references/api-spec.lap":"@lap v0.3\n# Machine-readable API spec. Each @endpoint block is one API call.\n@api Agent Analytics API\n@base https://api.agentanalytics.sh\n@version 1.0.0\n@auth ApiKey X-API-Key in header | ApiKey token in query\n@endpoints 32\n@hint download_for_search\n@toc track(2), stats(1), events(1), query(1), properties(2), sessions(2), breakdown(1), insights(1), pages(1), heatmap(1), funnel(1), retention(1), stream(1), live(1), projects(5), account(2), experiments(6), health(1), tracker.js(1)\n\n@group track\n@endpoint POST /track\n@desc Track a single event\n@required {token: str # Project token (`aat_*`), event: str # Event name (max 256 chars)}\n@optional {properties: map # Arbitrary key-value properties (max 8KB JSON). The tracker auto-populates `path`, `url`, `hostname`, `title`, `referrer`, `screen`, `browser`, `browser_version`, `os`, `device`, `language`, and `utm_*` params., user_id: str # Anonymous user identifier (max 256 chars). The tracker auto-generates one via localStorage., session_id: str # Session identifier (max 256 chars). The tracker auto-generates one via sessionStorage with 30-min inactivity timeout., timestamp: num # Unix timestamp in milliseconds. Defaults to `Date.now()`. Must be within 30 days ago to 5 minutes in the future.}\n@returns(202) {ok: bool, queued: bool} # Event queued\n@errors {400: Validation error (missing fields, invalid event name, properties too large), 401: Invalid or missing token, 429: Rate limited}\n\n@endpoint POST /track/batch\n@desc Track multiple events\n@required {events: [map{token!: str, event!: str, properties: map, user_id: str, session_id: str, timestamp: num}] # Array of events (max 100 per batch)}\n@returns(202) {ok: bool, queued: bool, count: int} # Events queued\n@errors {400: Validation error (empty array, exceeds 100 events, invalid event), 401: Invalid or missing token, 429: Rate limited}\n\n@endgroup\n\n@group stats\n@endpoint GET /stats\n@desc Aggregated stats overview\n@required {project: str # Project name}\n@optional {since: str # Start date. Accepts ISO 8601 (`2025-01-01`) or shorthand (`7d`, `30d`). Defaults to 7 days ago., groupBy: str(hour/day/week/month)=day # Time series granularity}\n@returns(200) {project: str, period: map{from: str, to: str, groupBy: str}, totals: map{unique_users: int, total_events: int}, timeSeries: [map], events: [map], sessions: map{total_sessions: int, bounce_rate: num, avg_duration: int, pages_per_session: num, sessions_per_user: num}} # Stats overview\n@errors {400: Missing project parameter, 401: Missing or invalid API key}\n\n@endgroup\n\n@group events\n@endpoint GET /events\n@desc Raw event log\n@required {project: str # Project name}\n@optional {event: str # Filter by event name, session_id: str # Filter by session ID, since: str # Start date. Accepts ISO 8601 (`2025-01-01`) or shorthand (`7d`, `30d`). Defaults to 7 days ago., limit: int=100 # Max results to return (1-1000, default 100)}\n@returns(200) {project: str, events: [map]} # Event list\n@errors {401: Missing or invalid API key}\n\n@endgroup\n\n@group query\n@endpoint POST /query\n@desc Flexible analytics query\n@required {project: str # Project name}\n@optional {metrics: [str]=event_count # Metrics to compute, group_by: [str]= # Fields to group results by, filters: [map{field: str, op: str, value: any}], date_from: str # Start date (ISO 8601 or `Nd` shorthand). Defaults to 7 days ago., date_to: str # End date (ISO 8601). Defaults to today., order_by: str(event_count/unique_users/date/event) # Field to sort by, order: str(asc/desc)=desc, limit: int=100}\n@returns(200) {project: str, period: map{from: str, to: str}, metrics: [str], group_by: [str], rows: [map], count: int} # Query results\n@errors {400: Invalid query (bad metric, group_by, filter, or missing project), 401: Missing or invalid API key}\n@example_request {\"project\":\"my-site\",\"metrics\":[\"event_count\",\"unique_users\"],\"group_by\":[\"date\"],\"filters\":[{\"field\":\"event\",\"op\":\"eq\",\"value\":\"page_view\"}],\"date_from\":\"2025-01-01\"}\n\n@endgroup\n\n@group properties\n@endpoint GET /properties\n@desc Discover event names and property keys\n@required {project: str # Project name}\n@optional {since: str # Start date. Accepts ISO 8601 (`2025-01-01`) or shorthand (`7d`, `30d`). Defaults to 7 days ago.}\n@returns(200) {project: str, events: [map], property_keys: [str]} # Event names and property keys\n@errors {401: Missing or invalid API key}\n\n@endpoint GET /properties/received\n@desc Property keys by event name\n@required {project: str # Project name}\n@optional {since: str # Start date. Accepts ISO 8601 (`2025-01-01`) or shorthand (`7d`, `30d`). Defaults to 7 days ago., sample: int=5000 # Number of recent events to sample (100-10000, default 5000)}\n@returns(200) {project: str, sample_size: int, since: str, properties: [map]} # Property-to-event mapping\n@errors {401: Missing or invalid API key}\n\n@endgroup\n\n@group sessions\n@endpoint GET /sessions\n@desc List sessions\n@required {project: str # Project name}\n@optional {since: str # Start date. Accepts ISO 8601 (`2025-01-01`) or shorthand (`7d`, `30d`). Defaults to 7 days ago., limit: int=100 # Max results to return (1-1000, default 100), user_id: str # Filter by user ID, is_bounce: int(0/1) # Filter by bounce status (0 or 1)}\n@returns(200) {project: str, sessions: [map]} # Session list\n@errors {401: Missing or invalid API key}\n\n@endgroup\n\n@group breakdown\n@endpoint GET /breakdown\n@desc Top property values\n@required {project: str # Project name, property: str # Property key to break down by (alphanumeric + underscores, max 128 chars). Use `country` for visitor geography.}\n@optional {event: str # Filter to a specific event name, since: str # Start date. Accepts ISO 8601 (`2025-01-01`) or shorthand (`7d`, `30d`). Defaults to 7 days ago., limit: int=20 # Max values to return (1-1000, default 20)}\n@returns(200) {project: str, property: str, event: str?, values: [map], total_events: int, total_with_property: int} # Property breakdown\n@errors {400: Missing property parameter or invalid property key, 401: Missing or invalid API key}\n\n@endgroup\n\n@group insights\n@endpoint GET /insights\n@desc Period-over-period comparison\n@required {project: str # Project name}\n@optional {period: str(1d/7d/14d/30d/90d)=7d # Comparison period}\n@returns(200) {project: str, current_period: map{from: str, to: str}, previous_period: map{from: str, to: str}, metrics: map{total_events: map{current: num, previous: num, change: num, change_pct: int?}, unique_users: map{current: num, previous: num, change: num, change_pct: int?}, total_sessions: map{current: num, previous: num, change: num, change_pct: int?}, bounce_rate: map{current: num, previous: num, change: num, change_pct: int?}, avg_duration: map{current: num, previous: num, change: num, change_pct: int?}}, trend: str} # Insights with trend\n@errors {400: Invalid period, 401: Missing or invalid API key}\n\n@endgroup\n\n@group pages\n@endpoint GET /pages\n@desc Entry/exit page stats\n@required {project: str # Project name}\n@optional {type: str(entry/exit/both)=entry # Page type to query, since: str # Start date. Accepts ISO 8601 (`2025-01-01`) or shorthand (`7d`, `30d`). Defaults to 7 days ago., limit: int=20 # Max pages to return (1-1000, default 20)}\n@returns(200) {project: str, entry_pages: [map], exit_pages: [map]} # Page stats\n@errors {400: Invalid page type, 401: Missing or invalid API key}\n\n@endgroup\n\n@group sessions\n@endpoint GET /sessions/distribution\n@desc Session duration histogram\n@required {project: str # Project name}\n@optional {since: str # Start date. Accepts ISO 8601 (`2025-01-01`) or shorthand (`7d`, `30d`). Defaults to 7 days ago.}\n@returns(200) {project: str, distribution: [map], median_bucket: str?, engaged_pct: num} # Session duration distribution\n@errors {401: Missing or invalid API key}\n\n@endgroup\n\n@group heatmap\n@endpoint GET /heatmap\n@desc Day-of-week x hour traffic grid\n@required {project: str # Project name}\n@optional {since: str # Start date. Accepts ISO 8601 (`2025-01-01`) or shorthand (`7d`, `30d`). Defaults to 7 days ago.}\n@returns(200) {project: str, heatmap: [map], peak: map?, busiest_day: str?, busiest_hour: int?} # Heatmap grid\n@errors {401: Missing or invalid API key}\n\n@endgroup\n\n@group funnel\n@endpoint POST /funnel\n@desc Funnel analysis\n@required {project: str # Project name, steps: [map{event!: str, filters: [map]}] # Funnel steps (2-8). Each step has an event name and optional property filters.}\n@optional {conversion_window_hours: num=168 # Max hours from step 1 entry to final step (1-8760, default 168 = 7 days), since: str=30d # Lookback period (ISO date or shorthand like '30d'). Default: 30d, count_by: str(user_id/session_id)=user_id # Count by unique users or sessions, breakdown: str # Optional property key to segment funnel by (e.g. 'variant', 'country'). Extracted from step 1 events only., breakdown_limit: num=10 # Max breakdown groups, ordered by step 1 users descending (1-50, default 10)}\n@returns(200) {steps: [map], overall_conversion_rate: num, breakdowns: [map]} # Funnel analysis results\n@errors {400: Validation error (invalid steps, filters, window, or count_by), 401: Missing or invalid API key, 404: Project not found}\n@example_request {\"project\":\"my-site\",\"steps\":[{\"event\":\"page_view\"},{\"event\":\"signup\"},{\"event\":\"purchase\"}]}\n\n@endgroup\n\n@group retention\n@endpoint GET /retention\n@desc Cohort retention analysis\n@required {project: str # Project name}\n@optional {period: str(day/week/month)=week # Cohort grouping period, cohorts: int=8 # Number of cohort periods (max: day=30, week=12, month=12), event: str # First-seen event filter (e.g. `signup`). Switches to event-based retention., returning_event: str # What counts as \"returned\" (defaults to same as `event`), since: str # Start date. Accepts ISO 8601 (`2025-01-01`) or shorthand (`7d`, `30d`). Defaults to 7 days ago.}\n@returns(200) {period: str, cohorts: [map], average_rates: [num], users_analyzed: int} # Cohort retention data\n@errors {400: Invalid period or cohorts value, 401: Missing or invalid API key, 404: Project not found}\n\n@endgroup\n\n@group stream\n@endpoint GET /stream\n@desc Live event stream (SSE)\n@optional {project: str # Project name. Defaults to first project., events: str # Comma-separated event name filter. Omit for all events., filter: str # Property filter as `key:value` pairs separated by `;`. Multiple filters use AND logic.}\n@returns(200) SSE event stream\n@errors {401: Missing or invalid API key, 404: Project not found, 429: Too many concurrent streams (max 10 per account)}\n\n@endgroup\n\n@group live\n@endpoint GET /live\n@desc Live snapshot (real-time)\n@optional {project: str # Project name. Defaults to first project., window: int=60 # Time window in seconds (10-300, default 60)}\n@returns(200) {project: str, window_seconds: int, timestamp: num, active_visitors: int, active_sessions: int, events_per_minute: int, top_pages: [map], top_events: [map], recent_events: [map]} # Live snapshot\n@errors {401: Missing or invalid API key, 404: Project not found}\n\n@endgroup\n\n@group projects\n@endpoint GET /projects\n@desc List all projects\n@returns(200) {projects: [map], has_api_key: bool, project_limit: int, tier: str} # Project list\n@errors {401: Missing or invalid API key}\n\n@endpoint POST /projects\n@desc Create a new project\n@required {name: str # Project name (alphanumeric, hyphens, underscores, dots; max 64 chars)}\n@optional {allowed_origins: str=* # Allowed origins for CORS. Use `*` for any origin.}\n@returns(200) {id: str, name: str, project_token: str, existing: bool} # Project already exists (returned existing project)\n@returns(201) {id: str, name: str, project_token: str, allowed_origins: str, snippet: str, api_example: str} # Project created\n@errors {400: Missing name or invalid project name, 401: Missing or invalid API key, 403: Project limit reached for your tier, 409: Duplicate origin}\n\n@endpoint GET /projects/{id}\n@desc Get project details\n@required {id: str}\n@returns(200) {id: str, name: str, project_token: str, allowed_origins: str, usage_today: map} # Project details\n@errors {401: Missing or invalid API key, 403: Not your project, 404: Project not found}\n\n@endpoint PATCH /projects/{id}\n@desc Update a project\n@required {id: str}\n@optional {name: str # New project name, allowed_origins: str # New allowed origins}\n@returns(200) {id: str, name: str, project_token: str, allowed_origins: str} # Updated project\n@errors {400: Invalid name or no fields to update, 401: Missing or invalid API key, 409: Name locked (events recorded) or duplicate name/origin}\n\n@endpoint DELETE /projects/{id}\n@desc Delete a project\n@required {id: str}\n@returns(200) {ok: bool, deleted: str} # Project deleted\n@errors {401: Missing or invalid API key, 403: Not your project, 404: Project not found}\n\n@endgroup\n\n@group account\n@endpoint GET /account\n@desc Get account info\n@returns(200) {id: str, email: str, github_login: str?, tier: str, created_at: str, projects_count: int, projects_limit: int, tier_limits: map{max_projects: int, max_events_lifetime: int, retention_days: int, rate_limit_rpm: int}, monthly_spend_cap_dollars: num?} # Account info\n@errors {401: Missing or invalid API key}\n\n@endpoint POST /account/revoke-key\n@desc Revoke and regenerate API key\n@returns(200) {ok: bool, api_key: str} # New API key\n@errors {401: Missing or invalid API key}\n\n@endgroup\n\n@group experiments\n@endpoint GET /experiments/config\n@desc Get experiment config for tracker.js\n@required {token: str # Project token (`aat_*`)}\n@returns(200) {experiments: [map]} # Active experiments for this project\n@errors {400: Missing token}\n\n@endpoint POST /experiments\n@desc Create an A/B experiment\n@required {project: str # Project name, name: str # Experiment name (alphanumeric, hyphens, underscores; max 64 chars), variants: [str] # 2-4 variant keys, goal_event: str # Event name to measure conversion (max 256 chars)}\n@optional {weights: [int] # Optional traffic weights per variant (must sum to 100). Defaults to equal split.}\n@returns(201) {id: str, project_id: str, account_id: str, name: str, variants: [map], goal_event: str, status: str, winner: str?, created_at: str, updated_at: str, completed_at: str?} # Experiment created\n@errors {400: Validation error (missing fields, invalid variants, duplicate name), 401: Missing or invalid API key, 403: Pro tier required, 404: Project not found, 409: Experiment name already exists in this project}\n\n@endpoint GET /experiments\n@desc List experiments\n@required {project: str # Project name}\n@returns(200) {experiments: [map]} # Experiment list\n@errors {400: Missing project parameter, 401: Missing or invalid API key, 404: Project not found}\n\n@endpoint GET /experiments/{id}\n@desc Get experiment with live results\n@required {id: str # Experiment ID (`exp_*`)}\n@returns(200) Experiment with results\n@errors {401: Missing or invalid API key, 403: Not your experiment, 404: Experiment not found}\n\n@endpoint PATCH /experiments/{id}\n@desc Update experiment status\n@required {id: str # Experiment ID (`exp_*`), status: str(active/paused/completed) # New status}\n@optional {winner: str # Variant key to declare as winner (only when completing)}\n@returns(200) {id: str, project_id: str, account_id: str, name: str, variants: [map], goal_event: str, status: str, winner: str?, created_at: str, updated_at: str, completed_at: str?} # Updated experiment\n@errors {400: Invalid status transition or missing status, 401: Missing or invalid API key, 403: Not your experiment, 404: Experiment not found}\n\n@endpoint DELETE /experiments/{id}\n@desc Delete an experiment\n@required {id: str # Experiment ID (`exp_*`)}\n@returns(200) {ok: bool, deleted: str} # Experiment deleted\n@errors {401: Missing or invalid API key, 403: Not your experiment, 404: Experiment not found}\n\n@endgroup\n\n@group health\n@endpoint GET /health\n@desc Health check\n@returns(200) {status: str, service: str} # Healthy\n@errors {404: Not found}\n\n@endgroup\n\n@group tracker.js\n@endpoint GET /tracker.js\n@desc JavaScript tracker script\n@returns(200) JavaScript file\n@errors {404: Not found}\n\n@endgroup\n\n@end\n"}}