LinqConnect School Lunches

Hi there - I was wondering if anyone has had any success tapping into the LinqConnect school lunch API to display menus, similar to the thread below:

https://community.home-assistant.io/t/rest-nutrislice-json-values

I realize this is pretty old, but in case anyone is looking for this later, I built a rest sensor yaml for this exact purpose. I wanted my kid to see the main menu options for the day. If it’s past 10am, it will show the menu options for the next day. It could obviously be extended to include sides as well, but I just needed something simple. Here is my rest.yaml file - to use, just create rest.yaml and include it in your configuration.yaml like

rest: !include rest.yaml

rest.yaml content - BE SURE TO REPLACE CONFIGURATION_VARIABLE VALUES FOR YOUR_BUILDING_ID, YOUR_DISTRICT_ID, AND YOUR_ALLERGEN_ID

- resource_template: >
    {#--- CONFIGURATION VARIABLES ---#}
    {% set building_id = 'YOUR_BUILDING_ID' %}
    {% set district_id = 'YOUR_DISTRICT_ID' %}
    {#--------------------------------#}
    {% set target_date = now() if now().hour < 10 else now() + timedelta(days=1) %}
    https://api.linqconnect.com/api/FamilyMenu?buildingId={{ building_id }}&districtId={{ district_id }}&startDate={{ target_date.strftime('%m-%d-%Y') }}&endDate={{ target_date.strftime('%m-%d-%Y') }}
  scan_interval: 10800 # 3 hours
  sensor:
    - name: "Lunch Date"
      value_template: >
        {% if value_json.FamilyMenuSessions | length > 0 and value_json.FamilyMenuSessions[0].MenuPlans | length > 0 %}
          {{ value_json.FamilyMenuSessions[0].MenuPlans[0].Days[0].Date }}
        {% else %}
          {% set date_to_display = now() if now().hour < 10 else now() + timedelta(days=1) %}
          {{ date_to_display.isoformat() }}
        {% endif %}
      device_class: timestamp

    - name: "Lunch Entree 1"
      value_template: >
        {% if value_json.FamilyMenuSessions | length > 0 and value_json.FamilyMenuSessions[0].MenuPlans | length > 0 %}
          {% set recipes = value_json.FamilyMenuSessions[0].MenuPlans[0].Days[0].MenuMeals[0].RecipeCategories[0].Recipes | default([]) %}
          {{ recipes[0].RecipeName if recipes | length > 0 else "No lunch today" }}
        {% else %}
          No lunch today
        {% endif %}

    - name: "Lunch Entree 1 Has Allergen"
      value_template: >
        {#--- CONFIGURATION VARIABLES ---#}
        {% set allergen_id_to_check = 'YOUR_ALLERGEN_ID' %}
        {#--------------------------------#}
        {% if value_json.FamilyMenuSessions | length > 0 and value_json.FamilyMenuSessions[0].MenuPlans | length > 0 %}
          {% set recipes = value_json.FamilyMenuSessions[0].MenuPlans[0].Days[0].MenuMeals[0].RecipeCategories[0].Recipes | default([]) %}
          {% if recipes | length > 0 and recipes[0].Allergens %}
            {{ allergen_id_to_check in recipes[0].Allergens }}
          {% else %}
            false
          {% endif %}
        {% else %}
          false
        {% endif %}

    - name: "Lunch Entree 2"
      value_template: >
        {% if value_json.FamilyMenuSessions | length > 0 and value_json.FamilyMenuSessions[0].MenuPlans | length > 0 %}
          {% set recipes = value_json.FamilyMenuSessions[0].MenuPlans[0].Days[0].MenuMeals[0].RecipeCategories[0].Recipes | default([]) %}
          {{ recipes[1].RecipeName if recipes | length > 1 else "No second lunch" }}
        {% else %}
          No second lunch
        {% endif %}

    - name: "Lunch Entree 2 Has Allergen"
      value_template: >
        {#--- CONFIGURATION VARIABLES ---#}
        {% set allergen_id_to_check = 'YOUR_ALLERGEN_ID' %}
        {#--------------------------------#}
        {% if value_json.FamilyMenuSessions | length > 0 and value_json.FamilyMenuSessions[0].MenuPlans | length > 0 %}
          {% set recipes = value_json.FamilyMenuSessions[0].MenuPlans[0].Days[0].MenuMeals[0].RecipeCategories[0].Recipes | default([]) %}
          {% if recipes | length > 1 and recipes[1].Allergens %}
            {{ allergen_id_to_check in recipes[1].Allergens }}
          {% else %}
            false
          {% endif %}
        {% else %}
          false
        {% endif %}

    - name: "Breakfast Entree 1"
      value_template: >
        {% if value_json.FamilyMenuSessions | length > 1 and value_json.FamilyMenuSessions[1].MenuPlans | length > 0 %}
          {% set recipes = value_json.FamilyMenuSessions[1].MenuPlans[0].Days[0].MenuMeals[0].RecipeCategories[0].Recipes | default([]) %}
          {{ recipes[0].RecipeName if recipes | length > 0 else "No breakfast today" }}
        {% else %}
          No breakfast today
        {% endif %}

    - name: "Breakfast Entree 1 Has Allergen"
      value_template: >
        {#--- CONFIGURATION VARIABLES ---#}
        {% set allergen_id_to_check = 'YOUR_ALLERGEN_ID' %}
        {#--------------------------------#}
        {% if value_json.FamilyMenuSessions | length > 1 and value_json.FamilyMenuSessions[1].MenuPlans | length > 0 %}
          {% set recipes = value_json.FamilyMenuSessions[1].MenuPlans[0].Days[0].MenuMeals[0].RecipeCategories[0].Recipes | default([]) %}
          {% if recipes | length > 0 and recipes[0].Allergens %}
            {{ allergen_id_to_check in recipes[0].Allergens }}
          {% else %}
            false
          {% endif %}
        {% else %}
          false
        {% endif %}

    - name: "Breakfast Entree 2"
      value_template: >
        {% if value_json.FamilyMenuSessions | length > 1 and value_json.FamilyMenuSessions[1].MenuPlans | length > 0 %}
          {% set recipes = value_json.FamilyMenuSessions[1].MenuPlans[0].Days[0].MenuMeals[0].RecipeCategories[0].Recipes | default([]) %}
          {{ recipes[1].RecipeName if recipes | length > 1 else "No second breakfast" }}
        {% else %}
          No second breakfast
        {% endif %}

    - name: "Breakfast Entree 2 Has Allergen"
      value_template: >
        {#--- CONFIGURATION VARIABLES ---#}
        {% set allergen_id_to_check = 'YOUR_ALLERGEN_ID' %}
        {#--------------------------------#}
        {% if value_json.FamilyMenuSessions | length > 1 and value_json.FamilyMenuSessions[1].MenuPlans | length > 0 %}
          {% set recipes = value_json.FamilyMenuSessions[1].MenuPlans[0].Days[0].MenuMeals[0].RecipeCategories[0].Recipes | default([]) %}
          {% if recipes | length > 1 and recipes[1].Allergens %}
            {{ allergen_id_to_check in recipes[1].Allergens }}
          {% else %}
            false
          {% endif %}
        {% else %}
          false
        {% endif %}

I also created a set of cards on the dashboard to display these:

- type: grid
        cards:
          - type: markdown
            content: >-
              ## <ha-icon icon=""></ha-icon> School Lunch for {{
              as_timestamp(states('sensor.lunch_date')) | timestamp_custom('%A,
              %B %-d') }}
          - type: tile
            entity: sensor.lunch_entree_1
            name: 'Lunch Choice #1'
            icon: mdi:help-circle-outline
            state_content: state
            vertical: false
            features_position: bottom
            card_mod:
              style: |
                ha-tile-icon {
                  --card-mod-icon: {% if is_state('sensor.lunch_entree_1_has_allergen', 'True') %}
                    mdi:cow
                  {% elif is_state('sensor.lunch_entree_1', 'No lunch today')%}
                    mdi:food-off-outline
                  {% else %}
                    mdi:cow-off
                  {% endif %};
                }
            grid_options:
              columns: 12
              rows: 1
          - type: tile
            entity: sensor.lunch_entree_2
            name: 'Lunch Choice #2'
            icon: mdi:help-circle-outline
            state_content: state
            vertical: false
            features_position: bottom
            card_mod:
              style: |
                ha-tile-icon {
                  --card-mod-icon: {% if is_state('sensor.lunch_entree_2_has_allergen', 'True') %}
                    mdi:cow
                  {% elif is_state('sensor.lunch_entree_2', 'No second lunch')%}
                    mdi:food-off-outline
                  {% else %}
                    mdi:cow-off
                  {% endif %};
                }
            grid_options:
              columns: 12
              rows: 1

Can you describe how you identified the {building id} and {allergen id}? I can find the {district id} through the schools website but unsure how to identify the others. Any help would be much appreciated. Thanks!

If you go to your school’s page on LinqConnect LINQ Connect - Making Schools Stronger, open the network tab and search for https://api.linqconnect.com/api/FamilyMenu?, and copy the buildingId

For allergenId list, you can search the network tab for 'allergy and look at the response tab for a mapping of allergen to Id.