Skip to main content
Many restaurants offer customizable dishes—build-your-own bowls, salads, pizzas, and more. When guests toggle ingredients on and off, they expect the nutrition panel and allergen warnings to update in real-time.
Dish customization interface showing ingredient toggles on the left and a nutrition panel on the right that updates as selections change
EveryBite provides two approaches for handling this:
ApproachBest ForTradeoffs
Calculate endpoint (recommended)Most integrationsSimple to implement, always accurate, requires API call per update
Client-side calculationOffline support, full controlYou implement the math, must handle updates when our data changes

Send the user’s selections to our API and receive calculated nutrition and allergens. This is the recommended approach because:
  • No math required — We handle the calculations
  • Always accurate — Allergen and nutrition logic updates automatically
  • Consistent — Same results across all platforms using your integration

Get Customization Options

First, fetch the available ingredients for a customizable dish:
query DishIngredients($dishId: ID!) {
  dish(id: $dishId) {
    id
    name
    isCustomizable
    addedIngredients {
      id
      name
      isIncluded        # Whether this ingredient is part of the default dish
      isKeyIngredient   # Whether this ingredient is part of the default selection when none are provided
      quantity
      unit
      amountGrams
      containsEgg
      containsFish
      containsMilk
      containsSesame
      containsShellfish
      containsWheat
      containsPeanut
      containsSoy
      containsTreeNut
    }
  }
}

Calculate Nutrition for Selections

As the user toggles ingredients on and off, call the calculate query:
query CalculateNutrition {
  calculate(
    dishId: "DISH_ID"
    selectedOptions: ["INGREDIENT_ID_1", "INGREDIENT_ID_2", "INGREDIENT_ID_3"]
  ) {
    nutrition {
      caloriesTotal
      caloriesFromFat
      fatTotal
      fatSaturated
      fatTrans
      cholesterol
      sodium
      dietaryFiber
      carbohydrates
      sugar
      protein
      vitaminA
      vitaminC
      calcium
      iron
    }
    allergens {
      id
      name
      description
      confidence
    }
  }
}

Input

calculate(
  dishId: ID!
  selectedOptions: [ID!]!
): CalculateResult!

Parameters

ParameterTypeRequiredDescription
dishIdIDYesThe customizable dish ID
selectedOptions[ID!]!YesArray of selected ingredient IDs for this dish. Can be empty.

Example

query CalculateNutrition {
  calculate(
    dishId: "dish_byo_001"
    selectedOptions: ["INGREDIENT_ID_1", "INGREDIENT_ID_2", "INGREDIENT_ID_3"]
  ) {
    nutrition {
      caloriesTotal
      protein
      carbohydrates
      fatTotal
    }
    allergens {
      id
      name
      description
      confidence
    }
  }
}

Performance Tips

The calculate endpoint is optimized for real-time use, but if you’re calling it on every toggle:
Debounce your requests. Wait 200-300ms after the user stops making changes before calling the API. This prevents unnecessary calls while they’re rapidly selecting options.
Example debounce pattern (JavaScript):
let debounceTimer;

function onSelectionChange(selectedOptions) {
  // Update UI optimistically if desired

  clearTimeout(debounceTimer);
  debounceTimer = setTimeout(() => {
    calculateCustomization(selectedOptions);
  }, 250);
}

Approach 2: Client-Side Calculation (Advanced)

For applications that need offline support or want full control over the calculation, you can request complete nutrition data for each customization option and calculate totals yourself.
With this approach, you’re responsible for:
  • Implementing nutrition summation logic
  • Handling allergen aggregation (including cross-contamination rules)
  • Determining dietary flag qualification
  • Updating your logic when our data model changes

Request Full Option Data

query DishWithFullCustomizations($dishId: ID!) {
  dish(id: $dishId) {
    id
    name
    baseNutrition {
      calories
      fatTotal
      fatSaturated
      fatTrans
      cholesterol
      sodium
      carbohydrates
      dietaryFiber
      sugar
      protein
    }
    baseAllergens {
      type
      displayName
      source
    }
    customizationGroups {
      id
      name
      selectionType
      options {
        id
        name
        isDefault
        nutrition {
          calories
          fatTotal
          fatSaturated
          fatTrans
          cholesterol
          sodium
          carbohydrates
          dietaryFiber
          sugar
          protein
        }
        allergens {
          type
          displayName
        }
        dietaryTags
      }
    }
  }
}

Calculation Rules

If you implement client-side calculation, follow these rules:

Nutrition

Sum the values from all selected options plus the base nutrition (if any):
function calculateNutrition(baseNutrition, selectedOptions) {
  const totals = { ...baseNutrition };

  for (const option of selectedOptions) {
    for (const [key, value] of Object.entries(option.nutrition)) {
      totals[key] = (totals[key] || 0) + (value || 0);
    }
  }

  return totals;
}

Allergens

Combine allergens from all selected options, deduplicating by type:
function aggregateAllergens(baseAllergens, selectedOptions) {
  const allergenMap = new Map();

  // Add base allergens
  for (const allergen of baseAllergens) {
    allergenMap.set(allergen.type, allergen);
  }

  // Add option allergens
  for (const option of selectedOptions) {
    for (const allergen of option.allergens) {
      if (!allergenMap.has(allergen.type)) {
        allergenMap.set(allergen.type, {
          ...allergen,
          source: option.name
        });
      }
    }
  }

  return Array.from(allergenMap.values());
}

Dietary Flags

A dish qualifies for a dietary flag only if all selected options qualify:
function checkDietaryFlag(flag, selectedOptions) {
  return selectedOptions.every(option =>
    option.dietaryTags.includes(flag)
  );
}
Dietary flag logic can be more complex than simple intersection. For example, a dish might be “vegan” only if it contains no animal products AND meets certain preparation requirements. The calculate endpoint handles these nuances automatically.

Which Approach Should I Use?

Use Calculate Endpoint

  • Building a web or mobile app with connectivity
  • Want simplest integration path
  • Need guaranteed accuracy for allergen/dietary info
  • Don’t want to maintain calculation logic

Use Client-Side Calculation

  • Building an offline-first application
  • Need instant updates without any network latency
  • Have specific UX requirements that need full control
  • Willing to maintain calculation logic
Most developers choose the calculate endpoint. It’s simpler to implement and ensures your users always see accurate information, even as our nutrition data and dietary classification rules evolve.

Response Types

Ingredient

type Ingredient {
  id: ID!
  name: String!
  brand: String
  description: String
  supplier: String
  caloriesTotalPer100g: String
  caloriesFromFatPer100g: String
  fatTotalPer100g: String
  fatSaturatedPer100g: String
  fatTransPer100g: String
  cholesterolPer100g: String
  carbohydratesPer100g: String
  sugarPer100g: String
  proteinPer100g: String
  vitaminAPer100g: String
  vitaminCPer100g: String
  calciumPer100g: String
  ironPer100g: String
  containsEgg: Boolean
  containsFish: Boolean
  containsMilk: Boolean
  containsSesame: Boolean
  containsShellfish: Boolean
  containsWheat: Boolean
  containsPeanut: Boolean
  containsSoy: Boolean
  containsTreeNut: Boolean
  isIncluded: Boolean!
  isKeyIngredient: Boolean!
  quantity: String!
  unit: String!
  amountGrams: Float!
}

CalculatedNutrition

type CalculatedNutrition {
  caloriesTotal: Float!
  caloriesFromFat: Float!
  fatTotal: Float!
  fatSaturated: Float!
  fatTrans: Float!
  cholesterol: Float!
  sodium: Float!
  dietaryFiber: Float!
  carbohydrates: Float!
  sugar: Float!
  protein: Float!
  vitaminA: Float!
  vitaminC: Float!
  calcium: Float!
  iron: Float!
}

CalculateResult

type CalculateResult {
  nutrition: CalculatedNutrition!
  allergens: [Allergen!]!
}