{"note":"OpenAPI conversion -- returning structured metadata","name":"agent-analytics","description":"Agent Analytics API","version":"1.0.0","base_url":"https://api.agentanalytics.sh","endpoints":32,"raw":"@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"}