ThunderPhone 2.0 is live.Self-serve, from 2¢/min.Read the announcement

Calls

Issue Reports

Org-wide feed of issue reports filed against calls.

Issue reports flag specific calls for quality review. They are created on a per-call basis via POST /v1/calls/{call_id}/issue-reports and can also be filed automatically by call grading when it detects an issue pattern. This page documents the org-wide feed — use it to build dashboards and route issues to your QA workflow.

Endpoints

MethodPathDescription
GET/v1/issue-reportsList issue reports across all calls (paginated)
PATCH/v1/issue-reportsBulk-update status by trace_id
PATCH/v1/issue-reports/{trace_id}Update one report's status

Issue report object

{
  "id": 4321,
  "trace_id": "5f9a...",
  "call_id": 987654321,
  "agent_id": 12,
  "source": "user",
  "severity": "warning",
  "status": "open",
  "title": "Agent paused too long",
  "description": "Five-second silence before responding to the main question.",
  "what_went_wrong": "",
  "suggested_fix": "",
  "timestamp_seconds": 48,
  "failing_turn_index": null,
  "detected_issue_ref": null,
  "metadata": {},
  "reported_by_id": 7,
  "linked_test_cases": [],
  "regression_guarded": false,
  "created_at": "2026-04-20T18:25:11.002Z",
  "updated_at": "2026-04-20T18:25:11.002Z"
}
FieldTypeDescription
idintegerIssue report id
trace_idUUIDStable id for external linking — also the key for status updates
call_idintegerParent call
agent_idinteger | nullAgent that handled the parent call
sourcestringuser (manually filed from the UI / API) or system (automatically filed — e.g. by call grading)
severitystringinfo, warning, or critical
statusstringopen, acknowledged, or resolved
titlestringShort description, 1–255 chars
descriptionstringFree-form body
what_went_wrongstringGrader analysis of the failure (system reports)
suggested_fixstringGrader-suggested remediation (system reports)
timestamp_secondsinteger | nullOffset in seconds into the call the issue refers to
failing_turn_indexinteger | nullTranscript turn index where the issue manifested — used by investigations to replay from the right point
detected_issue_refstring | nullFree-form id set by grading to correlate recurring patterns
metadataobjectFree-form bag for your own app data
reported_by_idinteger | nullUser id of the reporter. null when created by the system
linked_test_casesarrayTest scenarios created from this issue: {id, agent_id, title, source, latest_verdict, created_at}
regression_guardedbooleanTrue when the issue has linked scenarios and every one currently passes
created_at, updated_attimestampISO 8601 UTC

List issue reports

cURL
curl 'https://api.thunderphone.com/v1/issue-reports?severity=critical' \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY"
Python
issues = requests.get(
    "https://api.thunderphone.com/v1/issue-reports",
    headers={"Authorization": "Bearer sk_live_YOUR_API_KEY"},
    params={"severity": "critical"},
).json()

Query parameters

ParamTypeDescription
severitystringFilter: info, warning, critical
statusstringFilter: open, acknowledged, resolved
call_idintegerFilter to a single call
agent_idintegerFilter to reports on calls handled by this agent
start_dateISO 8601Earliest created_at
end_dateISO 8601Latest created_at
limitintegerPage size (default 100, capped at 500)
offsetinteger

Returns 200 OK with a paginated envelope of Issue report objects, ordered by severity (criticalwarninginfo) and then newest first:

{
  "results": [ /* Issue report objects */ ],
  "total": 42,
  "limit": 100,
  "offset": 0
}

Update a report's status

Reports move through openacknowledgedresolved (any transition is allowed). Both update endpoints accept only status.

Single report

cURL
curl -X PATCH https://api.thunderphone.com/v1/issue-reports/5f9a... \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"status": "resolved"}'

The path key is the report's trace_id (not the integer id). Returns 200 OK with the updated Issue report object, or 404 if no report with that trace_id exists in your org.

Bulk

cURL
curl -X PATCH https://api.thunderphone.com/v1/issue-reports \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "trace_ids": ["5f9a...", "77b1..."],
    "status": "acknowledged"
  }'
FieldTypeRequiredDescription
trace_idsarray of UUIDyes1–500 ids
statusstringyesopen, acknowledged, or resolved
Response
{ "updated": 2 }

Unknown trace_ids are skipped silently — updated counts the rows actually changed.


Issue clusters

Reports that share a failure mechanism are grouped into clusters — the rows on the dashboard's Issues page. Each cluster carries a name, a failure-mode description, a fix lane, aggregate counts, and (when one exists) a summary of its latest investigation.

List issue clusters

GET /v1/issue-clusters

Returns { "results": [...], "total": n, "limit": n, "offset": n }. Each cluster includes fix_lane (prompt, audio, runtime, model, config, infra, other), severity, call_count, report_count, investigation_summary, and flagged_at — when the cluster was flagged to ThunderPhone (platform-side lanes are flagged automatically; so are prompt issues whose investigation ended without a confirmed fix).

Update a cluster

PATCH /v1/issue-clusters/{cluster_id}

Accepts status (open, acknowledged, resolved) and/or fix_lane with fix_lane_source. Setting a status cascades to the cluster's reports; reclassifying onto a platform-side lane flags the cluster to ThunderPhone automatically.

Escalate a cluster

POST /v1/issue-clusters/{cluster_id}/escalate

Body: { "note": "..." }. Sends the cluster to ThunderPhone with a full evidence bundle (reports, evidence values, recent investigation results). Escalating again appends your note to the open escalation. Emits the issue.escalated webhook.