Support Ai API
14 endpoints in this group.
GET /api/support/ai/cases
List My Cases
List the caller's support cases.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
status_filter | query | string | optional |
Responses
| Code | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
POST /api/support/ai/cases
Create Case
Create a tenant-scoped human support case for the caller.
Request body: application/json
Responses
| Code | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
GET /api/support/ai/cases/{case_id}
Get My Case
Fetch one caller-owned support case with public comments.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
case_id | path | integer | required |
Responses
| Code | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
POST /api/support/ai/cases/{case_id}/comments
Add My Case Comment
Add a public caller comment to an open support case.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
case_id | path | integer | required |
Request body: application/json
Responses
| Code | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
GET /api/support/ai/conversations
List Conversations
Responses
| Code | Description |
|---|---|
200 | Successful Response |
POST /api/support/ai/conversations
Create Conversation
Create a new support conversation owned by the authenticated user.
Returns the new conversation_id. The full SSE message turn (LLM streaming + tool execution) lands in .
Request body: application/json
Responses
| Code | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
DELETE /api/support/ai/conversations/{conversation_id}
Delete Conversation
GDPR delete () — cascade-delete user's conversation + messages.
Was a temporary unavailable stub in prior . Now actually deletes:
- support_ai_intent_classifications (via message FK)
- support_ai_tool_calls (via message FK)
- support_ai_feedback (via message FK)
- support_ai_messages (via conversation FK CASCADE)
- support_ai_conversations row itself
Audit events for admin actions are retained per (the user's own conversation deletion is not an audit-retained event — it's a data-subject right).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
conversation_id | path | integer | required |
Responses
| Code | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
GET /api/support/ai/conversations/{conversation_id}
Get Conversation
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
conversation_id | path | integer | required |
Responses
| Code | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
POST /api/support/ai/conversations/{conversation_id}/escalate
Escalate Conversation
Mark conversation as escalated ().
Was a temporary unavailable stub in prior . Now sets status='escalated'
and returns the ticket-form URL for the FE to redirect into the
existing support-ticket flow with the conversation snapshot.
Per : ticket creation is FE-mediated — the bot does NOT auto-create a ticket. After escalation, the conversation is read-only (the message endpoint will reject new turns once status='escalated' — enforced when wires the streaming path).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
conversation_id | path | integer | required |
Request body: application/json
Responses
| Code | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
POST /api/support/ai/conversations/{conversation_id}/feedback
Submit Feedback
Persist user feedback on a conversation; auto-flag for improvement.
Improvement loop :
- Negative feedback (helpful=false OR rating<=2) auto-creates a
training candidate row with
candidate_type='negative_feedback', status='queued', PII-redacted comment. - Admin reviews via admin endpoints (approve/reject).
- Approved candidates are exported by an offline pipeline (not in this PR — see ).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
conversation_id | path | integer | required |
Request body: application/json
Responses
| Code | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
POST /api/support/ai/conversations/{conversation_id}/messages
Create Message
Submit a user turn.
Order per :
- master flag → typed-degraded
master_flag_offif off - tenant + user scope assertion
- rate-limit + cost-cap gate ( critical gap)
- ownership check on conversation_id (cross-tenant 404)
- classifier — refused intents short-circuit (no LLM call, no assistant turn row; user turn + classification persisted)
- allowed intents:
- SSE clients (Accept: text/event-stream) get a streaming
assistant turn through
_stream_assistant_response, Layer D output filter applied on accumulated text - JSON clients get a
runtime_not_wiredtyped-degraded — SSE is the supported path for
- SSE clients (Accept: text/event-stream) get a streaming
assistant turn through
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
conversation_id | path | integer | required | |
accept | header | — | optional |
Request body: application/json
Responses
| Code | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
POST /api/support/ai/disclosure/accept
Accept Disclosure
Pin AI-disclosure acceptance for the user ().
Idempotent: re-accepting the same version is a no-op (the latest
accepted_at simply moves forward).
Request body: application/json
Responses
| Code | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
GET /api/support/ai/disclosure/status
Disclosure Status
Has the user accepted the current AI-disclosure version ()?
Responses
| Code | Description |
|---|---|
200 | Successful Response |
GET /api/support/ai/quota
Get Quota Status
Return the caller's current AI Support quota status.
Responses
| Code | Description |
|---|---|
200 | Successful Response |