App reports
App reports
Upload a full navigation-session diagnostics JSON from the Navvo mobile apps. The API stores the file without truncating entries or text, classifies API vs app issues, and exposes them in platform admin grouped by each file's endedAt.
The ingest route is not API-key scoped. It is locked by the shared secret in the key query parameter (JSON_FILE_REPORT_KEY on the server). Admin list/detail/download/prompt routes require an admin session.
Body size limit for ingest: 64 MB.
entries timeline of api / fix / warning / event), then POST it when the session ends. Use client-only status codes 8 (network) and 9 (timeout) when there is no HTTP response. Prefer multipart if the downloaded file must match the original bytes. Full field-by-field contract for app teams: ask Navvo for the App Reports — Mobile Upload Guide.POST /app-reports
Ingest one diagnostics JSON file.
Query
| Param | Required | Notes |
|---|---|---|
key | yes | Must match the server's report ingest secret. Wrong or missing key → 401. |
Body
Send the JSON as application/json, or as a multipart file field. Prefer multipart when you need the downloaded file to match the original bytes exactly; a JSON body is re-encoded when stored.
The payload is kept in full: every entry, warning, API call, and note is retained. Nothing is sampled away at ingest.
Response
{
"ok": true,
"created": true,
"id": "…",
"sha256": "…",
"endedAt": "2026-11-02T16:35:44.000Z",
"endedAtRaw": "2026-11-02T16:35:44Z",
"findingCount": 11,
"highestSeverity": "high",
"backendFindingCount": 4,
"frontendFindingCount": 9
}
Uploading the same bytes again returns the existing row with created: false (deduped by SHA-256).
Errors
| Status | When |
|---|---|
401 | Missing or wrong key |
400 | Empty body, invalid JSON, or root not an object |
413 | Body larger than 64 MB |
503 | Ingest secret not configured on the server |
curl -X POST "https://navvo.io/api/v1/app-reports?key=YOUR_SECRET" \
-H "Content-Type: application/json" \
--data-binary @nav_session.json
GET /admin/app-reports
List ingested reports (newest endedAt first). Admin or super-admin JWT required.
Query
| Param | Notes |
|---|---|
limit | Default 50, max 200 |
offset | Default 0 |
platform | ios · android · web · unknown |
severity | critical · high · medium · low · info |
triageStatus | new · in_progress · blocked · done · canceled · wont_fix |
Response
{
"items": [
{
"id": "…",
"reportKey": "nav_20261102_192604_4317",
"endedAt": "2026-11-02T16:35:44.000Z",
"endedAtRaw": "2026-11-02T16:35:44Z",
"platform": "ios",
"highestSeverity": "high",
"triageStatus": "new",
"notes": "",
"hasNotes": false,
"findingCount": 11,
"backendFindingCount": 4,
"frontendFindingCount": 9,
"failedApiCalls": 10,
"entryCount": 931,
"rawBytes": 3429104
}
],
"total": 1,
"limit": 50,
"offset": 0,
"triageCounts": {
"new": 1,
"in_progress": 0,
"blocked": 0,
"done": 0,
"canceled": 0,
"wont_fix": 0
}
}
Platform admin UI: /platform-admin/app-reports — groups rows by endedAt, with triage filters, notes, and delete.
GET /admin/app-reports/{id}
Full classified analysis (findings, endpoint stats, session meta). Does not inline every raw timeline entry; use the raw download or the entries endpoint for those.
Each item also carries ops fields (independent of the session status inside the JSON):
| Field | Meaning |
|---|---|
triageStatus | new · in_progress · blocked · done · canceled · wont_fix (default new on ingest) |
notes | Free-form team notes |
hasNotes | true when notes are non-empty |
GET /admin/app-reports accepts ?triageStatus= and returns triageCounts (totals per status across all reports).
PATCH /admin/app-reports/{id}
Update triage classification and/or notes. Body may include either or both fields:
{ "triageStatus": "in_progress", "notes": "API timeout — assigned to backend" }
Returns the updated summary. Invalid triageStatus → 400.
DELETE /admin/app-reports/{id}
Permanently deletes the report row and the stored JSON file on disk. Irreversible.
{ "ok": true, "id": "…", "deletedFile": true }
GET /admin/app-reports/{id}/raw
Download the stored JSON file. Content-Disposition: attachment.
GET /admin/app-reports/{id}/prompts
Build two IDE-agent prompts from the classified findings:
| Field | Audience |
|---|---|
backend | API / backend team |
frontend | Mobile app / frontend team |
Findings with ownership both appear in both prompts with the matching fix text. Each prompt object has title, prompt, findingCount, and a short findings list.
GET /admin/app-reports/{id}/entries
Paginated timeline entries from the stored file.
| Param | Notes |
|---|---|
list | issues (default) · errors · warnings · notes · api · failed-api · slow-api · location · all |
limit | Default 100, max 500 |
offset | Default 0 |