Session JSON Schema
The submitted session’s JSON document is what a plugin (and any downstream consumer) sees. This page documents the shape as the backend writes it today.
This is not a stable, versioned schema. Fields can be added in any release; downstream consumers should ignore unknown keys.
Top-Level Shape
{
"id": "session-2026-05-15-18-30-00.123",
"created_at": "2026-05-15T18:30:00.123Z",
"screenshot": "screenshot.png",
"comments": [... ],
"bubbles": [... ],
"texts": [... ],
"canvas_objects": [... ]
}
| Field | Type | Description |
|---|---|---|
id | string | Generated as chrono::Utc::now.format("session-%Y-%m-%d-%H-%M-%S%.3f"). Lexicographically sortable by creation time. |
created_at | string | RFC 3339 / ISO 8601 UTC timestamp. |
screenshot | string | Always "screenshot.png". The primary screenshot image is at /sessions/{id}/screenshot.png. |
comments | array | Notes (rectangular focus + side + description + crop image). |
bubbles | array | Speech-bubble-style anchors (text targeted at a point). |
texts | array | Free-floating text objects placed on the canvas. |
canvas_objects | array | Verbatim canvas object array, used to reconstruct the scene for edit mode. Opaque to most consumers. |
A Comment Entry
Each entry of comments:
{
"index": 0,
"text": "the dropdown is cut off on narrow viewports",
"side": "top", // top | bottom | left | right
"focus_x": 240,
"focus_y": 180,
"focus_width": 320,
"focus_height": 180,
"focus_image": "focus-0.png"
}
focus_image is a sibling-relative path; the file is at /sessions/{id}/focus-{index}.png inside the AeorDB store.
A Bubble Entry
Each entry of bubbles:
{
"text": "this scrolls weirdly",
"target_x": 540,
"target_y": 220
}
A bubble is anchored to a point on the screenshot rather than to a rectangle.
A Text Entry
Each entry of texts:
{
"text": "see ticket #4123",
"x": 400,
"y": 100
}
A free-floating text annotation placed on the canvas.
Attachments
A session’s image attachments live alongside session.json inside the AeorDB store:
/sessions/{id}/
session.json
screenshot.png # the submitted screenshot
screenshot-clean.png # optional — background only, no markup
focus-0.png # one per comment
focus-1.png
...
Plugins reach these through HTTP:
GET /api/v1/sessions/{id}/files/{path}
For example, GET /api/v1/sessions/{id}/files/screenshot.png or GET /api/v1/sessions/{id}/files/focus-0.png.
Forward Compatibility
Don’t assume:
- That this shape is stable. There is no version gate; fields may be added or renamed in any release.
- That
commentsis ordered by anything other than insertion order during the session. - That the
idparses as anything other than a string (it’ssession--prefixed and includes literal hyphens — don’t try to parse it as a single timestamp without the prefix).
Do:
- Ignore unknown keys.
- Treat
focus_imageas a path you fetch from/api/v1/sessions/{id}/files/{...}, not as inline base64. - Use the
idas an opaque identifier.