API·Docs

The v1 API.

Drive simulations and read reports programmatically. Available on Pro and Enterprise. Battle-mode endpoints require Pro+.

01Create a key

Generate a key in Settings → API keys. Copy it once.

02Pass as Bearer

Send Authorization: Bearer agl_live_… on every request.

03Hit /api/v1/*

Curl examples for every endpoint below. JSON in, JSON out.

01·Authentication

Every request to /api/v1/* must include an Authorization header. Keys start with agl_live_ followed by 24 random URL-safe characters. Revoking a key in Settings takes effect immediately — the next request returns 401.

GET/api/v1/whoami
Sanity-check the key. Returns the owning account and the plan it's gated to. Useful as a connection test before running anything destructive.
curl
curl https://api.agentlens.example/api/v1/whoami \
  -H "Authorization: Bearer agl_live_xxxxxxxxxxxxxxxxxxxxxxxx"
response
{
  "account_id": "3c35c1ba-0e7f-4c63-9e83-acbb…",
  "account_name": "ACME UX team",
  "plan": "pro",
  "credits_remaining": 84532
}
02·Simulations — lifecycle

Launch runs, list/inspect them, cancel mid-flight, edit tags, poll progress.

POST/api/v1/simulations
Queue a new simulation. The job lands on your account's queue (priority queue if you're on Pro+). Returns the new simulation id and the estimated max credits — the actual spend is capped by credit_budget.
curl
curl https://api.agentlens.example/api/v1/simulations \
  -H "Authorization: Bearer agl_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "website_url": "https://acme.example.com",
    "name": "checkout flow — pricing change",
    "mode": "task",
    "objective": "Find the pricing page and complete checkout",
    "agent_count": 20,
    "max_steps_per_agent": 12,
    "max_pages_per_agent": 10,
    "tags": ["pricing-v2", "Q2"]
  }'
response
{
  "simulation_id": "1f3a-…",
  "status": "queued",
  "estimated_max_credits": 200
}
GET/api/v1/simulations
List simulations for the account, newest first. Filter by status and tag. Respects the plan's run-history retention window — older runs return 410 individually but are silently omitted from the list.
curl
curl "https://api.agentlens.example/api/v1/simulations?limit=50&status=completed&tag=pricing-v2" \
  -H "Authorization: Bearer agl_live_xxxxxxxxxxxxxxxxxxxxxxxx"
response
[
  {
    "id": "1f3a-…",
    "name": "checkout flow — pricing change",
    "status": "completed",
    "agent_count": 20,
    "credits_used": 184,
    "credit_budget": 200,
    "tags": ["pricing-v2", "Q2"],
    "started_at": "2026-05-19T14:02:11",
    "completed_at": "2026-05-19T14:21:48",
    "...": "…"
  }
]
GET/api/v1/simulations/{simulation_id}
Fetch a single simulation. Returns 410 if the run is outside your plan's retention window — upgrade to read it again.
curl
curl https://api.agentlens.example/api/v1/simulations/1f3a-… \
  -H "Authorization: Bearer agl_live_xxxxxxxxxxxxxxxxxxxxxxxx"
POST/api/v1/simulations/{simulation_id}/cancel
Request cancellation. The status transitions to 'canceling' immediately; workers tear down on the next checkpoint. Already-terminal runs return a noop.
curl
curl -X POST https://api.agentlens.example/api/v1/simulations/1f3a-…/cancel \
  -H "Authorization: Bearer agl_live_xxxxxxxxxxxxxxxxxxxxxxxx"
response
{ "status": "canceling" }
PATCH/api/v1/simulations/{simulation_id}/tags
Replace the tag set. Whitespace is stripped and duplicates removed server-side — send the full desired set on every call.
curl
curl -X PATCH https://api.agentlens.example/api/v1/simulations/1f3a-…/tags \
  -H "Authorization: Bearer agl_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{ "tags": ["pricing-v2", "Q2", "regression"] }'
GET/api/v1/simulations/{simulation_id}/progress
Poll-style status snapshot. Cheaper than the SSE stream — call this on a 2-5s loop while a run is active. agents_completed counts every terminal status (success, stuck, abandoned, max-steps, failed, canceled).
curl
curl https://api.agentlens.example/api/v1/simulations/1f3a-…/progress \
  -H "Authorization: Bearer agl_live_xxxxxxxxxxxxxxxxxxxxxxxx"
response
{
  "simulation_id": "1f3a-…",
  "status": "running",
  "agent_count": 20,
  "agents_completed": 14,
  "agents_by_status": {
    "running": 6,
    "goal_reached": 9,
    "stuck": 3,
    "max_steps_reached": 2
  },
  "credits_used": 132,
  "credit_budget": 200,
  "started_at": "2026-05-19T14:02:11",
  "completed_at": null
}
03·Results — reports, pages, agents

Once a run completes, pull the analysis. Reports come as either structured JSON or rendered Markdown.

GET/api/v1/simulations/{simulation_id}/report
The full structured report — executive summary, headline metrics, funnel, page-level insights, persona insights, recommendations, success/failure paths. Returns 404 until the report-generation job has finished.
curl
curl https://api.agentlens.example/api/v1/simulations/1f3a-…/report \
  -H "Authorization: Bearer agl_live_xxxxxxxxxxxxxxxxxxxxxxxx"
response
{
  "id": "report-…",
  "simulation_id": "1f3a-…",
  "status": "ready",
  "executive_summary": "62% of agents completed checkout…",
  "metrics": {
    "completion_rate": 0.62,
    "average_confusion": 0.31,
    "total_agents": 20
  },
  "funnel": [ { "url": "…", "agents_reached": 20 }, … ],
  "page_insights": [ … ],
  "persona_insights": [ … ],
  "recommendations": [ … ]
}
GET/api/v1/simulations/{simulation_id}/report/markdown
The same report rendered as Markdown (text/markdown content-type). Convenient for piping into a static-site generator or wiki page.
curl
curl https://api.agentlens.example/api/v1/simulations/1f3a-…/report/markdown \
  -H "Authorization: Bearer agl_live_xxxxxxxxxxxxxxxxxxxxxxxx"
GET/api/v1/simulations/{simulation_id}/pages
Per-URL aggregates: visit count, unique agent count, average confusion/attraction/trust, dropoff and goal-success counts, plus a representative screenshot key (use the /files endpoint to fetch the bytes).
curl
curl https://api.agentlens.example/api/v1/simulations/1f3a-…/pages \
  -H "Authorization: Bearer agl_live_xxxxxxxxxxxxxxxxxxxxxxxx"
GET/api/v1/simulations/{simulation_id}/agents
List agents for a simulation. Supports filtering by status and any persona dimension (confidence, technical_ability, background, motivation, accessibility, device, geography, purchase_behavior). Paginate with limit + offset.
curl
curl "https://api.agentlens.example/api/v1/simulations/1f3a-…/agents?status=goal_reached&persona_dimension=device&persona_value=mobile&limit=50" \
  -H "Authorization: Bearer agl_live_xxxxxxxxxxxxxxxxxxxxxxxx"
GET/api/v1/agents/{agent_id}
Single agent with the full ordered step list. Each step carries observation, thought summary, action, result, emotional state, and goal assessment — everything you need to reconstruct the run.
curl
curl https://api.agentlens.example/api/v1/agents/9ab2-… \
  -H "Authorization: Bearer agl_live_xxxxxxxxxxxxxxxxxxxxxxxx"
GET/api/v1/agents/{agent_id}/trajectory
A rendered Markdown trajectory for the agent (text/markdown). Returns 404 if the trajectory file hasn't been generated yet.
curl
curl https://api.agentlens.example/api/v1/agents/9ab2-…/trajectory \
  -H "Authorization: Bearer agl_live_xxxxxxxxxxxxxxxxxxxxxxxx"
04·Heatmaps

Per-page click / attention / confusion / attraction / repulsion / hesitation overlays.

GET/api/v1/simulations/{simulation_id}/heatmaps
List every page that has heatmap coverage, ordered by visit count. Returns the page id you need for the detail call, plus the representative screenshot key.
curl
curl https://api.agentlens.example/api/v1/simulations/1f3a-…/heatmaps \
  -H "Authorization: Bearer agl_live_xxxxxxxxxxxxxxxxxxxxxxxx"
GET/api/v1/simulations/{simulation_id}/heatmaps/{page_id}
The actual heatmap points for a page. Filter by type (click | attention | confusion | attraction | repulsion | hesitation), outcome (success | failure), and any persona dimension. Hard-capped at 5 000 points per response.
curl
curl "https://api.agentlens.example/api/v1/simulations/1f3a-…/heatmaps/page-…?type=confusion&outcome=failure&limit=500" \
  -H "Authorization: Bearer agl_live_xxxxxxxxxxxxxxxxxxxxxxxx"
05·Files

Screenshots, trajectory Markdown, report JSON/Markdown — anything referenced by an object_key on the rows above.

GET/api/v1/files/{key}
Stream a stored object. The key is the path you see on rows (e.g. screenshot_object_key, trajectory_object_key, representative_screenshot_key). Keys that no row in your account references will 404 — even if the file physically exists — so cross-tenant access by guessing UUIDs is impossible.
curl
curl https://api.agentlens.example/api/v1/files/screenshots/1f3a-…/step-007.png \
  -H "Authorization: Bearer agl_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
  --output step-007.png
06·Battles — A/B comparison

Group N simulations into a head-to-head and compare. Pro and Enterprise only.

POST/api/v1/battles
Create a battle group. Pick a primary_metric — completion_rate (default), average_confusion, total_agents, average_attraction, etc. — that's the metric the verdict line will summarize.
curl
curl https://api.agentlens.example/api/v1/battles \
  -H "Authorization: Bearer agl_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "/checkout — v1 vs v2",
    "hypothesis": "Sticky CTA improves completion by ≥5pp",
    "primary_metric": "completion_rate"
  }'
GET/api/v1/battles
List every battle on this account, newest first, each with its current entries.
curl
curl https://api.agentlens.example/api/v1/battles \
  -H "Authorization: Bearer agl_live_xxxxxxxxxxxxxxxxxxxxxxxx"
GET/api/v1/battles/{battle_id}
Fetch a single battle + its entries (no comparison math).
curl
curl https://api.agentlens.example/api/v1/battles/b-… \
  -H "Authorization: Bearer agl_live_xxxxxxxxxxxxxxxxxxxxxxxx"
DELETE/api/v1/battles/{battle_id}
Permanently remove the battle and all its entries. The underlying simulations are not deleted.
curl
curl -X DELETE https://api.agentlens.example/api/v1/battles/b-… \
  -H "Authorization: Bearer agl_live_xxxxxxxxxxxxxxxxxxxxxxxx"
POST/api/v1/battles/{battle_id}/entries
Add a simulation to a battle. Mark one entry as is_baseline — comparisons compute deltas against that one. Adding a second baseline silently demotes the first; adding the same sim twice returns 409.
curl
curl https://api.agentlens.example/api/v1/battles/b-…/entries \
  -H "Authorization: Bearer agl_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "simulation_id": "1f3a-…",
    "label": "v1 (control)",
    "is_baseline": true,
    "change_summary": "Original pricing page"
  }'
PATCH/api/v1/battles/{battle_id}/entries/{entry_id}
Update an entry's label, change summary, ordinal, or baseline flag.
curl
curl -X PATCH https://api.agentlens.example/api/v1/battles/b-…/entries/e-… \
  -H "Authorization: Bearer agl_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{ "label": "v2 — sticky CTA", "change_summary": "Sticky CTA + lighter headline" }'
DELETE/api/v1/battles/{battle_id}/entries/{entry_id}
Remove an entry from a battle. The simulation itself stays.
curl
curl -X DELETE https://api.agentlens.example/api/v1/battles/b-…/entries/e-… \
  -H "Authorization: Bearer agl_live_xxxxxxxxxxxxxxxxxxxxxxxx"
GET/api/v1/battles/{battle_id}/compare
The big one. Returns side-by-side KPIs for every entry (with deltas vs. the baseline), the top 6 persona buckets where the variant won, the top 6 where it lost, per-URL drop-off and confusion deltas, and a one-line verdict.
curl
curl https://api.agentlens.example/api/v1/battles/b-…/compare \
  -H "Authorization: Bearer agl_live_xxxxxxxxxxxxxxxxxxxxxxxx"
response
{
  "battle": { "id": "b-…", "name": "/checkout — v1 vs v2", … },
  "entries": [
    {
      "label": "v1 (control)",
      "is_baseline": true,
      "metrics": { "completion_rate": 0.58, "average_confusion": 0.34 },
      "deltas":  { "completion_rate": 0.0,  "average_confusion": 0.0 }
    },
    {
      "label": "v2 — sticky CTA",
      "is_baseline": false,
      "metrics": { "completion_rate": 0.71, "average_confusion": 0.28 },
      "deltas":  { "completion_rate": 0.13, "average_confusion": -0.06 }
    }
  ],
  "persona_winners": [ { "dimension": "device", "value": "mobile", "delta": 18.4, … } ],
  "persona_losers":  [ { "dimension": "confidence", "value": "low", "delta": -4.1, … } ],
  "page_deltas":     [ { "normalized_url": "/checkout", "delta_confusion": -0.12, … } ],
  "verdict": "v2 — sticky CTA beats v1 (control) by +13.0pp on completion rate."
}
GET/api/v1/battles/{battle_id}/snapshots?normalized_url=…
Raw HTML snapshots of the same URL across every entry — feed these into your own diff tool. Entries that didn't capture this URL come back with html: null instead of an error.
curl
curl "https://api.agentlens.example/api/v1/battles/b-…/snapshots?normalized_url=acme.example.com/checkout" \
  -H "Authorization: Bearer agl_live_xxxxxxxxxxxxxxxxxxxxxxxx"
07·Errors
400The request body / query is invalid. The detail field tells you which field is wrong.
401Missing or malformed Authorization header, or the key was revoked.
402Not enough credits to cover the requested simulation budget. Buy a pack or wait for the next period reset.
403The key is valid, but the account's plan doesn't include this feature (API access — Hobby/Plus; or battle mode — Hobby/Plus).
404The resource doesn't exist or isn't owned by this account. We don't distinguish — that would leak existence across tenants.
409Add-entry conflict: this simulation is already in the battle.
410Simulation falls outside this plan's run-history retention window. The row still exists — upgrade to read it again.
422Custom personas failed validation. The detail.report field has per-file errors.
08·Rate limits & quotas

What you'll actually hit before anything else.

We don't enforce request-rate limits in MVP. The hard cap is credit consumption — the API draws from the same pool as the dashboard, so a runaway script with 8000 credits/month on Pro can burn through your quota in a single afternoon. Pro+ accounts route onto a dedicated arq:priority queue, so an API-launched run skips ahead of Plus traffic on the shared workers.

Need an endpoint that isn't listed? Tell us what you'd build with it. Enterprise customers get priority on new endpoints.