Skip to main content
Not Accessible via Public API Gateway

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

AttributeValue
Python Service Path/api/recommendations
Public API GatewayNot proxied - no /v1/recommendations/* route exists
AuthenticationTenant auth (internal service calls)
Feature Gateanalytics.ml gating policy required

Recommendation Types

TypeDescription
upsellSize upgrades, premium options
cross_sellComplementary items
substituteAlternative items
popularTrending and best sellers
personalizedBased on customer history

Recommendation Contexts

ContextDescription
order_startBeginning of order (suggest popular items)
mid_orderDuring ordering (cross-sell, upsell)
order_completeAfter main items selected (desserts, drinks)
post_entreeAfter 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
}
FieldTypeRequiredDescription
tenant_idstringYesTenant identifier
location_idstringYesLocation identifier
order_idstringNoExisting order ID
items_in_cartarrayNoItem IDs currently in cart (default: empty)
party_sizeintegerNoParty size 1-20 (default: 2)
contextstringNoRecommendation context: order_start, mid_order, order_complete, post_entree (default: order_start)
customer_idstringNoCustomer ID for personalization
max_recommendationsintegerNoMax 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

ParameterTypeDescription
order_idstringExisting order identifier

Query Parameters

ParameterTypeRequiredDescription
tenant_idstringYesTenant identifier
location_idstringYesLocation identifier
max_recommendationsintegerNoMax 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
}
FieldTypeRequiredDescription
tenant_idstringYesTenant identifier
location_idstringYesLocation identifier
customer_idstringYesCustomer identifier
include_favoritesbooleanNoInclude favorite items (default: true)
include_new_itemsbooleanNoInclude new items to try (default: true)
max_recommendationsintegerNoMax 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"
}
FieldTypeRequiredDescription
tenant_idstringYesTenant identifier
location_idstringYesLocation identifier
order_idstringYesOrder identifier
item_idstringYesRecommended item ID
recommendation_typestringYesType: upsell, cross_sell, substitute, popular, personalized
was_acceptedbooleanYesWhether the recommendation was accepted
positionintegerYesPosition in the recommendation list (0-indexed)
experiment_idstringNoA/B test experiment ID
experiment_variantstringNoA/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

ParameterTypeRequiredDescription
tenant_idstringYesTenant identifier
location_idstringYesLocation identifier
daysintegerNoAnalysis 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

ParameterTypeRequiredDescription
tenant_idstringYesTenant identifier
location_idstringNoFilter by location
statusstringNoFilter 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

ParameterTypeDescription
experiment_idstringExperiment identifier

Query Parameters

ParameterTypeRequiredDescription
tenant_idstringYesTenant identifier
session_idstringYesSession 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

StatusCodeDescription
404Not FoundOrder not found (for GET /order/{order_id})
500Internal ErrorRecommendation engine or feature store failure