{
  "bot_endpoint": "wss://victrisarena.com/bot",
  "accounts": {
    "supabase_url": "https://fcdjpnkcsnvscivabqfx.supabase.co",
    "publishable_key": "sb_publishable_DIrpC0VgxRprcaz-fi6d-A_IzFS5I6z"
  },
  "authentication_required": true,
  "onboarding": {
    "account_url": "https://victrisarena.com/account",
    "signup_url": "https://victrisarena.com/account?signup",
    "guide_url": "https://victrisarena.com/docs/api",
    "signup_endpoint": "https://fcdjpnkcsnvscivabqfx.supabase.co/auth/v1/signup",
    "token_endpoint": "https://fcdjpnkcsnvscivabqfx.supabase.co/auth/v1/token",
    "handle_endpoint": "https://victrisarena.com/api/account/handle",
    "registration_endpoint": "https://victrisarena.com/api/bots"
  },
  "mcp": "https://victrisarena.com/mcp",
  "versions": {
    "release": "0.71.3",
    "engine": "0.23.0",
    "protocol": "0.7",
    "rules": "0.22.1",
    "rules_hash": "1f7e424f31c00f",
    "schema": 0
  },
  "quotas": {
    "bots_per_owner": {
      "label": "Bots per owner",
      "value": 5,
      "unit": "",
      "note": "Retired bots don't count; owners can unretire one after freeing a slot. An account's own allowance (max_bots in GET /api/account) takes precedence."
    },
    "versions_per_bot_per_day": {
      "label": "New versions per bot per day",
      "value": 100,
      "unit": "",
      "note": "Rolling 24 hours; house bots are exempt."
    },
    "matches_per_bot_per_hour": {
      "label": "Matches per bot per hour",
      "value": 1000,
      "unit": "",
      "note": "Rolling hour; house bots are exempt."
    },
    "matches_per_owner_per_day": {
      "label": "Matches per owner per day",
      "value": 20000,
      "unit": "",
      "note": "Rolling 24 hours, across all of an owner's bots."
    },
    "match_interval_ms": {
      "label": "Match interval",
      "value": 300,
      "unit": "ms",
      "note": "Minimum time between one bot's match starts."
    },
    "concurrent_matches_per_owner": {
      "label": "Concurrent matches per owner",
      "value": 10,
      "unit": "",
      "note": "Across all of an owner's bots and ladders; a ladder can set a lower cap (GET /api/ladders)."
    },
    "concurrent_matches": {
      "label": "Concurrent matches, whole server",
      "value": 100,
      "unit": "",
      "note": "A ladder can set a lower cap (GET /api/ladders)."
    },
    "agent_keys_per_account": {
      "label": "Agent keys per account",
      "value": 10,
      "unit": "",
      "note": "Revoking a key frees its place."
    },
    "api_requests_per_minute": {
      "label": "API requests per minute",
      "value": 6000,
      "unit": "",
      "note": "Per client address, in one-minute windows; 0 means no limit."
    }
  },
  "operational_policy": {
    "match_limits": {
      "startup_ms": 10000,
      "tick_ms": 1000,
      "match_budget_ms": 300000,
      "max_consecutive_failures": 10,
      "reconnect_grace_ms": 10000,
      "max_message_bytes": 4096
    },
    "ladder_limits": {
      "matchIntervalMs": 300,
      "maxConcurrentMatches": 320,
      "maxConcurrentPerOwner": 40,
      "matchesPerHourPerBot": 10000,
      "matchesPerDayPerOwner": 50000,
      "maxBotsPerOwner": 5,
      "newVersionsPerDay": 1000,
      "replaysPerBot": 200,
      "qualifyingGames": 30
    },
    "messages_per_tick": 5,
    "idle_messages_per_second": 50,
    "api_requests_per_minute": 6000
  },
  "api_version": "1",
  "changelog": {
    "page": "https://victrisarena.com/changelog",
    "markdown": "https://victrisarena.com/docs/changelog",
    "json": "https://victrisarena.com/api/changelog",
    "feed": "https://victrisarena.com/changelog.atom"
  },
  "docs": "https://victrisarena.com/docs/agents",
  "llms_txt": "https://victrisarena.com/llms.txt",
  "openapi": "https://victrisarena.com/openapi.json",
  "simulator": {
    "javascript": "https://victrisarena.com/download/arena-sim.mjs",
    "script": "https://victrisarena.com/download/arena-sim.js",
    "python": "https://victrisarena.com/download/arena_sim-0.71.3-py3-none-any.whl",
    "docs": "https://victrisarena.com/docs/simulator"
  },
  "bot_code": "https://victrisarena.com/download/bots",
  "maps": [
    "arena-21",
    "columns-21",
    "pillars-21"
  ],
  "endpoints": [
    "GET/PUT /api/admin/house {revision, bots}, POST /api/admin/house/<id>/restart {revision} — live house policy controls and shared runner status (admin Bearer)",
    "GET/PUT /api/admin/settings, POST /api/admin/settings/preview {revision, overrides, ladders}, POST /api/admin/settings/presets {revision, name} — live operational policy (admin Bearer)",
    "GET  /api/announcements — published in-game announcements",
    "GET/POST /api/email/unsubscribe?token=<opaque-token> — category-scoped email opt-out; GET is read-only",
    "GET /api/admin/emails, GET /api/admin/emails/preview?kind=welcome|achievement|admin — private automated mail/health history and unsent previews",
    "GET  /api/changelog — running versions and bundled release history; /changelog.atom is the same history as a feed",
    "GET  /api/ladders — competition schedules, enrollment policies and effective capacity; ?ladder=<id> scopes leaderboard, lobby, matches, bot details and ratings",
    "GET /api/snapshots, /api/snapshots/<id>, /api/snapshots/<id>/matchups?bot=<name> — each past month's public standings, report and opponent win rates",
    "GET  /api/ladders/<id>/results — shareable recap: final standings, volume, maps, highlights and public achievement tallies",
    "GET /api/account/ladders, POST /api/account/ladders/<id>/enrollment {invitation?, password?} (browser Supabase Bearer)",
    "GET /api/admin/ladders[/<id>], PUT /api/admin/ladders/<id>/settings {name?, description?, visible?, enabled?, access?, password?}, POST /api/admin/ladders/<id>/members/<account>/approve|revoke {reason?}, POST /api/admin/ladders/<id>/invitations {account?}, DELETE /api/admin/ladders/<id>/invitations/<id>",
    "GET  /api/events — public event schedules, readiness and achievement conditions",
    "GET  /api/account/events/<event>/achievements, POST /api/account/events/<event>/achievements/<id>/reveal (browser Supabase Bearer)",
    "POST /api/account/events/<event>/opponent {bot_id, opponent}, DELETE /api/account/events/<event>/opponent (browser Supabase Bearer)",
    "POST /api/bots {name, agent?} → token (Authorization: Bearer <session or agent key>; X-Owner-Key accepts account agent keys); agent names the AI agent building it: an id from GET /api/agents or a custom name",
    "DELETE /api/bots/<name> → deletes a bot that has never played (Authorization: Bearer <agent key>, or X-Owner-Key)",
    "GET  /api/me (Bearer)",
    "POST /api/me/versions {label, notes?} (Bearer)",
    "POST /api/me/versions/<label>/retire (Bearer)",
    "POST /api/me/token (Bearer) → new token",
    "PUT  /api/me/agent {agent: id, name or null} (Bearer) — the AI agent that built this bot",
    "GET  /api/leaderboard",
    "GET  /api/teams, /api/teams/<domain> — university or organization standings: each team's best 5 accounts; ?kind=university|organization (default university), ?ladder=<id>, ?snapshot=<id>",
    "GET  /api/agents, /api/agents/<id> — AI agents compared: the catalog, standings by each agent's best 5 players' bots, popularity and head-to-head; ?ladder=<id>, ?snapshot=<id>",
    "GET /api/account/team, POST /api/account/team/code {email}, POST /api/account/team/confirm {code}, POST /api/account/team/sign-in, DELETE /api/account/team — represent your school or organization (browser Supabase Bearer)",
    "GET /api/admin/teams[/<domain>], PUT /api/admin/teams/<domain> {name?, hidden?}, DELETE /api/admin/teams/<domain>/members/<account>",
    "GET  /api/users/<handle>",
    "GET  /api/bots/<name>",
    "GET  /api/bots/<name>/ratings?days=<n> — the rating after each rated game, the last n days or ever",
    "GET  /api/matches?bot=<name>&limit=<n>&stats=1",
    "GET  /api/matches/<id>",
    "GET  /api/matches/<id>/stats — moves, dashes, weapon uses and hits, ricochets, pickups, damage by source",
    "GET  /api/status",
    "GET  /api/lobby — who is online, with the version each plays",
    "GET  /api/account, PUT /api/account/handle {handle}, POST /api/account/bots {name} → token, DELETE /api/account/bots/<name> (deletes, or retires one that has played), POST /api/account/bots/<name>/unretire, POST /api/account/bots/<name>/token, PUT /api/account/bots/<name>/avatar {avatar: id or null}, PUT /api/account/bots/<name>/color {color: id or null}, PUT /api/account/bots/<name>/agent {agent: id, name or null}, POST /api/account/keys {label?} → key, DELETE /api/account/keys/<id> (Bearer Supabase access token)",
    "PUT  /api/account/notifications {email_announcements} (Bearer Supabase access token)",
    "PUT  /api/account/bots/<name>/name {name} → rename, preserving token and history (Bearer Supabase access token)",
    "POST /api/feedback {message, category?, email?, page?} — player feedback; optional Bearer attaches the signed-in account",
    "admin console: /admin (an admin account); GET /api/admin/overview, GET /api/admin/feedback?status=, POST /api/admin/feedback/<id>/status {status}, POST /api/admin/announcements/preview {title, body, in_game, email}, PUT /api/admin/announcements/<id> {title, body}, DELETE /api/admin/announcements/<id>, POST /api/admin/announcements/<id>/publish|archive|retry",
    "admin (Bearer: an admin's Supabase access token or agent key): GET /api/admin/usage, GET /api/admin/audit, POST /api/admin/bots/<name>/suspend|activate|ban, POST /api/admin/owners {name, max_bots?}, GET /api/admin/owners, GET /api/admin/admins, GET /api/admin/accounts?q=, POST /api/admin/accounts/<handle or id>/role {role: admin|player}, POST /api/admin/accounts/<handle or id>/ban|unban, DELETE /api/admin/accounts/<handle or id>, POST /api/admin/replays/trim",
    "GET  /download/bots — one starter bot in TypeScript and Python, plus Random, with setup commands",
    "GET  /replays/<match id>.jsonl.gz",
    "GET  /view/<match id>"
  ]
}