{
  "openapi": "3.0.3",
  "info": {
    "title": "Agnost AI API",
    "description": "Complete REST API for Agnost AI: an analytics and monitoring platform for AI agents.\n\n**Authentication**:\n- SDK ingestion endpoints (`/api/v1/*`) use `x-org-id` header (UUID)\n- Dashboard endpoints use `Authorization: Bearer <jwt>` + `x-org-id` header, or `x-api-key` header\n- API key management uses JWT only (no API key auth)\n",
    "version": "2.1.3",
    "contact": {
      "name": "Agnost AI",
      "url": "https://agnost.ai"
    }
  },
  "servers": [
    {
      "url": "https://api.agnost.ai",
      "description": "Production"
    }
  ],
  "tags": [
    {
      "name": "SDK",
      "description": "Event ingestion endpoints used by SDKs"
    },
    {
      "name": "Dashboard",
      "description": "Analytics and metrics for the dashboard"
    },
    {
      "name": "Organizations",
      "description": "Organization management"
    },
    {
      "name": "Alerts",
      "description": "Alert configuration and monitoring"
    },
    {
      "name": "SOPs",
      "description": "Standard Operating Procedures"
    },
    {
      "name": "Sentiments",
      "description": "Sentiment and intent analysis"
    },
    {
      "name": "Conversations",
      "description": "Conversation message and span retrieval"
    },
    {
      "name": "Classification",
      "description": "LLM-based classification operations"
    },
    {
      "name": "Onboarding",
      "description": "First-run helpers used during organization setup"
    },
    {
      "name": "Connections",
      "description": "External integrations (Slack)"
    },
    {
      "name": "Billing",
      "description": "Stripe billing management"
    },
    {
      "name": "API Keys",
      "description": "API key management"
    },
    {
      "name": "Auth",
      "description": "OAuth authentication callbacks"
    },
    {
      "name": "System",
      "description": "Health checks, webhooks, internal endpoints"
    }
  ],
  "components": {
    "securitySchemes": {
      "OrgId": {
        "type": "apiKey",
        "in": "header",
        "name": "x-org-id",
        "description": "Organization ID (UUID). Used by SDKs for event ingestion. Header is case-insensitive."
      },
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "JWT token from OAuth login."
      },
      "ApiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "API key (`agnost_<64-hex>`) for programmatic dashboard access. Issued via Settings → API Keys."
      },
      "OrgScope": {
        "type": "apiKey",
        "in": "header",
        "name": "x-org-id",
        "description": "Optional. Selects which organization a JWT- or API-key-authenticated request targets when the credential has access to multiple."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          }
        },
        "required": [
          "error"
        ],
        "example": {
          "error": "Invalid request body"
        }
      },
      "Connection": {
        "type": "object",
        "required": [
          "id",
          "org_id",
          "connection_type",
          "connection_name",
          "created_at",
          "created_by",
          "updated_at",
          "active"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "org_id": {
            "type": "string",
            "format": "uuid"
          },
          "connection_type": {
            "type": "string",
            "enum": [
              "slack"
            ]
          },
          "connection_name": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "created_by": {
            "type": "string",
            "format": "uuid"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "active": {
            "type": "integer",
            "enum": [
              0,
              1
            ]
          },
          "team_name": {
            "type": "string"
          },
          "channel_name": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "ready",
              "needs_invite",
              "degraded",
              "unknown"
            ]
          },
          "manual_invite_required": {
            "type": "boolean"
          },
          "last_error": {
            "type": "string"
          },
          "webhook_ready": {
            "type": "boolean"
          },
          "bot_member": {
            "type": "boolean"
          },
          "mentions_ready": {
            "type": "boolean"
          },
          "delivery_healthy": {
            "type": "boolean"
          }
        }
      },
      "TimeRange": {
        "type": "string",
        "enum": [
          "1min",
          "1h",
          "1d",
          "1w",
          "1m",
          "all"
        ],
        "default": "1w"
      },
      "QueryFilters": {
        "type": "object",
        "properties": {
          "time_range": {
            "$ref": "#/components/schemas/TimeRange"
          },
          "connection_type": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ]
          },
          "agent_name": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ]
          },
          "metadata_filters": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "key": {
                  "type": "string"
                },
                "value": {
                  "type": "string"
                }
              }
            }
          },
          "page": {
            "type": "integer",
            "default": 1
          },
          "page_size": {
            "type": "integer",
            "default": 20
          }
        }
      },
      "RawLogsQueryFilters": {
        "allOf": [
          {
            "$ref": "#/components/schemas/QueryFilters"
          },
          {
            "type": "object",
            "properties": {
              "event_id": {
                "type": "string",
                "format": "uuid",
                "description": "Fetches one exact event without applying the approximate raw-log time-window narrowing."
              },
              "conversation_id": {
                "type": "string",
                "format": "uuid",
                "description": "Filters events to one conversation, independently of event_id, and uses the event table's primary-key prefix for an efficient lookup."
              },
              "search_query": {
                "type": "string"
              },
              "success": {
                "type": "boolean"
              },
              "exclude_io": {
                "type": "boolean",
                "default": false,
                "description": "When false, each event includes input/output previews capped at 64 KiB per field. Use `/dashboard/api/event-io` for the full payload of one event."
              }
            }
          }
        ]
      },
      "UserStoriesQueryFilters": {
        "allOf": [
          {
            "$ref": "#/components/schemas/QueryFilters"
          },
          {
            "type": "object",
            "properties": {
              "search": {
                "type": "string",
                "description": "Case-insensitive identifier search used to load matching search options."
              },
              "search_field": {
                "type": "string",
                "enum": [
                  "user_id",
                  "conversation_id",
                  "original_conversation_id",
                  "user_email",
                  "group_value"
                ],
                "description": "Structured identifier selected from User Stories search. Grouped requests accept only `group_value`."
              },
              "search_value": {
                "type": "string",
                "description": "Exact value for the selected search field."
              },
              "group_by": {
                "$ref": "#/components/schemas/UserStoriesGroupBy"
              },
              "sort": {
                "type": "string",
                "enum": [
                  "newest",
                  "oldest"
                ],
                "default": "newest"
              },
              "exclude_io": {
                "type": "boolean",
                "default": false,
                "description": "Omits event input/output payloads when true."
              },
              "allow_limited_preview": {
                "type": "boolean",
                "default": false,
                "description": "Dashboard-only flag for a small access-limited preview; programmatic clients should leave false."
              },
              "sentiment_ids": {
                "type": "array",
                "items": {
                  "type": "string",
                  "format": "uuid"
                },
                "description": "Restricts conversations to events matching any selected intent id."
              },
              "sop_ids": {
                "type": "array",
                "items": {
                  "type": "string",
                  "format": "uuid"
                },
                "description": "Restricts conversations to events matching any selected violation id."
              }
            }
          }
        ]
      },
      "UserStoriesListFilters": {
        "allOf": [
          {
            "$ref": "#/components/schemas/UserStoriesQueryFilters"
          },
          {
            "type": "object",
            "properties": {
              "page_size": {
                "type": "integer",
                "minimum": 1,
                "maximum": 100,
                "default": 50,
                "description": "Conversations, groups, or users per page. The dashboard requests 15 distinct group values at a time."
              },
              "group_level": {
                "type": "string",
                "enum": [
                  "groups",
                  "users",
                  "conversations"
                ],
                "description": "When `group_by` is present, returns metadata groups by default, users within `group_value`, or conversations for `group_user_key`."
              },
              "group_value": {
                "type": "string",
                "description": "Required when `group_level` is `users` or `conversations`."
              },
              "group_user_key": {
                "type": "string",
                "description": "Opaque user key returned by grouped users; required for `group_level: conversations`."
              }
            }
          }
        ]
      },
      "UserStoriesGroupBy": {
        "type": "object",
        "required": [
          "source",
          "key"
        ],
        "properties": {
          "source": {
            "type": "string",
            "enum": [
              "conversation_metadata",
              "user_metadata"
            ]
          },
          "key": {
            "type": "string",
            "description": "Metadata-map key to group by."
          }
        }
      },
      "UserStoriesCostMetadata": {
        "type": "object",
        "additionalProperties": {
          "type": "string"
        },
        "description": "Pricing inputs aggregated from eligible events. Entries contain an explicit cost or a model/provider and token totals; `tokens.aggregated` is `true` for summary buckets, while `tokens.request_input` preserves the per-request input size used to select a model-pricing tier. `pricing.invalid` is `true` when malformed numeric metadata makes that bucket unpriceable."
      },
      "UserStoriesGroupSummary": {
        "type": "object",
        "required": [
          "value",
          "conversation_count",
          "user_count",
          "message_count",
          "intent_count",
          "intent_labels",
          "violation_count",
          "violation_labels",
          "last_active"
        ],
        "properties": {
          "value": {
            "type": "string"
          },
          "conversation_count": {
            "type": "integer",
            "minimum": 0
          },
          "user_count": {
            "type": "integer",
            "minimum": 0
          },
          "message_count": {
            "type": "integer",
            "minimum": 0,
            "description": "Distinct captured events across the group's eligible conversations, including tool events."
          },
          "intent_count": {
            "type": "integer",
            "minimum": 0
          },
          "intent_labels": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "violation_count": {
            "type": "integer",
            "minimum": 0
          },
          "violation_labels": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "last_active": {
            "type": "string",
            "format": "date-time"
          },
          "cost_metadata": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/UserStoriesCostMetadata"
            }
          }
        }
      },
      "UserStoriesUserSummary": {
        "type": "object",
        "required": [
          "key",
          "label",
          "representative_conversation_id",
          "conversation_count",
          "message_count",
          "intent_count",
          "intent_labels",
          "violation_count",
          "violation_labels",
          "last_active"
        ],
        "properties": {
          "key": {
            "type": "string"
          },
          "user_id": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "representative_conversation_id": {
            "type": "string"
          },
          "conversation_count": {
            "type": "integer",
            "minimum": 0
          },
          "message_count": {
            "type": "integer",
            "minimum": 0,
            "description": "Distinct captured events across the user's eligible conversations, including tool events."
          },
          "intent_count": {
            "type": "integer",
            "minimum": 0
          },
          "intent_labels": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "violation_count": {
            "type": "integer",
            "minimum": 0
          },
          "violation_labels": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "last_active": {
            "type": "string",
            "format": "date-time"
          },
          "cost_metadata": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/UserStoriesCostMetadata"
            }
          }
        }
      },
      "UserStoriesVisibleUserSummary": {
        "type": "object",
        "required": [
          "key",
          "conversation_count",
          "message_count",
          "intent_count",
          "intent_labels",
          "violation_count",
          "violation_labels"
        ],
        "properties": {
          "key": {
            "type": "string",
            "description": "Stable `user:<user_id>` key, or `conversation:<conversation_id>` for an anonymous conversation."
          },
          "conversation_count": {
            "type": "integer",
            "minimum": 0
          },
          "message_count": {
            "type": "integer",
            "minimum": 0,
            "description": "Distinct captured events across the user's eligible conversations, including tool events."
          },
          "intent_count": {
            "type": "integer",
            "minimum": 0
          },
          "intent_labels": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "violation_count": {
            "type": "integer",
            "minimum": 0
          },
          "violation_labels": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "cost_metadata": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/UserStoriesCostMetadata"
            }
          }
        }
      },
      "UserStoriesResponse": {
        "type": "object",
        "description": "Returns `conversations`, `groups`, or `users` according to the grouping request.",
        "properties": {
          "conversations": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "groups": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/UserStoriesGroupSummary"
            }
          },
          "users": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/UserStoriesUserSummary"
            }
          },
          "user_summaries": {
            "type": "array",
            "description": "Full filtered-history metrics for users on the current ungrouped interactive page. Empty for grouped or limited-preview responses. Metrics degrade to zero values when optional aggregation is unavailable.",
            "items": {
              "$ref": "#/components/schemas/UserStoriesVisibleUserSummary"
            }
          },
          "group_value": {
            "type": "string"
          },
          "overlapping": {
            "type": "boolean",
            "description": "Metadata arrays may place a conversation in more than one group."
          },
          "page": {
            "type": "integer",
            "minimum": 1
          },
          "page_size": {
            "type": "integer",
            "minimum": 1
          },
          "total_pages": {
            "type": "integer",
            "minimum": 0
          },
          "has_more": {
            "type": "boolean",
            "description": "True when one lookahead row proves that another page is available."
          },
          "partial_data": {
            "type": "boolean",
            "description": "True when optional hydration or enrichment failed and the returned page is incomplete."
          }
        }
      },
      "DashboardTimelinePoint": {
        "type": "object",
        "required": [
          "day",
          "count"
        ],
        "properties": {
          "day": {
            "type": "string",
            "format": "date-time"
          },
          "count": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "CommandCenterMetrics": {
        "type": "object",
        "required": [
          "total_calls",
          "total_conversations",
          "active_users",
          "daily_calls",
          "daily_users",
          "daily_conversations"
        ],
        "properties": {
          "total_calls": {
            "type": "integer",
            "minimum": 0
          },
          "total_conversations": {
            "type": "integer",
            "minimum": 0,
            "description": "Exact distinct conversation count in the selected period."
          },
          "active_users": {
            "type": "integer",
            "minimum": 0
          },
          "daily_calls": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DashboardTimelinePoint"
            }
          },
          "daily_users": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DashboardTimelinePoint"
            }
          },
          "daily_conversations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DashboardTimelinePoint"
            }
          }
        }
      },
      "AnalyticsTagCount": {
        "type": "object",
        "required": [
          "tag",
          "count"
        ],
        "properties": {
          "tag": {
            "type": "string"
          },
          "count": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "AnalyticsTagStats": {
        "type": "object",
        "required": [
          "total_analyzed",
          "total_messages",
          "top_tags",
          "tag_distribution"
        ],
        "properties": {
          "total_analyzed": {
            "type": "integer",
            "minimum": 0
          },
          "total_messages": {
            "type": "integer",
            "minimum": 0
          },
          "top_tags": {
            "type": "array",
            "nullable": true,
            "items": {
              "$ref": "#/components/schemas/AnalyticsTagCount"
            }
          },
          "tag_distribution": {
            "type": "array",
            "nullable": true,
            "items": {
              "$ref": "#/components/schemas/AnalyticsTagCount"
            }
          }
        }
      },
      "ClassificationRequest": {
        "type": "object",
        "properties": {
          "time_range": {
            "$ref": "#/components/schemas/TimeRange"
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 500,
            "default": 50,
            "description": "Maximum conversations to classify in this request"
          },
          "offset": {
            "type": "integer",
            "minimum": 0,
            "default": 0
          },
          "force": {
            "type": "boolean",
            "default": false,
            "description": "Reclassify conversations already marked as analyzed"
          },
          "run_id": {
            "type": "string",
            "description": "Client-generated identifier used to cancel a multi-batch run"
          }
        }
      },
      "AlertConfig": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "event_type": {
            "type": "string",
            "enum": [
              "custom",
              "global_report",
              "suggested_intent"
            ],
            "description": "suggested_intent alerts are triggered by intent discovery rather than the scheduled alert poller."
          },
          "natural_language_query": {
            "type": "string"
          },
          "sql_query": {
            "type": "string"
          },
          "context_sql_query": {
            "type": "string",
            "description": "Required for custom alerts. Returns up to five recent detail rows after the condition threshold is met."
          },
          "action_natural_language_query": {
            "type": "string",
            "description": "Optional instruction used only when no details query is available."
          },
          "threshold_value": {
            "type": "number"
          },
          "threshold_operator": {
            "type": "string",
            "enum": [
              ">",
              "<",
              ">=",
              "<=",
              "=="
            ]
          },
          "check_interval_hours": {
            "type": "integer"
          },
          "connection_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "recipient_emails": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "active": {
            "type": "boolean"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "AlertConfigInput": {
        "allOf": [
          {
            "$ref": "#/components/schemas/AlertConfig"
          },
          {
            "type": "object",
            "properties": {
              "event_type": {
                "type": "string",
                "enum": [
                  "custom",
                  "global_report"
                ]
              }
            }
          }
        ]
      },
      "SOPConfig": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "active": {
            "type": "boolean"
          }
        }
      },
      "SentimentConfig": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "active": {
            "type": "boolean"
          }
        }
      },
      "Organization": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "subscription": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "APIKeyRecord": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "created_by": {
            "type": "string"
          }
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Invalid request body",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing or invalid authentication",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Forbidden": {
        "description": "No access to the requested organization",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "Resource not found",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "ServerError": {
        "description": "Internal server error",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    }
  },
  "paths": {
    "/healthz": {
      "get": {
        "tags": [
          "System"
        ],
        "summary": "Health check",
        "operationId": "healthCheck",
        "security": [

        ],
        "responses": {
          "200": {
            "description": "Service is healthy",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string",
                  "example": "ok"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/capture-session": {
      "post": {
        "tags": [
          "SDK"
        ],
        "summary": "Capture session",
        "description": "Start a session. Call once per conversation; reuse `session_id` on every event.",
        "operationId": "captureSession",
        "parameters": [
          {
            "name": "x-org-id",
            "in": "header",
            "required": true,
            "description": "Your organization ID (UUID, case-insensitive).",
            "schema": {
              "type": "string",
              "example": "<org-id>"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "session_id",
                  "user_data"
                ],
                "properties": {
                  "session_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Session UUID. Reuse on every event in this conversation.",
                    "example": "a3f9c182-7d4e-4b6a-9e21-c5d8f0b4e731"
                  },
                  "user_data": {
                    "type": "object",
                    "description": "End-user identity. `user_id` is required; other traits are supported for analytics. The example shows shape, but production integrations should prefer a stable pseudonymous ID and avoid raw email, name, phone, or other personal data unless explicitly approved.",
                    "required": [
                      "user_id"
                    ],
                    "properties": {
                      "user_id": {
                        "type": "string",
                        "example": "user-anon-002"
                      }
                    },
                    "additionalProperties": {
                      "type": "string"
                    },
                    "example": {
                      "user_id": "user-anon-002",
                      "email": "user@example.com",
                      "user_plan": "pro"
                    }
                  },
                  "metadata": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "Free-form session metadata. Prefer allowlisted operational fields; do not send secrets or sensitive personal data.",
                    "example": {
                      "language": "hi-IN"
                    }
                  },
                  "timestamp": {
                    "type": "integer",
                    "format": "int64",
                    "description": "Unix time in **ms** when the session began. Defaults to server time.",
                    "example": 1714867200000
                  },
                  "client_config": {
                    "type": "string",
                    "description": "Free-form client/SDK label.",
                    "example": "client-segment-001"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Session created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "session_id": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          }
        }
      }
    },
    "/api/v1/capture-event": {
      "post": {
        "tags": [
          "SDK"
        ],
        "summary": "Capture event",
        "description": "Record one turn-pair or tool call. Generate `event_id` client-side so children can reference parents.",
        "operationId": "captureEvent",
        "parameters": [
          {
            "name": "x-org-id",
            "in": "header",
            "required": true,
            "description": "Your organization ID (UUID, case-insensitive).",
            "schema": {
              "type": "string",
              "example": "<org-id>"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "event_id",
                  "session_id",
                  "primitive_name",
                  "args",
                  "result"
                ],
                "properties": {
                  "event_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Client-generated UUID. Use as `parent_id` on child events.",
                    "example": "e8b1c52f-3a9d-4e7c-8f0b-2d6a91c4ef58"
                  },
                  "session_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Session UUID from `capture-session`.",
                    "example": "a3f9c182-7d4e-4b6a-9e21-c5d8f0b4e731"
                  },
                  "primitive_name": {
                    "type": "string",
                    "description": "Agent name (turn-pair) or tool name (tool call).",
                    "example": "your-agent-name"
                  },
                  "args": {
                    "type": "string",
                    "description": "Input — user message or JSON-encoded tool args.",
                    "example": "your input in plain text or JSON-encoded string"
                  },
                  "result": {
                    "type": "string",
                    "description": "Output — assistant reply or JSON-encoded tool result.",
                    "example": "your output in plain text or JSON-encoded string"
                  },
                  "success": {
                    "type": "boolean",
                    "description": "Defaults to `true`."
                  },
                  "latency": {
                    "type": "integer",
                    "description": "Execution time in **ms**.",
                    "example": 5200
                  },
                  "timestamp": {
                    "type": "integer",
                    "format": "int64",
                    "description": "Unix time in **ms** when the event occurred. Defaults to server time.",
                    "example": 1714867201000
                  },
                  "parent_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Parent event UUID. Set on tool calls to point at the agent turn (or parent tool) that triggered them.",
                    "example": "4c7d2e8a-1b95-4f3d-a08e-7b3c9d12f5e6"
                  },
                  "metadata": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "Free-form event metadata.",
                    "example": {
                      "language": "hi-IN"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Event recorded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "event_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          }
        }
      }
    },
    "/api/voice/v1/webhooks/vapi": {
      "post": {
        "tags": [
          "SDK"
        ],
        "summary": "Ingest a Vapi end-of-call report",
        "description": "Translates a Vapi `end-of-call-report` into one Agnost voice\nconversation. The Vapi call ID becomes the conversation ID, the caller\nnumber becomes the user ID, and each caller/assistant exchange becomes\nan event. The completed call total is attached to exactly one event so\nconversation cost aggregation does not multiply it by the turn count.\n\nThe caller number may be supplied in either `message.call.customer.number`\nor `message.customer.number`. Transcript content may be supplied in\n`message.artifact.messages`, `message.artifact.transcript`, or\n`message.transcript`. Internal function calls found in the artifact are\nstored as child tool events beneath their synthetic agent tool-call\nevents, including their arguments, results, timing, and success state.\n",
        "operationId": "ingestVapiEndOfCallReport",
        "parameters": [
          {
            "name": "x-org-id",
            "in": "header",
            "required": true,
            "description": "Your Agnost organization ID (UUID, case-insensitive).",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "message"
                ],
                "properties": {
                  "message": {
                    "type": "object",
                    "required": [
                      "type",
                      "call"
                    ],
                    "properties": {
                      "type": {
                        "type": "string",
                        "enum": [
                          "end-of-call-report"
                        ]
                      },
                      "startedAt": {
                        "type": "string",
                        "format": "date-time"
                      },
                      "endedAt": {
                        "type": "string",
                        "format": "date-time"
                      },
                      "endedReason": {
                        "type": "string"
                      },
                      "durationSeconds": {
                        "type": "number"
                      },
                      "cost": {
                        "type": "number",
                        "minimum": 0,
                        "description": "Vapi's completed total call cost in USD."
                      },
                      "transcript": {
                        "type": "string"
                      },
                      "customer": {
                        "type": "object",
                        "properties": {
                          "number": {
                            "type": "string"
                          }
                        }
                      },
                      "analysis": {
                        "type": "object",
                        "additionalProperties": true
                      },
                      "artifact": {
                        "type": "object",
                        "additionalProperties": true,
                        "properties": {
                          "transcript": {
                            "type": "string"
                          },
                          "messages": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "additionalProperties": true
                            }
                          },
                          "recordingUrl": {
                            "type": "string",
                            "format": "uri"
                          },
                          "stereoRecordingUrl": {
                            "type": "string",
                            "format": "uri"
                          },
                          "logUrl": {
                            "type": "string",
                            "format": "uri"
                          }
                        }
                      },
                      "call": {
                        "type": "object",
                        "required": [
                          "id"
                        ],
                        "additionalProperties": true,
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "orgId": {
                            "type": "string"
                          },
                          "assistantId": {
                            "type": "string"
                          },
                          "phoneNumberId": {
                            "type": "string"
                          },
                          "type": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string"
                          },
                          "customer": {
                            "type": "object",
                            "properties": {
                              "number": {
                                "type": "string"
                              }
                            }
                          },
                          "assistant": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "name": {
                                "type": "string"
                              }
                            }
                          }
                        }
                      }
                    },
                    "additionalProperties": true
                  }
                },
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Report accepted and translated into a conversation.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "status",
                    "session_id",
                    "user_id",
                    "event_count"
                  ],
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "accepted"
                      ]
                    },
                    "session_id": {
                      "type": "string"
                    },
                    "user_id": {
                      "type": "string"
                    },
                    "event_count": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid organization ID, event type, call ID, or caller number."
          },
          "413": {
            "description": "Transcript exceeds the one-megabyte ingestion limit."
          },
          "422": {
            "description": "Missing organization header or usable transcript."
          },
          "500": {
            "description": "Downstream Agnost ingestion failed."
          }
        }
      }
    },
    "/dashboard/api/profile": {
      "get": {
        "tags": [
          "Organizations"
        ],
        "summary": "Get current user profile",
        "operationId": "getProfile",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          }
        ],
        "responses": {
          "200": {
            "description": "User profile with org info"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/dashboard/api/organizations": {
      "get": {
        "tags": [
          "Organizations"
        ],
        "summary": "List organizations",
        "operationId": "listOrganizations",
        "security": [
          {
            "BearerAuth": [

            ]
          }
        ],
        "responses": {
          "200": {
            "description": "List of organizations the user belongs to",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Organization"
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Organizations"
        ],
        "summary": "Create organization",
        "operationId": "createOrganization",
        "security": [
          {
            "BearerAuth": [

            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Organization created"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          }
        }
      }
    },
    "/dashboard/api/organizations/{id}": {
      "put": {
        "tags": [
          "Organizations"
        ],
        "summary": "Update organization",
        "operationId": "updateOrganization",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Organization updated"
          }
        }
      },
      "delete": {
        "tags": [
          "Organizations"
        ],
        "summary": "Delete organization",
        "operationId": "deleteOrganization",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Organization deleted"
          }
        }
      }
    },
    "/dashboard/api/organization/displayId": {
      "get": {
        "tags": [
          "Organizations"
        ],
        "summary": "Get the public-facing org display ID",
        "description": "Returns the short, public-facing display ID for the active organization.\nUsed by the dashboard UI to render a user-friendly org identifier\nwithout exposing the internal UUID.\n",
        "operationId": "getOrgDisplayID",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Display ID for the active organization",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "display_id": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/dashboard/api/organization/summary": {
      "get": {
        "tags": [
          "Organizations"
        ],
        "summary": "Get organization summary",
        "description": "Returns the selected organization's identity and whether its event aggregate contains any data.",
        "operationId": "getOrganizationSummary",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Organization identity and data-presence flag",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "id",
                    "name",
                    "has_data"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "name": {
                      "type": "string"
                    },
                    "has_data": {
                      "type": "boolean",
                      "description": "True when the organization has at least one row in event_daily_stats."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Organization not found"
          }
        }
      }
    },
    "/dashboard/api/organizations/{id}/members": {
      "get": {
        "tags": [
          "Organizations"
        ],
        "summary": "List organization members",
        "operationId": "listOrgMembers",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of members"
          }
        }
      },
      "post": {
        "tags": [
          "Organizations"
        ],
        "summary": "Add member to organization",
        "operationId": "addOrgMember",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Member added"
          }
        }
      }
    },
    "/dashboard/api/login-summary": {
      "get": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Generate login summary",
        "description": "Generates a fresh 48-hour login summary for the selected organization.\nThe response is not persisted; dashboard clients request it after org\nselection settles, then keep it in memory for the current page session.\nIf no recent data exists, the endpoint returns a generic `summary_text`\nwith an empty `sections` array.\n",
        "operationId": "getLoginSummary",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "parameters": [
          {
            "name": "org_id",
            "in": "query",
            "required": false,
            "description": "Organization ID. Optional when org scope is supplied by JWT/API-key auth or `x-org-id`.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Generated login summary",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "org_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "window_start": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "window_end": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "generated_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "summary_text": {
                      "type": "string",
                      "description": "LLM-written summary capped at 90 words, or a generic no-data fallback."
                    },
                    "sections": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "key": {
                            "type": "string",
                            "example": "errors"
                          },
                          "title": {
                            "type": "string",
                            "example": "Critical errors"
                          },
                          "href": {
                            "type": "string",
                            "example": "/errors"
                          },
                          "items": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "title": {
                                  "type": "string"
                                },
                                "detail": {
                                  "type": "string"
                                },
                                "count": {
                                  "type": "integer"
                                },
                                "href": {
                                  "type": "string"
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "id": "89d7ad7e-0248-4f98-abfa-1278ce5b7b4a",
                  "org_id": "5344ec46-cfc4-478a-805f-8c9d0b5ed66a",
                  "window_start": "2026-07-06T12:00:00Z",
                  "window_end": "2026-07-08T12:00:00Z",
                  "generated_at": "2026-07-08T12:00:00Z",
                  "summary_text": "Critical errors remained concentrated in policy checks and webhook probes, with feature-request and billing-dispute intents leading the last 48 hours.",
                  "sections": [
                    {
                      "key": "errors",
                      "title": "Critical errors",
                      "href": "/errors",
                      "items": [
                        {
                          "title": "policy_check",
                          "detail": "4 critical errors in the last 48 hours",
                          "count": 4,
                          "href": "/errors"
                        }
                      ]
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/dashboard/api/user-stories": {
      "post": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Get user stories (conversations)",
        "operationId": "getUserStories",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UserStoriesListFilters"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recent conversations, metadata groups, or users within a metadata group",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserStoriesResponse"
                }
              }
            }
          }
        }
      }
    },
    "/dashboard/api/user-stories/search-options": {
      "post": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Search User Stories identifiers or grouped values",
        "description": "Searches User ID, conversation ID, original conversation ID, and user email when ungrouped. When `group_by` is present, searches only values from that selected metadata field.",
        "operationId": "searchUserStoryIdentifiers",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UserStoriesQueryFilters"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Matching structured identifiers from conversations in the selected organization and time range",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "options"
                  ],
                  "properties": {
                    "options": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "field",
                          "label",
                          "value"
                        ],
                        "properties": {
                          "field": {
                            "type": "string",
                            "enum": [
                              "user_id",
                              "conversation_id",
                              "original_conversation_id",
                              "user_email",
                              "group_value"
                            ]
                          },
                          "label": {
                            "type": "string"
                          },
                          "value": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/dashboard/api/tool-stats": {
      "post": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Get tool usage statistics",
        "operationId": "getToolStats",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QueryFilters"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool usage breakdown"
          }
        }
      }
    },
    "/dashboard/api/tool-checkpoint-stats": {
      "post": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Get tool checkpoint timing stats",
        "operationId": "getToolCheckpointStats",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QueryFilters"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Checkpoint timing statistics"
          }
        }
      }
    },
    "/dashboard/api/tool-error-distribution": {
      "post": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Get error distribution by tool",
        "operationId": "getToolErrorDistribution",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QueryFilters"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Error distribution for the newest 1,000 critical error events matching the tool",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error_messages",
                    "total_errors_in_range",
                    "sample_size",
                    "is_truncated"
                  ],
                  "properties": {
                    "error_messages": {
                      "type": "array",
                      "nullable": true,
                      "maxItems": 10,
                      "items": {
                        "type": "object",
                        "required": [
                          "message",
                          "count"
                        ],
                        "properties": {
                          "message": {
                            "type": "string"
                          },
                          "count": {
                            "type": "integer",
                            "minimum": 1
                          }
                        }
                      }
                    },
                    "total_errors_in_range": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 1000,
                      "description": "Number of errors represented by this newest-error sample"
                    },
                    "sample_size": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 1000
                    },
                    "is_truncated": {
                      "type": "boolean",
                      "description": "True when additional matching errors exist beyond the returned sample"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/dashboard/api/errors": {
      "post": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Get error events",
        "operationId": "getErrors",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/QueryFilters"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "page_size": {
                        "type": "integer",
                        "minimum": 1,
                        "maximum": 1000,
                        "default": 1000
                      },
                      "severity": {
                        "type": "string",
                        "enum": [
                          "all",
                          "critical",
                          "non_critical"
                        ]
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Error statistics and up to the newest 1,000 matching events; Critical uses error_events, Non-critical uses filtered event rows, and All merges both",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "recent_errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "event_id": {
                            "type": "string"
                          },
                          "event_type": {
                            "type": "string"
                          },
                          "event_name": {
                            "type": "string"
                          },
                          "timestamp": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "latency": {
                            "type": "integer"
                          },
                          "error_message": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "recent_errors_truncated": {
                      "type": "boolean",
                      "description": "True only when more than 1,000 events match the request filters"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/dashboard/api/errors/export": {
      "post": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Export errors as CSV",
        "operationId": "exportErrors",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QueryFilters"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "CSV containing the newest 10,000 errors matching the selected range and filters",
            "headers": {
              "X-Export-Row-Limit": {
                "description": "Maximum number of matching rows included in the export",
                "schema": {
                  "type": "integer",
                  "example": 10000
                }
              }
            },
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/dashboard/api/raw-logs": {
      "post": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Get raw event logs",
        "description": "Returns a paginated event list. Input/output hydration runs only for the selected page and each field is capped at a 64 KiB preview; use `/dashboard/api/event-io` for a full single-event payload.",
        "operationId": "getRawLogs",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RawLogsQueryFilters"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Paginated raw log list"
          }
        }
      }
    },
    "/dashboard/api/raw-logs/export": {
      "post": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Export raw logs as CSV",
        "operationId": "exportRawLogs",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QueryFilters"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "CSV file download",
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/dashboard/api/raw-logs/count": {
      "post": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Get total count for raw logs query",
        "description": "Returns the total event count matching the MV-compatible subset of\n`/raw-logs` filters, served from the `event_daily_stats` materialized\nview for sub-second latency. Exact `event_id` and `conversation_id`\nfilters are not supported. The frontend issues this in parallel with\n`/raw-logs` so the page renders immediately and the total fills in\nwhen ready.\n\nReturns `{\"total_count\": null}` when the filter set cannot be answered\nby the materialized view (search query, client_config, connection_type,\nor arbitrary metadata keys other than event_type).\n",
        "operationId": "getRawLogsCount",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QueryFilters"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Total count, or null if filters are MV-incompatible",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "total_count": {
                      "type": "integer",
                      "nullable": true
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/dashboard/api/event-io": {
      "post": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Get input/output for a specific event",
        "operationId": "getEventIO",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "event_id"
                ],
                "properties": {
                  "event_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "conversation_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Optional conversation key for an efficient primary-key lookup."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Event input and output data"
          }
        }
      }
    },
    "/dashboard/api/metadata-distribution": {
      "post": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Get metadata key distribution",
        "operationId": "getMetadataDistribution",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/QueryFilters"
                  },
                  {
                    "type": "object",
                    "required": [
                      "metadata_source",
                      "metadata_field"
                    ],
                    "properties": {
                      "metadata_source": {
                        "type": "string",
                        "enum": [
                          "event_metadata",
                          "event_field",
                          "conversation_metadata",
                          "user_metadata",
                          "user_id",
                          "conversation_user_id"
                        ],
                        "description": "Use conversation_user_id to rank stable conversation user IDs without merging display names or emails."
                      },
                      "metadata_field": {
                        "type": "string"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Distribution of metadata keys"
          }
        }
      }
    },
    "/dashboard/api/command-center-summary": {
      "post": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Get combined command center data",
        "description": "Returns the fixed stats-only Command Center summary: event, user, and conversation totals and timeline buckets plus top error aggregates. Eligible multi-day unfiltered event windows use daily materialized views; short or filtered windows retain raw filtering semantics. SOP stats, sentiment stats, and the separate 120-event raw-log feed load independently.",
        "operationId": "getCommandCenterSummary",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/QueryFilters"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "offset_hours": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 720,
                        "default": 0,
                        "description": "Shifts the selected window into the past by this many hours."
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Combined Command Center metrics and errors",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "metrics",
                    "errors"
                  ],
                  "properties": {
                    "metrics": {
                      "nullable": true,
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/CommandCenterMetrics"
                        }
                      ]
                    },
                    "errors": {
                      "type": "object",
                      "nullable": true
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/dashboard/api/tools-dashboard": {
      "post": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Get combined tools dashboard data",
        "description": "Combines tool stats, time series, and saved charts",
        "operationId": "getToolsDashboard",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QueryFilters"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Combined tools data"
          }
        }
      }
    },
    "/dashboard/api/conversation-messages": {
      "post": {
        "tags": [
          "Conversations"
        ],
        "summary": "Get conversation messages",
        "operationId": "getConversationMessages",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "conversation_id"
                ],
                "properties": {
                  "conversation_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "time_range": {
                    "type": "string",
                    "description": "Optional reporting window applied to conversation events."
                  },
                  "page": {
                    "type": "integer",
                    "minimum": 1,
                    "default": 1
                  },
                  "limit": {
                    "type": "integer",
                    "minimum": 1,
                    "description": "Event rows per page; explicitly supplied values are capped at 100."
                  },
                  "load_io": {
                    "type": "boolean",
                    "default": true,
                    "description": "Resolves readable input/output message content when true."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Conversation messages, with multimodal text/image_url content encoded in versioned message strings",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "conversation_id",
                    "timestamp",
                    "user_id",
                    "messages",
                    "total_messages",
                    "has_more"
                  ],
                  "properties": {
                    "conversation_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "timestamp": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "user_id": {
                      "type": "string"
                    },
                    "messages": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "role": {
                            "type": "string"
                          },
                          "timestamp": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "latency": {
                            "type": "integer"
                          },
                          "success": {
                            "type": "boolean"
                          },
                          "message": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "total_messages": {
                      "type": "integer",
                      "description": "Number of rendered messages in this page."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when another event page is available for the same query."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/dashboard/api/conversation-spans": {
      "post": {
        "tags": [
          "Conversations"
        ],
        "summary": "Get conversation spans (trace)",
        "operationId": "getConversationSpans",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "conversation_id"
                ],
                "properties": {
                  "conversation_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "event_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Optional. Filter to ancestors/descendants of this event"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Span hierarchy for the conversation"
          }
        }
      }
    },
    "/dashboard/api/conversation-audio": {
      "get": {
        "tags": [
          "Conversations"
        ],
        "summary": "Get a presigned URL for a conversation's recorded audio",
        "description": "Returns a short-lived presigned URL the dashboard uses to play back\nrecorded audio for a voice conversation. The audio is stored in\nobject storage and only addressable through this endpoint.\n",
        "operationId": "getConversationAudio",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "parameters": [
          {
            "name": "conversation_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Presigned audio URL",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "url": {
                      "type": "string",
                      "format": "uri"
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "No audio recorded for this conversation"
          }
        }
      }
    },
    "/dashboard/api/conversation-detail": {
      "post": {
        "tags": [
          "Conversations"
        ],
        "summary": "Get conversation detail (messages + spans combined)",
        "operationId": "getConversationDetail",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "conversation_id"
                ],
                "properties": {
                  "conversation_id": {
                    "type": "string",
                    "format": "uuid"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Combined messages and spans",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "messages": {
                      "type": "object"
                    },
                    "spans": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/dashboard/api/spotlight-search": {
      "post": {
        "tags": [
          "Conversations"
        ],
        "summary": "Text search across conversations",
        "operationId": "spotlightSearch",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/QueryFilters"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "question": {
                        "type": "string",
                        "description": "Natural-language analytics question. Preferred over `query` when both are supplied."
                      },
                      "query": {
                        "type": "string",
                        "description": "Backward-compatible natural-language analytics question."
                      },
                      "response_format": {
                        "type": "string",
                        "enum": [
                          "json"
                        ],
                        "description": "Optional structured-answer mode. Requires `response_schema`."
                      },
                      "response_schema": {
                        "type": "object",
                        "maxProperties": 100,
                        "additionalProperties": true,
                        "description": "Bounded JSON response template whose keys and value types the final Spotlight answer must match."
                      }
                    },
                    "anyOf": [
                      {
                        "required": [
                          "question"
                        ]
                      },
                      {
                        "required": [
                          "query"
                        ]
                      }
                    ]
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Search results"
          }
        }
      }
    },
    "/dashboard/api/sops": {
      "get": {
        "tags": [
          "SOPs"
        ],
        "summary": "List SOPs",
        "operationId": "listSOPs",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "responses": {
          "200": {
            "description": "List of SOPs",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SOPConfig"
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "SOPs"
        ],
        "summary": "Create SOP",
        "description": "Active SOPs are applied to new messages and asynchronously evaluated against up to 1,000 recent conversations.",
        "operationId": "createSOP",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "title",
                  "description"
                ],
                "properties": {
                  "title": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  },
                  "active": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "SOP created"
          }
        }
      }
    },
    "/dashboard/api/sops/{id}": {
      "put": {
        "tags": [
          "SOPs"
        ],
        "summary": "Update SOP",
        "description": "Activating an SOP or changing an active SOP's description asynchronously re-evaluates up to 1,000 recent conversations.",
        "operationId": "updateSOP",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  },
                  "active": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "SOP updated"
          }
        }
      },
      "delete": {
        "tags": [
          "SOPs"
        ],
        "summary": "Delete SOP",
        "operationId": "deleteSOP",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "SOP deleted"
          }
        }
      }
    },
    "/dashboard/api/sop-violations": {
      "post": {
        "tags": [
          "SOPs"
        ],
        "summary": "Get SOP violation events",
        "operationId": "getSOPViolations",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QueryFilters"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Events that violated SOPs"
          }
        }
      }
    },
    "/dashboard/api/sop-stats": {
      "post": {
        "tags": [
          "SOPs"
        ],
        "summary": "Get SOP violation distribution stats",
        "description": "Mirrors `/sentiment-stats`. Returns total analyzed events, total events\nin the time range, top violating SOPs, and the full SOP distribution.\n",
        "operationId": "getSOPStats",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QueryFilters"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "SOP distribution with counts per SOP title",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnalyticsTagStats"
                }
              }
            }
          }
        }
      }
    },
    "/dashboard/api/sop-messages": {
      "post": {
        "tags": [
          "SOPs"
        ],
        "summary": "Get assistant messages matching a specific SOP violation",
        "description": "Mirrors `/sentiment-messages`, but matches on the assistant output rather\nthan the user input. The `tag` field is the SOP title to filter on.\n",
        "operationId": "getMessagesBySOP",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/QueryFilters"
                  },
                  {
                    "type": "object",
                    "required": [
                      "tag"
                    ],
                    "properties": {
                      "tag": {
                        "type": "string",
                        "description": "SOP title to match"
                      },
                      "page": {
                        "type": "integer",
                        "default": 1
                      },
                      "limit": {
                        "type": "integer",
                        "default": 50
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Paginated assistant messages that violated the SOP"
          }
        }
      }
    },
    "/dashboard/api/sop-timeline": {
      "post": {
        "tags": [
          "SOPs"
        ],
        "summary": "Get timeline for a single SOP violation",
        "description": "Mirrors `/sentiment-timeline`. Bucketing is automatic based on the time range.",
        "operationId": "getSOPTimeline",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/QueryFilters"
                  },
                  {
                    "type": "object",
                    "required": [
                      "tag"
                    ],
                    "properties": {
                      "tag": {
                        "type": "string",
                        "description": "SOP title"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Per-bucket violation counts plus the bucket size in seconds"
          }
        }
      }
    },
    "/dashboard/api/sop-timelines": {
      "post": {
        "tags": [
          "SOPs"
        ],
        "summary": "Get per-SOP timelines for multiple SOP titles in a single call",
        "description": "Mirrors `/sentiment-timelines`. Pass an array of SOP titles in `tags`.",
        "operationId": "getBatchSOPTimelines",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/QueryFilters"
                  },
                  {
                    "type": "object",
                    "required": [
                      "tags"
                    ],
                    "properties": {
                      "tags": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Map of SOP title → timeline data points"
          }
        }
      }
    },
    "/dashboard/api/summarize-sop-distribution": {
      "post": {
        "tags": [
          "SOPs"
        ],
        "summary": "LLM summary of why a SOP is being violated",
        "description": "Pulls assistant outputs that violated the given SOP within the time\nrange and produces a natural-language summary via the LLM. Mirrors\n`/summarize-intent-distribution`.\n",
        "operationId": "summarizeSOPDistribution",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "tag"
                ],
                "properties": {
                  "org_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "tag": {
                    "type": "string",
                    "description": "SOP title to summarize"
                  },
                  "time_range": {
                    "$ref": "#/components/schemas/TimeRange"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Natural-language summary",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "summary": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/dashboard/api/sentiments": {
      "get": {
        "tags": [
          "Sentiments"
        ],
        "summary": "List sentiment configs",
        "operationId": "listSentiments",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "responses": {
          "200": {
            "description": "List of sentiment configurations",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SentimentConfig"
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Sentiments"
        ],
        "summary": "Create sentiment (intent) config",
        "operationId": "createSentiment",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "title",
                  "description"
                ],
                "properties": {
                  "title": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  },
                  "active": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Sentiment created"
          }
        }
      }
    },
    "/dashboard/api/enrich-intent": {
      "post": {
        "tags": [
          "Sentiments"
        ],
        "summary": "Enrich one intent description",
        "description": "Improves an existing User Intent description while preserving its name.\nThe returned description contains explicit Includes and Excludes clauses.\n",
        "operationId": "enrichIntent",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name",
                  "description"
                ],
                "additionalProperties": false,
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 2000
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Enriched intent description",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "description"
                  ],
                  "additionalProperties": false,
                  "properties": {
                    "description": {
                      "type": "string",
                      "maxLength": 2000
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body or missing organization scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid intent name or description",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Intent enrichment failed or returned invalid output",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "AI service is not configured",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/dashboard/api/sentiments/{id}": {
      "put": {
        "tags": [
          "Sentiments"
        ],
        "summary": "Update sentiment config",
        "operationId": "updateSentiment",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  },
                  "active": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sentiment updated"
          }
        }
      },
      "delete": {
        "tags": [
          "Sentiments"
        ],
        "summary": "Delete sentiment config",
        "operationId": "deleteSentiment",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Sentiment deleted"
          }
        }
      }
    },
    "/dashboard/api/sentiment-stats": {
      "post": {
        "tags": [
          "Sentiments"
        ],
        "summary": "Get sentiment distribution stats",
        "operationId": "getSentimentStats",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QueryFilters"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sentiment distribution with counts per tag",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnalyticsTagStats"
                }
              }
            }
          }
        }
      }
    },
    "/dashboard/api/sentiment-messages": {
      "post": {
        "tags": [
          "Sentiments"
        ],
        "summary": "Get messages matching an active or suggested intent tag",
        "description": "Proactively suggested intents expose up to 20 stored evidence matches before approval. Active and suggested matches honor time_range and metadata filters. Each message includes the authoritative conversation user_id and user_email when available.",
        "operationId": "getMessagesByTag",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/QueryFilters"
                  },
                  {
                    "type": "object",
                    "required": [
                      "tag"
                    ],
                    "properties": {
                      "tag": {
                        "type": "string"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Active intent matches or suggested-intent evidence preview"
          }
        }
      }
    },
    "/dashboard/api/sentiment-timeline": {
      "post": {
        "tags": [
          "Sentiments"
        ],
        "summary": "Get timeline for a single sentiment tag",
        "operationId": "getTagTimeline",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/QueryFilters"
                  },
                  {
                    "type": "object",
                    "required": [
                      "tag"
                    ],
                    "properties": {
                      "tag": {
                        "type": "string"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Daily event counts for the tag"
          }
        }
      }
    },
    "/dashboard/api/sentiment-timelines": {
      "post": {
        "tags": [
          "Sentiments"
        ],
        "summary": "Get timelines for multiple tags (batch)",
        "operationId": "getBatchTagTimelines",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "tags"
                ],
                "properties": {
                  "tags": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "time_range": {
                    "$ref": "#/components/schemas/TimeRange"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Timelines keyed by tag name",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "timelines": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "timestamp": {
                              "type": "string"
                            },
                            "value": {
                              "type": "number"
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/dashboard/api/summarize-intent-distribution": {
      "post": {
        "tags": [
          "Sentiments"
        ],
        "summary": "LLM summary of an intent distribution",
        "description": "Pulls user inputs matching the given intent within the time range and\nproduces a natural-language summary via the LLM.\n",
        "operationId": "summarizeIntentDistribution",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "tag"
                ],
                "properties": {
                  "org_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "tag": {
                    "type": "string",
                    "description": "Intent title to summarize"
                  },
                  "time_range": {
                    "$ref": "#/components/schemas/TimeRange"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Natural-language summary",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "summary": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/dashboard/api/run-intent-classification": {
      "post": {
        "tags": [
          "Classification"
        ],
        "summary": "Run intent classification on conversations",
        "operationId": "runIntentClassification",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClassificationRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Classification results"
          }
        }
      }
    },
    "/dashboard/api/run-sop-classification": {
      "post": {
        "tags": [
          "Classification"
        ],
        "summary": "Run SOP classification on conversations",
        "operationId": "runSOPClassification",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClassificationRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "SOP classification results"
          }
        }
      }
    },
    "/dashboard/api/run-spotlight-query": {
      "post": {
        "tags": [
          "Classification"
        ],
        "summary": "Run LLM-based spotlight query (SSE streaming)",
        "operationId": "runSpotlightLLMQuery",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/QueryFilters"
                  },
                  {
                    "type": "object",
                    "required": [
                      "query"
                    ],
                    "properties": {
                      "query": {
                        "type": "string"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "SSE stream of classification results",
            "content": {
              "text/event-stream": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/dashboard/api/alerts": {
      "get": {
        "tags": [
          "Alerts"
        ],
        "summary": "List alerts",
        "operationId": "listAlerts",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "responses": {
          "200": {
            "description": "List of custom, daily summary, and proactive suggested-intent alert configurations.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AlertConfig"
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Alerts"
        ],
        "summary": "Create alert",
        "description": "Custom alerts require a validated `context_sql_query` in addition to the scalar condition `sql_query`.",
        "operationId": "createAlert",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AlertConfigInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Alert created"
          }
        }
      }
    },
    "/dashboard/api/alerts/{id}": {
      "get": {
        "tags": [
          "Alerts"
        ],
        "summary": "Get alert by ID",
        "operationId": "getAlert",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Alert configuration",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertConfig"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "Alerts"
        ],
        "summary": "Update alert",
        "operationId": "updateAlert",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AlertConfigInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Alert updated"
          }
        }
      },
      "delete": {
        "tags": [
          "Alerts"
        ],
        "summary": "Delete alert",
        "operationId": "deleteAlert",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Alert deleted"
          }
        }
      }
    },
    "/dashboard/api/alerts/{id}/toggle": {
      "post": {
        "tags": [
          "Alerts"
        ],
        "summary": "Toggle alert active status",
        "operationId": "toggleAlert",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Alert toggled"
          }
        }
      }
    },
    "/dashboard/api/alerts/{id}/history": {
      "get": {
        "tags": [
          "Alerts"
        ],
        "summary": "Get alert execution history",
        "operationId": "getAlertHistory",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Last 50 alert executions"
          }
        }
      }
    },
    "/dashboard/api/alerts/generate-query": {
      "post": {
        "tags": [
          "Alerts"
        ],
        "summary": "Generate alert SQL from natural language (LLM)",
        "operationId": "generateAlertQuery",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "natural_language_query"
                ],
                "properties": {
                  "natural_language_query": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Generated SQL query"
          }
        }
      }
    },
    "/dashboard/api/alerts/build-query": {
      "post": {
        "tags": [
          "Alerts"
        ],
        "summary": "Build alert SQL from structured params (no LLM)",
        "operationId": "buildAlertQuery",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "params"
                ],
                "properties": {
                  "params": {
                    "type": "object"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Built SQL query"
          }
        }
      }
    },
    "/dashboard/api/alerts/test-query": {
      "post": {
        "tags": [
          "Alerts"
        ],
        "summary": "Test a SQL query and return results",
        "operationId": "testAlertQuery",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "sql_query"
                ],
                "properties": {
                  "sql_query": {
                    "type": "string"
                  },
                  "query_type": {
                    "type": "string",
                    "enum": [
                      "condition",
                      "action"
                    ],
                    "default": "condition"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Query results"
          }
        }
      }
    },
    "/dashboard/api/alerts/{id}/test": {
      "post": {
        "tags": [
          "Alerts"
        ],
        "summary": "Send a test notification for an existing alert",
        "description": "Fires the alert's notification action immediately, with sample/test\ncontext, so the user can verify the wiring (Slack channel, email\nrecipients, message format) without waiting for the next scheduled\nevaluation.\n",
        "operationId": "sendTestNotification",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Test notification sent"
          }
        }
      }
    },
    "/dashboard/api/alerts/summarize-action": {
      "post": {
        "tags": [
          "Alerts"
        ],
        "summary": "LLM summarize action query results",
        "operationId": "summarizeAction",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "action_prompt",
                  "rows"
                ],
                "properties": {
                  "action_prompt": {
                    "type": "string"
                  },
                  "rows": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Summary text"
          }
        }
      }
    },
    "/dashboard/api/report-config": {
      "get": {
        "tags": [
          "Alerts"
        ],
        "summary": "Get report configuration",
        "operationId": "getReportConfig",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Report configuration"
          }
        }
      },
      "put": {
        "tags": [
          "Alerts"
        ],
        "summary": "Update report configuration",
        "operationId": "saveReportConfig",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "delivery_time": {
                    "type": "string",
                    "pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$",
                    "description": "UTC delivery time; the dashboard converts it to and from browser-local time."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Report config saved"
          }
        }
      }
    },
    "/dashboard/api/dashboard/charts": {
      "get": {
        "tags": [
          "Dashboard"
        ],
        "summary": "List saved dashboard charts",
        "operationId": "listDashboardCharts",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "responses": {
          "200": {
            "description": "List of chart configurations"
          }
        }
      },
      "post": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Create dashboard chart",
        "operationId": "createDashboardChart",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Chart created"
          }
        }
      }
    },
    "/dashboard/api/dashboard/charts/{id}": {
      "delete": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Delete dashboard chart",
        "operationId": "deleteDashboardChart",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Chart deleted"
          }
        }
      }
    },
    "/dashboard/api/dashboard/charts/reorder": {
      "put": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Reorder dashboard charts",
        "operationId": "reorderDashboardCharts",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "chart_ids"
                ],
                "properties": {
                  "chart_ids": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Charts reordered"
          }
        }
      }
    },
    "/dashboard/api/organization/event-keys": {
      "get": {
        "tags": [
          "Organizations"
        ],
        "summary": "Get event metadata key configuration",
        "operationId": "getEventKeys",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Event key configuration"
          }
        }
      },
      "put": {
        "tags": [
          "Organizations"
        ],
        "summary": "Update event metadata keys",
        "operationId": "updateEventKeys",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "keys": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "include_keys": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Event keys updated"
          }
        }
      }
    },
    "/dashboard/api/organization/conversation-keys": {
      "get": {
        "tags": [
          "Organizations"
        ],
        "summary": "Get conversation and user metadata keys",
        "operationId": "getConversationKeys",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Conversation key configuration",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "conversation_keys",
                    "conversation_metadata_keys",
                    "user_metadata_keys"
                  ],
                  "properties": {
                    "conversation_keys": {
                      "type": "array",
                      "description": "Legacy combined registry of conversation and user metadata keys.",
                      "items": {
                        "type": "string"
                      }
                    },
                    "conversation_metadata_keys": {
                      "type": "array",
                      "description": "Keys discovered from conversation metadata.",
                      "items": {
                        "type": "string"
                      }
                    },
                    "user_metadata_keys": {
                      "type": "array",
                      "description": "Keys discovered from conversation user metadata.",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "Organizations"
        ],
        "summary": "Update conversation metadata keys",
        "operationId": "updateConversationKeys",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "keys": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "include_keys": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Conversation keys updated"
          }
        }
      }
    },
    "/dashboard/api/organization/api-keys": {
      "get": {
        "tags": [
          "API Keys"
        ],
        "summary": "List API keys",
        "operationId": "listAPIKeys",
        "security": [
          {
            "BearerAuth": [

            ]
          }
        ],
        "responses": {
          "200": {
            "description": "List of API keys (hashes, not raw keys)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "api_keys": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/APIKeyRecord"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "API Keys"
        ],
        "summary": "Create API key",
        "operationId": "createAPIKey",
        "security": [
          {
            "BearerAuth": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "API key created (raw key returned ONCE)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "api_key": {
                      "type": "string",
                      "description": "Raw API key. Store securely, shown only once"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/dashboard/api/organization/api-keys/{id}": {
      "delete": {
        "tags": [
          "API Keys"
        ],
        "summary": "Delete API key",
        "operationId": "deleteAPIKey",
        "security": [
          {
            "BearerAuth": [

            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "API key deleted"
          }
        }
      }
    },
    "/dashboard/api/connections": {
      "get": {
        "tags": [
          "Connections"
        ],
        "summary": "List connections",
        "operationId": "listConnections",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "responses": {
          "200": {
            "description": "List of external integrations",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Connection"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/dashboard/api/connections/initiate-slack": {
      "post": {
        "tags": [
          "Connections"
        ],
        "summary": "Initiate Slack OAuth flow",
        "operationId": "initiateSlackOAuth",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "org_id": {
                    "type": "string",
                    "format": "uuid"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Slack OAuth URL",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "oauth_url"
                  ],
                  "properties": {
                    "oauth_url": {
                      "type": "string",
                      "format": "uri"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/dashboard/api/connections/{id}": {
      "delete": {
        "tags": [
          "Connections"
        ],
        "summary": "Delete connection",
        "operationId": "deleteConnection",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Connection disconnected and detached from alert/report configurations",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/dashboard/api/connections/{id}/verify": {
      "post": {
        "tags": [
          "Connections"
        ],
        "summary": "Verify Slack bot channel access",
        "operationId": "verifySlackConnection",
        "description": "Sends a visible test message as the bot and refreshes connection readiness. A 409 response means the bot still needs a channel invite or Slack rejected the post.",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Bot posting and mention follow-ups are ready",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "status"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "ready"
                      ]
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Bot cannot yet post in the selected channel",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error",
                    "status"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "needs_invite",
                        "degraded"
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/dashboard/api/connections/{id}/send-message": {
      "post": {
        "tags": [
          "Connections"
        ],
        "summary": "Send message via Slack connection",
        "operationId": "sendSlackMessage",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "message"
                ],
                "properties": {
                  "message": {
                    "type": "string"
                  },
                  "channel": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Message sent"
          }
        }
      }
    },
    "/dashboard/api/billing/create-checkout": {
      "post": {
        "tags": [
          "Billing"
        ],
        "summary": "Create Stripe checkout session",
        "operationId": "createCheckoutSession",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "org_id"
                ],
                "properties": {
                  "org_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "tier": {
                    "type": "string",
                    "enum": [
                      "starter",
                      "pro"
                    ],
                    "default": "pro"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Stripe checkout URL",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "url": {
                      "type": "string",
                      "format": "uri"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid or unconfigured checkout tier"
          }
        }
      }
    },
    "/dashboard/api/billing/create-portal": {
      "post": {
        "tags": [
          "Billing"
        ],
        "summary": "Create Stripe billing portal session",
        "operationId": "createPortalSession",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Stripe portal URL",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "url": {
                      "type": "string",
                      "format": "uri"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/dashboard/api/billing/cancel": {
      "post": {
        "tags": [
          "Billing"
        ],
        "summary": "Cancel subscription",
        "operationId": "cancelSubscription",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Subscription cancelled"
          }
        }
      }
    },
    "/dashboard/api/onboarding/describe-product": {
      "post": {
        "tags": [
          "Onboarding"
        ],
        "summary": "Stream an LLM-generated product description from a website",
        "description": "Fetches the user's website (either a URL passed directly or inferred\nfrom a corporate email domain) and streams a 2-3 sentence product\ndescription over Server-Sent Events. Used during organization setup\nso the user does not have to write the description by hand.\n\nReturns 422 if the email domain is a free email provider, the site\ncannot be reached, or extraction yielded too little content. The\nclient should ask the user to describe the product manually in those\ncases.\n\nResponse is `text/event-stream`. Each event is a JSON object:\n`{\"text\": \"...\"}` for incremental tokens, `{\"error\": \"...\"}` for\nterminal failure. The stream ends with a `[DONE]` sentinel.\n",
        "operationId": "onboardingDescribeProduct",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "description": "Website URL (preferred). Either url or email is required."
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "description": "Falls back to the email's domain if url is not provided."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Server-Sent Events stream of description tokens",
            "content": {
              "text/event-stream": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "422": {
            "description": "Personal email, unreachable site, or insufficient content"
          }
        }
      }
    },
    "/auth/callback": {
      "get": {
        "tags": [
          "Auth"
        ],
        "summary": "Google OAuth callback (redirect)",
        "operationId": "googleOAuthCallbackGet",
        "security": [

        ],
        "parameters": [
          {
            "name": "code",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "302": {
            "description": "Redirects to frontend with JWT token"
          }
        }
      },
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "Google OAuth callback (JSON response)",
        "operationId": "googleOAuthCallbackPost",
        "security": [

        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "code"
                ],
                "properties": {
                  "code": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JWT token",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "token": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/auth/slack/callback": {
      "get": {
        "tags": [
          "Auth"
        ],
        "summary": "Slack OAuth callback",
        "operationId": "slackOAuthCallback",
        "security": [

        ],
        "parameters": [
          {
            "name": "code",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "302": {
            "description": "Redirects to frontend"
          }
        }
      }
    },
    "/webhooks/stripe": {
      "post": {
        "tags": [
          "System"
        ],
        "summary": "Stripe webhook",
        "operationId": "stripeWebhook",
        "security": [

        ],
        "description": "Verified via Stripe-Signature header",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Webhook processed"
          },
          "400": {
            "description": "Invalid signature"
          }
        }
      }
    },
    "/dashboard/api/classify": {
      "post": {
        "tags": [
          "Classification"
        ],
        "summary": "Unified classification endpoint",
        "description": "Dispatches to intent, SOP, or spotlight classification based on type field.\nReplaces separate run-intent-classification, run-sop-classification, and run-spotlight-query endpoints.\n",
        "operationId": "runClassification",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/QueryFilters"
                  },
                  {
                    "type": "object",
                    "required": [
                      "type"
                    ],
                    "properties": {
                      "type": {
                        "type": "string",
                        "enum": [
                          "intent",
                          "sop",
                          "spotlight"
                        ]
                      },
                      "query": {
                        "type": "string",
                        "description": "Required for spotlight type"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Classification results"
          }
        }
      }
    },
    "/dashboard/api/alerts/query": {
      "post": {
        "tags": [
          "Alerts"
        ],
        "summary": "Unified alert query endpoint",
        "description": "Dispatches to generate, build, test, or summarize based on action field.\nReplaces separate generate-query, build-query, test-query, and summarize-action endpoints.\n",
        "operationId": "alertQuery",
        "security": [
          {
            "BearerAuth": [

            ],
            "OrgScope": [

            ]
          },
          {
            "ApiKey": [

            ]
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "action"
                ],
                "properties": {
                  "action": {
                    "type": "string",
                    "enum": [
                      "generate",
                      "build",
                      "test",
                      "summarize"
                    ]
                  },
                  "natural_language_query": {
                    "type": "string",
                    "description": "For generate action"
                  },
                  "params": {
                    "type": "object",
                    "description": "For build action"
                  },
                  "sql_query": {
                    "type": "string",
                    "description": "For test action"
                  },
                  "query_type": {
                    "type": "string",
                    "enum": [
                      "condition",
                      "action"
                    ],
                    "description": "For test action"
                  },
                  "action_prompt": {
                    "type": "string",
                    "description": "For summarize action"
                  },
                  "rows": {
                    "type": "string",
                    "description": "For summarize action"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Query operation results"
          }
        }
      }
    }
  }
}
