Skip to main content
These endpoints read the per-conversation signals Moda detects on ingested data: user frustration and other emotions, tool failures, and grounding (hallucination) results. Detections typically appear within minutes of ingest. The same data drives the Signals dashboard.

GET /frustrations

Frustration detections with evidence, verbatim user quotes, and an embedded context window.

Query parameters

integer
default:"7"
1–90.
integer
default:"10"
1–20. This endpoint’s cap is 20, lower than the general 100.
integer
default:"0"
0–10,000.

Response fields

object
total_analyzed (conversations analyzed in the window), frustrated_count, at_risk_count (risk score at least 0.5 but not frustrated), frustration_rate_pct.
object
Map of frustration signal to count, across frustrated conversations only.
array
Frustrated and at-risk conversations, ordered by frustration_score then risk_score. Each row has conversation_id, is_frustrated, frustration_score, risk_score, trajectory, target, primary_cause, evidence, user_quotes[] (turn, quote, signal), expressed_signals[], observed_signals[], key_turns[], message_count, detected_at, and conversation — an embedded context window (same shape as /conversations/:id/context) centered on the first key turn, or null.
object
limit, offset, total, has_more.

Example

GET /emotions

Multi-family emotion detections. Moda scores six families — frustration, sadness, confusion, anxiety, trust, positive — with one detection row per conversation and family. See Signals in the dashboard for the full 16-signal taxonomy.

Query parameters

integer
default:"7"
1–90.
integer
default:"10"
1–20.
integer
default:"0"
0–10,000.
string
Filter the paginated detections list (and its total) to one family. The summary and signal_breakdown always cover all families. Unknown values return 400.

Response fields

object
conversations_analyzed, by_family (detected count per family), negative_rate_pct (share of analyzed conversations with any negative-family detection), positive_rate_pct, and repair_rate_pct (share of negative detections whose trajectory resolved).
array
{family, signal, count} rows across detected conversations.
array
Detected and at-risk rows, ordered by score. Each has detection_id, conversation_id, user_id, family, is_detected, score, risk_score, trajectory, elicitor, primary_cause, evidence, user_quotes[], expressed_signals[], observed_signals[], key_turns[], downgrade_reason, detection_grade (rlm for deep analyses, light for the positive-family fast path), message_count, detected_at, and conversation_context (embedded context window or null).
object
limit, offset, total, has_more.

Example

GET /tool-failures

Per-tool failure KPIs for the window. Only tools with at least one failure are listed. This endpoint has no pagination; use /tool-failures/:toolName for examples.

Query parameters

integer
default:"7"
1–90.

Response fields

object
total (failed calls), total_calls (all calls), conversations (with a failure), tools (with a failure), failure_rate_pct.
array
Ordered by failure_count descending. Each has tool_name, failure_count, total_count, failure_rate_pct, conversation_count, top_error (a sample error message, truncated to 80 characters), last_seen.

Example

GET /tool-failures/:toolName

Failure detail for one tool: a breakdown by error subtype plus individual examples with embedded conversation context. Subtype names come from your tenant’s failure taxonomy — they are labels, not a fixed enum.

Query parameters

string
Filter examples (and the pagination total) to one error subtype. The subtypes breakdown is always unfiltered.
integer
default:"7"
1–90.
integer
default:"5"
1–20.
integer
default:"0"
0–10,000.

Response fields

string
array
{subtype, count, conversation_count, sample_error, last_seen} per error subtype.
array
Newest first. Each has failure_id, conversation_id, error_message, error_subtype, tool_input (truncated), msg_index, detected_at, and conversation — an embedded context window centered on the failing call, or null.
object
limit, offset, total, has_more.

Example

GET /hallucinations

Grounding results: agent claims checked against the conversation’s world state and tool results.
The per-message detections list contains only two kinds of rows: contradicted (a claim contradicted by evidence) and verified (a claim confirmed by evidence). Ungrounded claims — statements with no supporting or contradicting evidence — appear only in the summary aggregates and are never listed per message.

Query parameters

integer
default:"7"
1–90.
integer
default:"10"
1–20.
integer
default:"0"
0–10,000.
string
Scope the response — including the summary aggregates — to one conversation.
string
contradicted or verified. Filters the detections list and its total.

Response fields

object
Counts across all scored claims: total_scored, contradicted_count, verified_count, ungrounded_count, ungrounded_rate (0–1), conversations_scored, conversations_with_contradiction, and rule_breakdown[] ({source, rule_id, count} for contradictions).
array
Contradicted rows first, then by confidence. Each has conversation_id, message_index, unit_id, segment_id, kind (contradicted or verified), label, confidence, source, rule_id, model_id, violated_receipt_id (or null), violated_slot_key, violated_thread_id, offending_substring, evidence_quote, cws_high_water_msg_index, message_count, detected_at.
object
limit, offset, total. This endpoint does not return has_more; page until fewer than limit rows come back or offset + limit >= total.

Example

Next steps

  • Conversations — pull a wider context window around any detection’s key turn.
  • Problems — signals grouped into ranked root-cause problems.
  • Dashboard: Signals — the same detections with the full emotion and failure taxonomies.