Parent
Child of #498 (Export & share).
Goal
Ship a stable, developer/AI-friendly export contract for a single error issue — not a database dump.
Primary loop we want to unlock:
Copy JSON → paste into Cursor / ChatGPT / GitHub / Slack
→ explain this error
→ what changed between releases?
→ generate a regression test
→ suggest a possible root cause
Recommendation
v1 — JSON via API (required)
Prefer GET /api/errors/:id/export as the MVP source of truth (not a purely client-side build).
| Consumer |
Uses |
| Dashboard |
Copy JSON, Download JSON, Copy as Markdown |
| curl / CLI / CI |
Same document |
| Future SDK / Actions / webhooks / AI tooling |
Same contract |
| Action |
Why |
| Copy JSON |
Paste into tickets, Slack, AI tools |
Download .json |
Attachments / archives |
| Copy as Markdown |
Better paste into GitHub issues/PRs (view over the same JSON) |
CSV / bulk list export, PDF, and share links stay in #498.
Design principles
- Versioned schema (
telemetry-tracker.issue.v1) — long-lived public contract
- Safe when data is incomplete (e.g. retention deleted occurrences)
- PII scrubbing matches project settings (same as dashboard view)
- Prefer developer usefulness over mirroring internal DB columns
Payload shape — telemetry-tracker.issue.v1
{
"schema": "telemetry-tracker.issue.v1",
"telemetry_tracker_version": "1.17.0",
"exported_at": "2026-07-19T12:00:00.000Z",
"project": {
"name": "production-api"
},
"issue": {
"id": "…",
"message": "…",
"fingerprint": "…",
"app": "web",
"environment": "production",
"platform": "javascript",
"release": "1.2.3",
"occurrences": 42,
"users_affected": 12,
"sessions_affected": 18,
"first_seen": "…",
"last_seen": "…",
"resolved_at": null,
"top_stack": "…",
"symbolicated_top_stack": "…",
"tags": {}
},
"latest_occurrence": {
"id": "…",
"created_at": "…",
"stack": "…",
"symbolicated_stack": "…",
"context": {},
"user_id": null,
"session_id": "…",
"release": "…",
"sdk_version": "…"
},
"dashboard_url": "https://…/dashboard/errors/…"
}
When no occurrence is available (retention, empty group, etc.):
{
"latest_occurrence": null
}
Export must not fail solely because an occurrence is missing.
Field notes
| Field |
Decision |
schema |
Required. Locked name for this document family. |
telemetry_tracker_version |
Product/app version that produced the export (support + AI context). |
project.name |
Human-readable only — omit internal project.id from the public contract. |
issue.id |
Keep — needed to find the issue again in TT. |
latest_occurrence |
Nullable. Prefer latest (or currently selected on detail). Renamed from ambiguous sample_occurrence. |
issue.tags |
Reserved object (may be {} today). Future keys e.g. browser, os, locale for AI/diagnosis. |
| Occurrence history |
Not in v1 — keep paste-friendly. Optional later: last N. |
Example Markdown (follow-on, derived from the same JSON)
## TypeError: Cannot read properties of undefined
- **Occurrences:** 42 · **Users:** 12 · **Sessions:** 18
- **App:** web · **Env:** production · **Release:** 1.2.3
- **First / last seen:** … / …
- **Telemetry Tracker:** 1.17.0
### Stack
\`\`\`
…
\`\`\`
[View in Telemetry Tracker](https://…/dashboard/errors/…)
If latest_occurrence is null, omit the stack section or note that no occurrence is available.
UX
On issue detail (/dashboard/errors/[id]):
- Copy JSON / Download JSON / Copy as Markdown
- All three call (or mirror)
GET /api/errors/:id/export
- Toast on copy success / failure
API
GET /api/errors/:id/export
- Auth / project scope same as existing error detail
- Honor current scope query params where relevant (app / env / platform / release / range), consistent with detail page
Content-Type: application/json
- Download filename suggestion:
issue-<id>.json (via Content-Disposition optional)
Markdown stays client-rendered from that JSON (no separate markdown endpoint required for v1).
Out of scope (this issue)
Acceptance
Contract
Surfaces
Parent
Child of #498 (Export & share).
Goal
Ship a stable, developer/AI-friendly export contract for a single error issue — not a database dump.
Primary loop we want to unlock:
Recommendation
v1 — JSON via API (required)
Prefer
GET /api/errors/:id/exportas the MVP source of truth (not a purely client-side build)..jsonCSV / bulk list export, PDF, and share links stay in #498.
Design principles
telemetry-tracker.issue.v1) — long-lived public contractPayload shape —
telemetry-tracker.issue.v1{ "schema": "telemetry-tracker.issue.v1", "telemetry_tracker_version": "1.17.0", "exported_at": "2026-07-19T12:00:00.000Z", "project": { "name": "production-api" }, "issue": { "id": "…", "message": "…", "fingerprint": "…", "app": "web", "environment": "production", "platform": "javascript", "release": "1.2.3", "occurrences": 42, "users_affected": 12, "sessions_affected": 18, "first_seen": "…", "last_seen": "…", "resolved_at": null, "top_stack": "…", "symbolicated_top_stack": "…", "tags": {} }, "latest_occurrence": { "id": "…", "created_at": "…", "stack": "…", "symbolicated_stack": "…", "context": {}, "user_id": null, "session_id": "…", "release": "…", "sdk_version": "…" }, "dashboard_url": "https://…/dashboard/errors/…" }When no occurrence is available (retention, empty group, etc.):
{ "latest_occurrence": null }Export must not fail solely because an occurrence is missing.
Field notes
schematelemetry_tracker_versionproject.nameproject.idfrom the public contract.issue.idlatest_occurrencesample_occurrence.issue.tags{}today). Future keys e.g.browser,os,localefor AI/diagnosis.Example Markdown (follow-on, derived from the same JSON)
If
latest_occurrenceis null, omit the stack section or note that no occurrence is available.UX
On issue detail (
/dashboard/errors/[id]):GET /api/errors/:id/exportAPI
Content-Type: application/jsonissue-<id>.json(viaContent-Dispositionoptional)Markdown stays client-rendered from that JSON (no separate markdown endpoint required for v1).
Out of scope (this issue)
Acceptance
Contract
telemetry-tracker.issue.v1)telemetry_tracker_version,schema, anddashboard_urllatest_occurrenceis nullable; missing occurrences do not prevent exporting an issueprojectexposesnameonly (noproject.idin the public contract)issue.tagsis present (may be empty{})Surfaces
GET /api/errors/:id/exportreturns the versioned documentlatest_occurrenceis present