# Ginkgo Playtest Analytics API

This site has a read-only JSON API for agents and a shared refresh command. Use the API instead of scraping the dashboard.

## Discovery

- OpenAPI 3.1 contract: [https://ginkgo.maxceem.bid/openapi.json](https://ginkgo.maxceem.bid/openapi.json)
- Compact index: [https://ginkgo.maxceem.bid/llms.txt](https://ginkgo.maxceem.bid/llms.txt)
- API base: `https://ginkgo.maxceem.bid/api/v1`
- Authentication: none
- Read limits: none
- Response language: field names are English; explanatory text can be Russian

## Recommended workflow

1. `GET /api/v1/builds` and choose a published build.
2. `GET /api/v1/builds/{build}/levels` to discover exact level names and immutable layout identifiers.
3. `GET /api/v1/builds/{build}/levels/{level}/report` for decision-ready metrics. Add `?session={run_id}` for one run.
4. Request `/events` only when the aggregate report is insufficient. Follow `page.nextCursor` until it is `null`.
5. Use `GET /api/v1/compare?from={build}&to={build}&level={level}` for a like-for-like build comparison.

## Interpretation rules

- Treat `level.layoutGuid`, `level.mapAssetId`, `level.analyticsCompatibilityId`, and `snapshot.id` as provenance. Do not merge spatial data from incompatible layouts.
- `movementProfile` is calculated at build time from the real character configuration. It describes mechanical capability, not observed player behavior.
- `dangerousAreas` are server-calculated connected components. Two death points are linked at a maximum distance of 4.5 world units; the method is recorded in `methodology`.
- Counts can be weighted by `event_count`; do not assume one JSON object always equals one occurrence.
- A null metric means the denominator or source data is unavailable. It does not mean zero.
- Map images are for visual context. Prefer metadata and report coordinates for analysis.

## Event pagination and filters

`GET /api/v1/builds/{build}/events` and the level-specific events endpoint accept:

- `limit`: 1–1000, default 250
- `cursor`: opaque value returned as `page.nextCursor`
- `level`, `session`, `event`, `tester`: exact-match filters

## Refresh

`POST /api/v1/refresh` starts the same Amplitude import used by the dashboard. `POST /api/refresh` is an equivalent stable compatibility path for existing clients. Both paths use the same global job and are limited to one new manual start every 300 seconds. A concurrent request joins the running job. During cooldown the server returns `429 Too Many Requests`, a `Retry-After` header, and `rateLimit.retryAfterSeconds`. Poll `GET /api/v1/refresh/status` while `running` is true.

Do not loop on refresh. Reading reports and events is not rate limited.

## Level tasks

Designers mark up levels on the site as tasks (правки), grouped into batches (наборы правок). Each batch is published as a brief for an agent at `https://ginkgo.maxceem.bid/batches/{id}.md`: the scene to change, every task in words with Unity world coordinates, object hierarchy paths and `GlobalObjectId`s, and the full data as JSON. A single task of a batch is published the same way at `https://ginkgo.maxceem.bid/batches/{id}/tasks/{taskId}.md`: do that task only and leave the batch's other tasks alone. A person hands you that link; it needs no key or sign-in.

Everything is worked out in advance, so the brief says exactly what to change and where everything is. It does not say how: how to make, check and hand back the change is your own process. Each object comes with its hierarchy path, its prefab and its block in the scene file: scenes are YAML, and `GameObject &N` is the block `--- !u!1 &N` while `PrefabInstance &N` is `--- !u!1001 &N`, changed through its `m_Modifications` (the numbers come from the object's `GlobalObjectId`). A comment or an addition lists what lies under its point; a cut or an insertion lists the objects inside the span and crossing it and how many shift; a measurement says by how much a distance must change. Task types are `comment`, `move`, `removal`, `addition`, `cut`, `insertion` and `measurement`. The brief anchors the version the tasks were drawn on in git (the build's `build/{n}` tag and commit, or the export's commit), since the scene may have changed after it, and links that version's level data (`/api/layouts/.../{level}.design.json`, the export the site's map is drawn from). Only an editor signed in with Google can change a batch's or a task's status on the site.

An editor can also connect you to the MCP server at `https://ginkgo.maxceem.bid/mcp` (OAuth: the editor signs in and allows you once in the browser). Its tools act for that editor: `list_batches`, `get_brief` (the same Markdown briefs), `set_task_status` and `set_batch_status`.

`GET /api/v1/batches?level={level}` (optionally `layout`, `status`) and `GET /api/v1/batches/{id}` return the same batches as JSON without sign-in. Creating and changing batches needs a signed-in editor.
