Skip to main content
The search query is where personalization happens. Pass in a guest’s dietary restrictions, allergen exclusions, and nutritional preferences—we traverse our entire ingredient hierarchy to find dishes that are safe and satisfying for them. Results come back grouped by match quality: full matches, almost matches (with explanations), and non-matches. This gives you everything you need to build interfaces that help guests find exactly what they’re looking for—while being transparent about dishes that come close but don’t quite fit.
Chain and session context come from your headers (X-Session-ID). You don’t need to pass them in the query.

Query

query SmartMenuSearch(
  $preferences: PreferencesInput
  $searchTerm: String
  $category: String
  $pagination: PaginationInput
) {
  search(
    preferences: $preferences
    searchTerm: $searchTerm
    category: $category
    pagination: $pagination
  ) {
    matches {
      dish { ...DishFields }
      matchStatus
    }
    almostMatches {
      dish { ...DishFields }
      matchStatus
      matchReasons
    }
    notMatches {
      dish { ...DishFields }
      matchStatus
      matchReasons
    }
    counts {
      matches
      almostMatches
      notMatches
      total
    }
    pageInfo {
      hasNextPage
      hasPreviousPage
      startCursor
      endCursor
    }
  }
}

Parameters

All parameters are optional. Chain and session context come from your X-Session-ID header.
ParameterTypeDescription
preferencesPreferencesInputDietary filters (see below)
searchTermStringText search (dish name, description)
categoryStringFilter by menu category
paginationPaginationInputPagination controls

PreferencesInput

input PreferencesInput {
  diets: [DietType!]
  excludeAllergens: [AllergenType!]
  calorieRange: RangeInput
  nutrientRanges: NutrientRangesInput
}

input RangeInput {
  min: Int
  max: Int
}

input NutrientRangesInput {
  protein: RangeInput
  carbohydrates: RangeInput
  fatTotal: RangeInput
}

enum DietType {
  VEGAN
  VEGETARIAN
  PESCATARIAN
}

enum AllergenType {
  DAIRY
  EGG
  FISH
  SHELLFISH
  TREE_NUT
  PEANUT
  WHEAT
  SOY
  SESAME
}

PaginationInput

input PaginationInput {
  first: Int      # Number of results (default: 25, max: 100)
  after: String   # Cursor for next page
}

Response

Match Groups

Results are grouped into three categories:
GroupDescriptionUse Case
matchesFully meets all preferencesDisplay prominently
almostMatchesPartial match with exceptionsDisplay with warnings
notMatchesDoes not meet critical preferencesDisplay greyed out or hide

MatchStatus Enum

enum MatchStatus {
  MATCH           # Fully matches all preferences
  ALMOST_MATCH    # Partial match, has exceptions
  NOT_MATCH       # Does not meet preferences
}

Match Reasons

For almostMatches and notMatches, the matchReasons array explains why:
{
  "matchReasons": [
    "Contains Dairy",
    "Exceeds calorie limit (650 > 600)"
  ]
}

Example

query SmartMenuSearch {
  search(
    preferences: {
      diets: [VEGETARIAN]
      excludeAllergens: [PEANUT]
      calorieRange: { max: 600 }
    }
  ) {
    matches {
      dish {
        id
        name
        nutrition { calories, protein }
      }
      matchStatus
    }
    almostMatches {
      dish { id, name }
      matchReasons
    }
    counts {
      matches
      almostMatches
      notMatches
      total
    }
  }
}

Examples

Basic Search (No Filters)

query {
  search {
    matches {
      dish {
        id
        name
        nutrition { calories }
      }
    }
    counts { total }
  }
}
{
  "data": {
    "search": {
      "matches": [
        { "dish": { "id": "dish_001", "name": "Garden Salad", "nutrition": { "calories": 320 } } },
        { "dish": { "id": "dish_002", "name": "Mediterranean Bowl", "nutrition": { "calories": 450 } } }
      ],
      "counts": { "total": 24 }
    }
  }
}

Search with Dietary Preferences

query VegetarianSearch {
  search(
    preferences: {
      diets: [VEGETARIAN]
      excludeAllergens: [PEANUT, TREE_NUT]
      calorieRange: { max: 600 }
    }
  ) {
    matches {
      dish {
        id
        name
        category
        nutrition { calories, protein }
        diets { type }
      }
      matchStatus
    }
    almostMatches {
      dish { id, name }
      matchReasons
    }
    counts {
      matches
      almostMatches
      notMatches
    }
  }
}
{
  "data": {
    "search": {
      "matches": [
        {
          "dish": { "id": "dish_001", "name": "Garden Salad", "category": "Salads", "nutrition": { "calories": 320, "protein": 12 }, "diets": [{ "type": "VEGETARIAN" }] },
          "matchStatus": "MATCH"
        }
      ],
      "almostMatches": [
        { "dish": { "id": "dish_003", "name": "Caesar Salad" }, "matchReasons": ["Contains Dairy"] }
      ],
      "counts": { "matches": 8, "almostMatches": 4, "notMatches": 12 }
    }
  }
}

Text Search with Category Filter

query SearchSalads {
  search(
    searchTerm: "chicken"
    category: "Salads"
    pagination: { first: 10 }
  ) {
    matches {
      dish {
        id
        name
        description
      }
    }
    pageInfo {
      hasNextPage
      endCursor
    }
  }
}
{
  "data": {
    "search": {
      "matches": [
        { "dish": { "id": "dish_005", "name": "Grilled Chicken Salad", "description": "Mixed greens with grilled chicken breast" } },
        { "dish": { "id": "dish_006", "name": "Chicken Caesar Salad", "description": "Romaine, parmesan, croutons, grilled chicken" } }
      ],
      "pageInfo": { "hasNextPage": false, "endCursor": "cursor_abc123" }
    }
  }
}

Paginated Results

# First page
query Page1 {
  search(pagination: { first: 20 }) {
    matches { dish { id, name } }
    pageInfo {
      hasNextPage
      endCursor
    }
  }
}

# Next page (use endCursor from previous response)
query Page2 {
  search(pagination: { first: 20, after: "eyJpZCI6MjB9" }) {
    matches { dish { id, name } }
    pageInfo {
      hasNextPage
      endCursor
    }
  }
}

Full Example Response

{
  "data": {
    "search": {
      "matches": [
        {
          "dish": {
            "id": "dish_001",
            "partnerDishId": "olo_12345",
            "name": "Garden Salad",
            "category": "Salads",
            "imageUrl": "https://cdn.example.com/garden-salad.jpg",
            "nutrition": {
              "calories": 320,
              "protein": 12,
              "carbohydrates": 28,
              "fatTotal": 15
            },
            "allergens": [],
            "diets": [
              { "type": "VEGAN", "displayName": "Vegan" },
              { "type": "VEGETARIAN", "displayName": "Vegetarian" }
            ]
          },
          "matchStatus": "MATCH"
        },
        {
          "dish": {
            "id": "dish_004",
            "partnerDishId": "olo_12348",
            "name": "Mediterranean Bowl",
            "category": "Bowls",
            "imageUrl": "https://cdn.example.com/med-bowl.jpg",
            "nutrition": {
              "calories": 450,
              "protein": 18,
              "carbohydrates": 52,
              "fatTotal": 20
            },
            "allergens": [],
            "diets": [
              { "type": "VEGETARIAN", "displayName": "Vegetarian" }
            ]
          },
          "matchStatus": "MATCH"
        }
      ],
      "almostMatches": [
        {
          "dish": {
            "id": "dish_002",
            "partnerDishId": "olo_12346",
            "name": "Caesar Salad",
            "category": "Salads",
            "imageUrl": "https://cdn.example.com/caesar-salad.jpg",
            "nutrition": {
              "calories": 450,
              "protein": 18,
              "carbohydrates": 25,
              "fatTotal": 28
            },
            "allergens": [
              { "type": "DAIRY", "displayName": "Dairy" }
            ],
            "diets": [
              { "type": "VEGETARIAN", "displayName": "Vegetarian" }
            ]
          },
          "matchStatus": "ALMOST_MATCH",
          "matchReasons": ["Contains Dairy"]
        }
      ],
      "notMatches": [
        {
          "dish": {
            "id": "dish_003",
            "partnerDishId": "olo_12347",
            "name": "Grilled Chicken Salad",
            "category": "Salads"
          },
          "matchStatus": "NOT_MATCH",
          "matchReasons": ["Contains Meat"]
        }
      ],
      "counts": {
        "matches": 8,
        "almostMatches": 4,
        "notMatches": 12,
        "total": 24
      },
      "pageInfo": {
        "hasNextPage": true,
        "hasPreviousPage": false,
        "startCursor": "eyJpZCI6MX0=",
        "endCursor": "eyJpZCI6MjR9"
      }
    }
  }
}