Skip to main content
Authenticated API

This endpoint requires a valid JWT Bearer token. Accessible via the API gateway at /v1/voice-ai/*.

Voice AI API

Voice AI assistant (Hey Maximus) for voice queries, commands, proactive alerts, and real-time speech processing.

Overview

AttributeValue
Base Path/api/v1/voice-ai
AuthenticationBearer Token
Required Rolespos_staff, server, restaurant_staff, kitchen, host, bartender, cashier, chef, manager, drive_thru_staff, restaurant_manager, tenant_admin, platform_admin, system_admin, super_admin
Real-timeWebSocket at /api/voice-ai/stream/{session_id} (Python service only; not proxied through Go gateway)

Health & Status

Health Check

Check Voice AI service health and agent availability.

GET /api/v1/voice-ai/health

Response

{
"status": "healthy",
"service": "voice-ai-manager",
"agent_available": true,
"timestamp": "2026-02-19T14:30:00Z"
}

The status field returns "healthy" when the LangGraph voice agent is loaded, or "degraded" when the agent is unavailable.


Agent Status

Get Voice AI agent capabilities and supported intents.

GET /api/v1/voice-ai/status

Response

{
"available": true,
"capabilities": [
"query_sales",
"query_labor",
"query_inventory",
"query_performance",
"query_forecast",
"command_pricing",
"command_special",
"command_message"
],
"supported_intents": [
"query_sales",
"query_labor",
"query_inventory",
"query_performance",
"query_forecast",
"command_pricing",
"command_special",
"command_message",
"general"
],
"wake_words": ["hey maximus", "maximus", "hey max"],
"message": "Voice AI agent ready"
}

When the agent is not installed, available is false, capabilities and supported_intents are empty arrays, and message returns "Agent not installed".


Voice Queries

Process Voice Query

Send a text transcript for AI processing through the Voice AI Manager LangGraph agent. The Go gateway extracts tenant_id and user_id from the JWT token and forwards them to the Python service.

POST /api/v1/voice-ai/query

Request Body

{
"transcript": "Hey Maximus, what were my sales yesterday?",
"location_id": "loc-456",
"session_id": "sess-789",
"include_ssml": true
}
FieldTypeRequiredDescription
transcriptstringYesVoice transcript text
location_idstringYesLocation identifier
session_idstringNoSession identifier (auto-generated if omitted)
include_ssmlbooleanNoInclude SSML for TTS synthesis (default: true)

Response

{
"response_text": "Yesterday's sales were $11,200 across 260 orders. That's up 8% from the day before.",
"response_ssml": "<speak>Yesterday's sales were <say-as interpret-as='currency'>$11,200</say-as>...</speak>",
"intent": "query_sales",
"confidence": 0.95,
"analytics_result": {
"sales_total": 11200.00,
"order_count": 260,
"comparison_percent": 8
},
"requires_confirmation": false,
"session_id": "sess-789"
}
FieldTypeDescription
response_textstringNatural language response
response_ssmlstringSSML for TTS synthesis (null if include_ssml was false)
intentstringClassified intent (e.g., query_sales, query_labor, general)
confidencefloatIntent confidence score (0.0 to 1.0)
analytics_resultobjectAnalytics data returned by the agent (null if not applicable)
requires_confirmationbooleanWhether a follow-up command needs confirmation
session_idstringSession identifier

Voice Commands

Execute Command

Execute a voice command through the Voice AI Manager agent. Commands support permission checking based on user roles.

POST /api/v1/voice-ai/command

Request Body

{
"command": "Turn on Happy Hour pricing",
"location_id": "loc-456",
"session_id": "sess-789",
"confirmed": true
}
FieldTypeRequiredDescription
commandstringYesVoice command text
location_idstringYesLocation identifier
session_idstringNoSession identifier (auto-generated if omitted)
confirmedbooleanNoWhether the command is pre-confirmed (default: false)

Response

{
"success": true,
"response_text": "Done. Happy Hour pricing is now active.",
"response_ssml": "<speak>Done. Happy Hour pricing is now active.</speak>",
"command_type": "command_pricing",
"result": {
"success": true,
"pricing_mode": "happy_hour",
"activated_at": "2026-02-19T16:00:00Z"
}
}
FieldTypeDescription
successbooleanWhether the command executed successfully
response_textstringNatural language response
response_ssmlstringSSML for TTS synthesis (may be null)
command_typestringClassified command type
resultobjectCommand execution result (may be null)

Supported Command Types

TypeExamples
enable_pricing"Turn on Happy Hour pricing"
add_special"Add a daily special: Grilled Salmon $24.99"
send_message"Send the team a message about the VIP party tonight"
86_item"86 the salmon", "Bring back the salmon"

Alerts & Notifications

Get Proactive Alerts

Retrieve pending proactive alerts from Maximus for a location.

GET /api/v1/voice-ai/alerts

Query Parameters

ParameterTypeRequiredDescription
location_idstringYesLocation identifier

The tenant_id is extracted from the JWT token by the Go gateway.

Response

{
"alerts": [
{
"id": "ot-1234567890",
"type": "overtime",
"severity": "high",
"title": "Overtime Alert",
"message": "Server Maria is approaching overtime at 38.5 hours",
"data": {
"employee_name": "Maria",
"current_hours": 38.5,
"threshold": 40
},
"created_at": "2026-02-19T14:25:00Z",
"acknowledged": false
}
],
"count": 1
}

Alert Types

TypeDescription
overtimeEmployees approaching overtime
inventoryItems needing to be 86'd
sales_targetBehind or ahead of daily target
pending_ordersLong-pending orders

Acknowledge Alert

Mark a proactive alert as acknowledged.

POST /api/v1/voice-ai/alerts/acknowledge

Request Body

The Go gateway sends only alert_id and extracts user_id from the JWT. The Python endpoint accepts an extended body:

{
"alert_id": "ot-1234567890",
"user_id": "manager-123",
"tenant_id": "demo-restaurant",
"location_id": "loc-456",
"session_id": "sess-789",
"alert_type": "overtime"
}
FieldTypeRequiredDescription
alert_idstringYesID of the alert to acknowledge
user_idstringYesUser acknowledging the alert
tenant_idstringYesTenant identifier
location_idstringYesLocation identifier
session_idstringNoVoice session ID (if from voice interaction)
alert_typestringNoType of alert being acknowledged

Response

{
"success": true,
"alert_id": "ot-1234567890",
"acknowledged_by": "manager-123",
"acknowledged_at": "2026-02-19T14:35:00Z"
}

Session State

Get Session State

Get the current state of a voice session, including pending alerts and last interaction.

GET /api/v1/voice-ai/session/{session_id}

Path Parameters

ParameterTypeDescription
session_idstringVoice session identifier

Query Parameters

ParameterTypeRequiredDescription
location_idstringYesLocation identifier

The tenant_id is extracted from the JWT token by the Go gateway.

Response

{
"session_id": "sess-789",
"tenant_id": "demo-restaurant",
"location_id": "loc-456",
"is_active": true,
"last_activity": "2026-02-19T14:30:00Z",
"pending_alerts": 2,
"last_query": "What were my sales yesterday?",
"last_response": "Yesterday's sales were $11,200 across 260 orders."
}

If the session does not exist or cannot be retrieved, the endpoint returns a default inactive state with is_active: false and pending_alerts: 0.


Command Queue

Internal Only

The command queue endpoints exist on the Python service but are not proxied through the Go API gateway. They are only accessible by calling the Python Analytics service directly (internal service-to-service communication). The Go gateway only exposes the core Voice AI endpoints listed above (health, status, query, command, alerts, alerts/acknowledge, session/{session_id}).

The command queue enables offline-first voice command execution. When a device is offline or connectivity is limited, commands are queued locally and synced to the server when connectivity is restored. Commands are prioritized and processed in order.

Queue Command

Queue a voice command for offline or deferred execution.

POST /api/voice-ai/queue/command

Request Body

{
"tenant_id": "demo-restaurant",
"user_id": "manager-123",
"location_id": "loc-456",
"session_id": "sess-789",
"command_text": "Turn on Happy Hour pricing",
"command_type": "enable_pricing",
"command_data": {
"pricing_mode": "happy_hour"
},
"confirmed": false,
"priority": "high",
"device_id": "device-abc-123"
}
FieldTypeRequiredDescription
tenant_idstringYesTenant identifier
user_idstringYesUser identifier
location_idstringYesLocation identifier
session_idstringYesSession identifier
command_textstringYesVoice command text
command_typestringYesCommand type (e.g., enable_pricing, add_special, send_message, 86_item)
command_dataobjectNoAdditional command parameters
confirmedbooleanNoWhether the command is pre-confirmed (default: false)
prioritystringNoPriority level: critical, high, normal, low (default: normal)
device_idstringNoDevice ID for sync tracking

Response

{
"command_id": "cmd-uuid-001",
"status": "pending",
"queued_at": "2026-02-19T14:30:00Z",
"priority": "high",
"estimated_execution": null
}

Get Queued Command Status

Get the current status of a specific queued command.

GET /api/voice-ai/queue/command/{command_id}

Path Parameters

ParameterTypeDescription
command_idstringQueued command identifier

Response

{
"id": "cmd-uuid-001",
"tenant_id": "demo-restaurant",
"user_id": "manager-123",
"location_id": "loc-456",
"command_text": "Turn on Happy Hour pricing",
"command_type": "enable_pricing",
"status": "pending",
"priority": "high",
"created_at": "2026-02-19T14:30:00Z",
"updated_at": "2026-02-19T14:30:00Z",
"attempt_count": 0,
"last_error": null,
"result": null
}
Status ValueDescription
pendingQueued and waiting for execution
executingCurrently being processed
completedSuccessfully executed
failedFailed after all retry attempts
cancelledCancelled by a user

Returns 404 if the command ID is not found.


Get Pending Commands

Get all pending commands in the queue for a tenant.

GET /api/voice-ai/queue/pending

Query Parameters

ParameterTypeRequiredDescription
tenant_idstringYesTenant identifier
limitintegerNoMaximum results (1-100, default: 50)

Response

[
{
"id": "cmd-uuid-001",
"tenant_id": "demo-restaurant",
"user_id": "manager-123",
"location_id": "loc-456",
"command_text": "Turn on Happy Hour pricing",
"command_type": "enable_pricing",
"status": "pending",
"priority": "high",
"created_at": "2026-02-19T14:30:00Z",
"updated_at": "2026-02-19T14:30:00Z",
"attempt_count": 0,
"last_error": null,
"result": null
}
]

Cancel Queued Command

Cancel a pending queued command. Only commands in pending status can be cancelled.

DELETE /api/voice-ai/queue/command/{command_id}

Path Parameters

ParameterTypeDescription
command_idstringQueued command identifier

Query Parameters

ParameterTypeRequiredDescription
user_idstringYesUser requesting the cancellation

Response

{
"success": true,
"command_id": "cmd-uuid-001",
"status": "cancelled"
}

If the command cannot be cancelled (e.g., already executing or completed), success is false and status reflects the current state.


Get Queue Statistics

Get statistics about the offline command queue.

GET /api/voice-ai/queue/stats

Query Parameters

ParameterTypeRequiredDescription
tenant_idstringNoFilter statistics by tenant (omit for global stats)

Response

{
"pending_count": 5,
"executing_count": 1,
"completed_count": 142,
"failed_count": 3,
"total_processed": 145,
"total_retries": 8,
"average_execution_time_ms": 320.5,
"oldest_pending_age_seconds": 45.2
}

Sync Commands from Device

Sync queued commands from an offline device. When a device reconnects after being offline, it sends all locally queued commands to the server for execution.

POST /api/voice-ai/queue/sync

Request Body

{
"tenant_id": "demo-restaurant",
"device_id": "device-abc-123",
"commands": [
{
"device_id": "local-cmd-1",
"user_id": "manager-123",
"location_id": "loc-456",
"command_text": "Turn on Happy Hour pricing",
"command_type": "enable_pricing"
}
]
}
FieldTypeRequiredDescription
tenant_idstringYesTenant identifier
device_idstringYesDevice identifier
commandsarrayYesArray of command objects to sync

Response

{
"synced_count": 1,
"id_mapping": {
"local-cmd-1": "cmd-uuid-001"
}
}

The id_mapping maps the device-local command IDs to the server-assigned IDs. If a command fails to sync, its value in the mapping will be prefixed with error:.


Trigger Queue Processing

Manually trigger processing of pending commands. This is typically called when connectivity is restored after a period of being offline.

POST /api/voice-ai/queue/process

Query Parameters

ParameterTypeRequiredDescription
tenant_idstringYesTenant identifier

Response

{
"success": true,
"processed_count": 5,
"timestamp": "2026-02-19T14:35:00Z"
}

Dead Letter Queue

Internal Only

Dead letter queue endpoints are part of the internal Python service and are not proxied through the Go API gateway.

Commands that fail after all retry attempts are moved to the dead letter queue (DLQ). These commands can be inspected and manually retried.

Get Dead Letter Queue

Get commands that have permanently failed.

GET /api/voice-ai/queue/dlq

Query Parameters

ParameterTypeRequiredDescription
tenant_idstringYesTenant identifier
limitintegerNoMaximum results (1-100, default: 50)

Response

[
{
"id": "cmd-uuid-003",
"tenant_id": "demo-restaurant",
"user_id": "manager-123",
"location_id": "loc-456",
"command_text": "Send the team a message about the VIP party",
"command_type": "send_message",
"status": "failed",
"priority": "normal",
"created_at": "2026-02-19T12:00:00Z",
"updated_at": "2026-02-19T12:05:00Z",
"attempt_count": 3,
"last_error": "Notification service unavailable",
"result": null
}
]

Retry Command from DLQ

Re-queue a failed command from the dead letter queue for another execution attempt. The command must be in failed status.

POST /api/voice-ai/queue/dlq/{command_id}/retry

Path Parameters

ParameterTypeDescription
command_idstringFailed command identifier

Query Parameters

ParameterTypeRequiredDescription
user_idstringYesUser requesting the retry

Response

{
"success": true,
"command_id": "cmd-uuid-003",
"status": "pending"
}

Returns 404 if the command is not found. Returns 400 if the command is not in failed status.


WebSocket Streaming

Internal Only

The WebSocket endpoint exists on the Python service but is not proxied through the Go API gateway. It is only accessible by connecting directly to the Python Analytics service.

WebSocket Connection

Connect for real-time voice interaction with Maximus.

ws://{python-service}/api/voice-ai/stream/{session_id}?tenant_id={tenant_id}&user_id={user_id}&location_id={location_id}

Client Messages

TypeDescription
text_querySend a text query for processing
commandExecute a voice command
acknowledge_alertAcknowledge a proactive alert
pingKeep-alive ping

Text Query

{
"type": "text_query",
"text": "What are today's sales?"
}

Command

{
"type": "command",
"command": "Turn on Happy Hour pricing",
"confirmed": true
}

Acknowledge Alert

{
"type": "acknowledge_alert",
"alert_id": "ot-1234567890",
"alert_type": "overtime"
}

Server Messages

TypeDescription
stateSession state update (sent on connection)
responseQuery response with analytics data
command_responseCommand execution result
alertProactive alert pushed to client
alert_acknowledgedConfirmation of alert acknowledgment
pongKeep-alive response
errorError message

State (on connection)

{
"type": "state",
"status": "connected",
"session_id": "sess-789",
"timestamp": "2026-02-19T14:30:00Z"
}

Response

{
"type": "response",
"response_text": "Today's sales are $12,450...",
"response_ssml": "<speak>...</speak>",
"intent": "query_sales",
"confidence": 0.95,
"analytics_result": {...},
"timestamp": "2026-02-19T14:30:05Z"
}

Alert (pushed periodically)

{
"type": "alert",
"alert": {
"id": "ot-1234567890",
"type": "overtime",
"severity": "high",
"title": "Overtime Alert",
"message": "Server Maria is approaching overtime at 38.5 hours",
"data": {...},
"created_at": "2026-02-19T14:25:00Z"
}
}

Proactive alerts are checked every 30 seconds and pushed to the connected client.


Error Responses

StatusCodeDescription
400validation_errorInvalid request body or missing required fields
401tenant_requiredJWT token missing or tenant context not available
403permission_deniedUser role does not have permission for the command
404not_foundSession or command not found
500service_errorInternal processing error
503service_unavailableVoice AI agent not loaded or Python service unreachable