The Recommendations API endpoints exist on the Python Analytics service but there is no Go API gateway proxy configured for /recommendations/*. These endpoints are only accessible through internal service-to-service communication directly to the Python service. They cannot be called from external clients through the public API gateway (api.olympuscloud.ai).
Recommendations API
AI-powered menu item recommendations using locally-trained ML models with optional AI Gateway enhancement for natural language explanations.
Overview
| Attribute | Value |
|---|---|
| Python Service Path | /api/recommendations |
| Public API Gateway | Not proxied - no /v1/recommendations/* route exists |
| Authentication | Tenant auth (internal service calls) |
| Feature Gate | analytics.ml gating policy required |
Recommendation Types
| Type | Description |
|---|---|
upsell | Size upgrades, premium options |
cross_sell | Complementary items |
substitute | Alternative items |
popular | Trending and best sellers |
personalized | Based on customer history |
Recommendation Contexts
| Context | Description |
|---|---|
order_start | Beginning of order (suggest popular items) |
mid_order | During ordering (cross-sell, upsell) |
order_complete | After main items selected (desserts, drinks) |
post_entree | After entree selection (sides, add-ons) |
Get Order Recommendations
Get AI-powered recommendations for an order based on cart contents, time of day, party size, and customer history.
POST /api/recommendations/order
Request Body
{
"tenant_id": "restaurant-1",
"location_id": "loc_123",
"order_id": "ord_456",
"items_in_cart": ["entree-001", "drink-002"],
"party_size": 4,
"context": "mid_order",
"customer_id": "cust_789",
"max_recommendations": 5
}
| Field | Type | Required | Description |
|---|---|---|---|
tenant_id | string | Yes | Tenant identifier |
location_id | string | Yes | Location identifier |
order_id | string | No | Existing order ID |
items_in_cart | array | No | Item IDs currently in cart (default: empty) |
party_size | integer | No | Party size 1-20 (default: 2) |
context | string | No | Recommendation context: order_start, mid_order, order_complete, post_entree (default: order_start) |
customer_id | string | No | Customer ID for personalization |
max_recommendations | integer | No | Max results 1-20 (default: 5) |
Response
{
"order_id": "ord_456",
"recommendations": [
{
"item_id": "side-003",
"item_name": "Loaded Fries",
"category": "sides",
"price": 6.99,
"score": 0.92,
"recommendation_type": "cross_sell",
"reason": "Frequently ordered with your entree selection",
"factors": {
"co_occurrence": 0.85,
"time_relevance": 0.90,
"margin": 0.75
},
"margin_score": 0.75,
"confidence": 0.92
}
],
"context_used": {
"party_size": 4,
"time_of_day": "dinner",
"items_in_cart": 2
},
"model_version": "v2.3",
"latency_ms": 45,
"experiment_id": "exp_001",
"experiment_variant": "variant_b"
}
Get Recommendations for Existing Order
Fetch current order items from the commerce service and generate recommendations.
GET /api/recommendations/order/{order_id}
Path Parameters
| Parameter | Type | Description |
|---|---|---|
order_id | string | Existing order identifier |
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
tenant_id | string | Yes | Tenant identifier |
location_id | string | Yes | Location identifier |
max_recommendations | integer | No | Max results 1-20 (default: 5) |
Response
Same format as POST /api/recommendations/order.
Returns 404 if the order is not found.
Get Customer Recommendations
Get personalized recommendations based on customer order history, including favorites, new items to try, and history-based suggestions.
POST /api/recommendations/customer
Request Body
{
"tenant_id": "restaurant-1",
"location_id": "loc_123",
"customer_id": "cust_456",
"include_favorites": true,
"include_new_items": true,
"max_recommendations": 10
}
| Field | Type | Required | Description |
|---|---|---|---|
tenant_id | string | Yes | Tenant identifier |
location_id | string | Yes | Location identifier |
customer_id | string | Yes | Customer identifier |
include_favorites | boolean | No | Include favorite items (default: true) |
include_new_items | boolean | No | Include new items to try (default: true) |
max_recommendations | integer | No | Max results 1-50 (default: 10) |
Response
{
"customer_id": "cust_456",
"favorites": [
{
"item_id": "entree-001",
"item_name": "Ribeye Steak",
"category": "entrees",
"price": 34.99,
"score": 0.95,
"recommendation_type": "personalized",
"reason": "One of your favorites",
"confidence": 0.95
}
],
"try_something_new": [
{
"item_id": "entree-005",
"item_name": "Pan-Seared Salmon",
"category": "entrees",
"price": 28.99,
"score": 0.82,
"recommendation_type": "personalized",
"reason": "Try something new",
"confidence": 0.82
}
],
"based_on_history": [
{
"item_id": "side-002",
"item_name": "Garlic Mashed Potatoes",
"category": "sides",
"price": 5.99,
"score": 0.78,
"recommendation_type": "cross_sell",
"reason": "Pairs well with items you've ordered before",
"confidence": 0.78
}
],
"visit_count": 12,
"average_ticket": 42.50
}
Record Feedback
Record whether a recommendation was accepted or rejected, used for continuous model improvement.
POST /api/recommendations/feedback
Request Body
{
"tenant_id": "restaurant-1",
"location_id": "loc_123",
"order_id": "ord_789",
"item_id": "side-003",
"recommendation_type": "cross_sell",
"was_accepted": true,
"position": 0,
"experiment_id": "exp_001",
"experiment_variant": "variant_b"
}
| Field | Type | Required | Description |
|---|---|---|---|
tenant_id | string | Yes | Tenant identifier |
location_id | string | Yes | Location identifier |
order_id | string | Yes | Order identifier |
item_id | string | Yes | Recommended item ID |
recommendation_type | string | Yes | Type: upsell, cross_sell, substitute, popular, personalized |
was_accepted | boolean | Yes | Whether the recommendation was accepted |
position | integer | Yes | Position in the recommendation list (0-indexed) |
experiment_id | string | No | A/B test experiment ID |
experiment_variant | string | No | A/B test variant |
Response
{
"success": true,
"item_id": "side-003",
"was_accepted": true
}
Performance Metrics
Get recommendation performance analytics including acceptance rates, revenue impact, and improvement suggestions.
GET /api/recommendations/performance
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
tenant_id | string | Yes | Tenant identifier |
location_id | string | Yes | Location identifier |
days | integer | No | Analysis period in days, 1-365 (default: 30) |
Response
{
"period_days": 30,
"total_recommendations": 5420,
"overall_acceptance_rate": 0.23,
"recommended_revenue": 15680.50,
"by_type": {
"upsell": {
"total": 1800,
"accepted": 180,
"acceptance_rate": 0.10,
"revenue": 2700.00
},
"cross_sell": {
"total": 2200,
"accepted": 660,
"acceptance_rate": 0.30,
"revenue": 8580.00
}
},
"trending_items": [
{
"type": "cross_sell",
"acceptance_rate": 0.30,
"total": 2200
}
],
"improvement_suggestions": [
"Upsell acceptance is low. Try featuring higher-value appetizers and sides."
]
}
A/B Test Experiments
List Experiments
List A/B test experiments for the recommendation engine.
GET /api/recommendations/experiments
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
tenant_id | string | Yes | Tenant identifier |
location_id | string | No | Filter by location |
status | string | No | Filter by status: running, completed |
Response
[
{
"experiment_id": "exp_001",
"experiment_name": "Cross-sell positioning test",
"start_date": "2026-02-01T00:00:00Z",
"status": "running",
"variants": [
{"name": "control", "traffic_percent": 50},
{"name": "variant_b", "traffic_percent": 50}
],
"winner": null,
"statistical_significance": null
}
]
Returns an empty array if no experiments are found or if the experiments service is unavailable.
Assign Experiment Variant
Assign a session to an experiment variant for consistent experience.
POST /api/recommendations/experiments/{experiment_id}/assign
Path Parameters
| Parameter | Type | Description |
|---|---|---|
experiment_id | string | Experiment identifier |
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
tenant_id | string | Yes | Tenant identifier |
session_id | string | Yes | Session or order ID for assignment |
Response
{
"experiment_id": "exp_001",
"session_id": "sess_456",
"variant": "variant_b",
"config": {
"recommendation_position": "top",
"max_shown": 3
}
}
On error, defaults to the "control" variant with empty config.
Error Responses
| Status | Code | Description |
|---|---|---|
| 404 | Not Found | Order not found (for GET /order/{order_id}) |
| 500 | Internal Error | Recommendation engine or feature store failure |
Related Documentation
- Menu API - Menu management
- AI Insights - AI analytics
- Orders API - Order processing