bburwell  
                (Bob B)
               
                 
              
                  
                    February 10, 2025, 11:08pm
                   
                   
              789 
               
             
            
              So I was curious how Tennis works with TeamTracker because they are individuals and not teams.  It would be cool if you could just have teamtracker do events instead of individuals or some other method to simplify the code but I am not sure how that would work.
Anyway for fun I looked at https://site.web.api.espn.com/apis/site/v2/sports/tennis/atp/scoreboard  to see what players were either in pre/in/post mode which is one of the items TT keys off of.  I saw a couple and put them into my tennis.yaml sensor file.  Here are the 4 I grabbed (I am not doing all 150 and would love to have someone post it if they get an itch to create them and I would put them on my github site).
- platform: teamtracker
  league_id: "ATP"
  team_id: "Jannik Sinner"
  name: "Jannik Sinner"
  
- platform: teamtracker
  league_id: "ATP"
  team_id: "Luca Nardi"
  name: "Luca Nardi"  
- platform: teamtracker
  league_id: "ATP"
  team_id: "Benjamin Bonzi"
  name: "Benjamin Bonzi" 
- platform: teamtracker
  league_id: "ATP"
  team_id: "Manuel Guinard"
  name: "Manuel Guinard"  
  
 
I changed up my Sandbox - Tennis dashboard to use post the TT cards if available.  I like to keep things compact so here is what it looks like now. 
Here is what the TT card tabs look like. 
Here is the Sandbox dashboard code for any interested:
decluttering_templates:
  bpl_settings:
    card:
      type: custom:flex-table-card
      title: '[[title]]'
      css:
        table+: 'padding: 0px; width: 400px;'
        tbody tr td:first-child: 'width: 1%;'
        tbody tr td:nth-child(2): 'width: 1%;'
        tbody tr td:nth-child(3): 'width: 20%;'
        tbody tr:hover: 'background-color: green!important; color:white!important;'
      card_mod:
        style:
          .: |
            ha-card {
              overflow: auto;
              }
          $: |
            .card-header {
               padding-top: 6px!important;
               padding-bottom: 4px!important;
               font-size: 14px!important;
               line-height: 14px!important;
               font-weight: bold!important;
             }
      entities:
        include: '[[entity]]'
      sort_by: ranks
      columns:
        - name: Rank
          data: ranks
          modify: x.current
        - name: Previous
          data: ranks
          modify: x.previous
        - name: Athlete
          data: ranks
          modify: >-
            '<div
            style="display:flex;justify-content:space-between;align-items:center;">'
            + '<div style="display:flex;align-items:center;">' + (typeof
            x.athlete.headshot !== 'undefined' ? '<img src="' +
            x.athlete.headshot + '"
            style="width:40px;height:40px;margin-right:5px;">' : '') +
            x.athlete.displayName + '</div>' + '<div style="background-image:
            url(' + (typeof x.athlete.flag !== 'undefined' ? x.athlete.flag :
            '') + '); background-size: cover; background-repeat: no-repeat;
            height: 30px; width: 50px; display: flex; align-items: center;
            justify-content: center;">' + (typeof x.athlete.flag !== 'undefined'
            ? x.athlete.flagAltText : '') + '</div>' + '</div>'
        - name: Pts
          data: ranks
          modify: x.points
  game_stats:
    card:
      type: custom:auto-entities
      unique: true
      show_empty: false
      card:
        type: custom:layout-card
        layout_type: masonry
        width: 200px
        max-columns: 5
      card_param: cards
      filter:
        template: |
          {%- for team in integration_entities("teamtracker") -%}
            {%- if state_attr(team, "league") == "[[sport]]" -%}
               {%- if states(team) == "[[status]]" -%}
                    {{{"type": "custom:teamtracker-card",
                      "entity": team, 
                      "home_side": "right"}}},
              {%- endif -%} 
            {%- endif -%}
          {%- endfor -%}
        exclude:
          - entity_id: '*team_tracker*'
      sort:
        method: attribute
        attribute: date
views:
  - theme: Backend-selected
    title: Sports
    type: panel
    icon: mdi:strategy
    badges: []
    cards:
      - type: custom:mod-card
        card_mod:
          style:
            tabbed-card $: |
              mwc-tab {
                background: black;
                color: silver;
                border-color: var(--ha-card-border-color, var(--divider-color, #e0e0e0));
                border-width: 2px;
                border-style: solid;
                overflow: hidden;
                width: 20%;
              }
              mwc-tab[active] {
                background: white !important;
                color: black !important;
              }
        card:
          type: custom:tabbed-card
          styles:
            '--mdc-theme-primary': black
            '--mdc-tab-text-label-color-default': silver
            '--mdc-typography-button-font-size': 12px
          tabs:
            - attributes:
                label: Tennis
                icon: mdi:tennis
              card:
                type: custom:mod-card
                card_mod:
                  style:
                    tabbed-card $: |
                      mwc-tab {
                        background: black;
                        border-color: silver;
                        border-width: 2px;
                        border-top-left-radius: 20px;
                        border-top-right-radius: 20px;
                        border-style: solid;
                        overflow: hidden;
                        width: 15%;
                      }
                      mwc-tab[active] {
                        background: white !important;
                        color: black !important
                      }
                card:
                  type: custom:tabbed-card
                  card_mod:
                    style:
                      tabbed-card $: |
                        mwc-tab {
                          background: black;
                          border-color: silver;
                          border-width: 2px;
                          border-top-left-radius: 20px;
                          border-top-right-radius: 20px;
                          border-style: solid;
                          overflow: hidden;
                          width: 10%;
                        }
                        mwc-tab[active] {
                          background: white !important;
                          color: black !important
                        }
                  tabs:
                    - attributes:
                        label: Men's Tennis
                        icon: mdi:account-group
                      card:
                        type: custom:mod-card
                        card_mod:
                          style:
                            tabbed-card $: |
                              mwc-tab {
                               background: black;
                               border-color: silver;
                               border-width: 2px;
                               border-top-left-radius: 20px;
                               border-top-right-radius: 20px;
                               border-style: solid;
                               overflow: hidden;
                               width: 15%;
                              }
                              mwc-tab[active] {
                                background: white !important;
                                color: black !important
                              }
                        card:
                          type: custom:tabbed-card
                          styles:
                            '--mdc-theme-primary': blue
                            '--mdc-tab-text-label-color-default': white
                            '--mdc-typography-button-font-size': 12px
                          tabs:
                            - attributes:
                                label: Standings
                                icon: mdi:tennis-ball-outline
                              card:
                                type: custom:stack-in-card
                                mode: vertical
                                cards:
                                  - type: markdown
                                    content: |
                                      <h1>ATP Rankings</h1>
                                  - type: custom:decluttering-card
                                    template: bpl_settings
                                    variables:
                                      - title: ATP
                                      - entity: sensor.tennis_atp_ranking
                            - attributes:
                                label: Pre, Post, Live
                              card:
                                type: horizontal-stack
                                cards:
                                  - type: vertical-stack
                                    cards:
                                      - type: markdown
                                        content: |
                                          <h1>ATP Games Pre</h1>
                                      - type: custom:decluttering-card
                                        template: game_stats
                                        variables:
                                          - sport: ATP
                                          - status: PRE
                                      - type: markdown
                                        content: |
                                          <h1>ATP Games Live</h1>
                                      - type: custom:decluttering-card
                                        template: game_stats
                                        variables:
                                          - sport: ATP
                                          - status: IN
                                      - type: markdown
                                        content: |
                                          <h1>ATP Games Completed</h1>
                                      - type: custom:decluttering-card
                                        template: game_stats
                                        variables:
                                          - sport: ATP
                                          - status: POST
                    - attributes:
                        label: Women's Tennis
                        icon: mdi:account-group
                      card:
                        type: horizontal-stack
                        cards:
                          - type: vertical-stack
                            cards:
                              - type: markdown
                                content: |
                                  <h1>WTA Rankings</h1>
                              - type: custom:decluttering-card
                                template: bpl_settings
                                variables:
                                  - title: WTA
                                  - entity: sensor.tennis_wta_ranking
 
More for fun than anything else
             
            
               
               
               
            
           
          
            
            
              For tennis tracking, Iāve gotten rankings, upcoming tournament schedule and scores all pulled together for ATP and WTA. Here are some screenshots:
I have created player specific teamtracker sensors for those that I want to follow ā since there isnāt a āteamā type list, players coming in/out of the top 25 or so will always be a moving target ā I donāt have a solution for that.
Outside of the teamtracker sensors for individual players, I created four sensors to pull in the rankings and tournaments, as follows. The rankings only update once per week (Monday mornings) and Iāve got another automation to update them at that time.
##
## ATP Rankings
## 
- platform: rest
  scan_interval: 604800
  name: Tennis ATP Ranking
  unique_id: sensor.tennis_atp_ranking
  resource: https://site.web.api.espn.com/apis/site/v2/sports/tennis/atp/rankings?region=us&lang=en
  value_template: "{{ now() }}"
  json_attributes_path: "$.['rankings'][0]"
  json_attributes:
    - ranks
##
## WTA Rankings
## 
- platform: rest
  scan_interval: 604800
  name: Tennis WTA Ranking
  unique_id: sensor.tennis_wta_ranking
  resource: https://site.web.api.espn.com/apis/site/v2/sports/tennis/wta/rankings?region=us&lang=en
  value_template: "{{ now() }}"
  json_attributes_path: "$.['rankings'][0]"
  json_attributes:
    - ranks
##
## WTA Schedule
##
- platform: rest
  scan_interval: 86400
  name: Tennis WTA Schedule
  unique_id: sensor.tennis_wta_schedule
  resource_template: >-
    https://site.web.api.espn.com/apis/site/v2/sports/tennis/wta/scoreboard?region=us&lang=en&dates={{ now().strftime('%Y%m%d') }}-{{ now().replace(month=12, day=31).strftime('%Y%m%d') }}
  value_template: "{{ value_json.events | default([]) | count }}"
  json_attributes:
    - events
##
## ATP Schedule
##
- platform: rest
  scan_interval: 86400
  name: Tennis ATP Schedule
  unique_id: sensor.tennis_atp_schedule
  resource_template: >-
    https://site.web.api.espn.com/apis/site/v2/sports/tennis/atp/scoreboard?region=us&lang=en&dates={{ now().strftime('%Y%m%d') }}-{{ now().replace(month=12, day=31).strftime('%Y%m%d') }}
  value_template: "{{ value_json.events | default([]) | count }}"
  json_attributes:
    - events
 
For the schedule sensors, I added the dates variable to the api url and it brings back each tournament from today through the end of the year.
Here is the yaml:
decluttering_templates:
  ranking_settings:
    card:
      type: custom:flex-table-card
      title: '[[title]]'
      css:
        table+: >-
          padding: 0px; width: 100%; max-width: 1600px; display: block;
          overflow-x: auto;
        tbody tr td:first-child: 'width: 0.1%; text-align: center;'
        tbody tr td:nth-child(2): 'width: 0.1%; text-align: center;'
        tbody tr td:nth-child(3): 'width: auto; text-align: center;'
        tbody tr td:nth-child(n+4): 'width: auto;'
        tbody tr:hover: 'background-color: green!important; color: white!important;'
        '@media (max-width: 600px)': |
          tbody tr td {
            font-size: 12px;
            padding: 2px;
          }
          tbody tr td img {
            width: 15px;
            height: 15px;
          }
      card_mod:
        style:
          .: |
            ha-card {
              overflow: auto;
              }
          $: |
            .card-header {
               padding-top: 6px!important;
               padding-bottom: 4px!important;
               font-size: 14px!important;
               line-height: 14px!important;
               font-weight: bold!important;
             }
      entities:
        include: '[[entity]]'
      sort_by: ranks
      columns:
        - name: Rk
          data: ranks
          modify: x.current
        - name: +-
          data: ranks
          modify: >-
            '<div style="color:' + (x.trend > 0 ? 'green' : x.trend < 0 ? 'red'
            : 'white') + ';">' + x.trend + '</div>'
        - name: Flag
          data: ranks
          modify: >-
            '<div style="white-space: nowrap; display: flex; align-items:
            center;">' + (typeof x.athlete.flag !== 'undefined' ? '<img src="' +
            x.athlete.flag + '"
            style="width:20px;height:20px;margin-right:5px;">' : '') + '<span>'
            + x.athlete.citizenshipCountry + '</span></div>'
        - name: Name
          data: ranks
          modify: >-
            '<div style="white-space: nowrap; overflow: auto; max-width: 150px;
            display: inline-block;">' + (typeof x.athlete.headshot !==
            'undefined' ? '<img src="' + x.athlete.headshot + '"
            style="width:20px;height:20px;margin-right:5px;">' : '') +
            (x.athlete.links && x.athlete.links.find(l =>
            l.rel.includes("playercard")) ? '<a href="' + x.athlete.links.find(l
            => l.rel.includes("playercard")).href + '" target="_blank"
            style="text-decoration: none; color: inherit;">' +
            x.athlete.displayName + '</a>' : x.athlete.displayName) + '</div>'
        - name: Pts
          data: ranks
          modify: x.points
  schedule_settings:
    card:
      type: custom:flex-table-card
      title: '[[title]]'
      css:
        table+: >-
          padding: 10px; width: 100%; max-width: 1600px; display: block;
          overflow-x: auto;
        tbody tr td:first-child: 'width: 20%; text-align: left;'
        tbody tr td:nth-child(2): 'width: auto; text-align: left;'
        tbody tr td:nth-child(3): 'width: auto; text-align: left;'
        tbody tr:hover: 'background-color: green!important; color: white!important;'
        '@media (max-width: 600px)': |
          tbody tr td {
            font-size: 12px;
            padding: 2px;
          }
          tbody tr td img {
            width: 15px;
            height: 15px;
          }
      card_mod:
        style:
          .: |
            ha-card {
              overflow: auto;
            }
          $: |
            .card-header {
               padding-top: 6px!important;
               padding-bottom: 4px!important;
               font-size: 14px!important;
               line-height: 14px!important;
               font-weight: bold!important;
             }
      entities:
        include: '[[entity]]'
      columns:
        - name: Dates
          data: events
          modify: >-
            new Date(x.date).toLocaleDateString('en-US', { month: 'short', day:
            'numeric' })  + ' - ' + new
            Date(x.endDate).toLocaleDateString('en-US', { month: 'short', day:
            'numeric' })
        - name: Tournament
          data: events
          modify: >-
            '<div><a href="' + (x.links && x.links.length > 0 ? x.links[0].href
            : '#')  + '" target="_blank" style="text-decoration: none; color:
            inherit;">' + x.name + '</a><br> <span style="font-size: smaller;
            color: gray;">' + (x.venue ? x.venue.displayName : '') +
            '</span></div>'
        - name: Previous Winner
          data: events
          modify: >-
            (x.previousWinners && x.previousWinners.find(w => w.type.slug ===
            '[[type]]')) ?   (x.previousWinners.find(w => w.type.slug ===
            '[[type]]').headshot ?   '<img src="' + x.previousWinners.find(w =>
            w.type.slug === '[[type]]').headshot +   '" style="width: 20px;
            height: 20px; margin-right: 5px; vertical-align: middle;">' : '')
            +   '<a href="' + x.previousWinners.find(w => w.type.slug ===
            '[[type]]').links[0].href +   '" target="_blank"
            style="text-decoration: none; color: inherit;">' +  
            x.previousWinners.find(w => w.type.slug === '[[type]]').displayName
            + '</a>' : ''
  game_stats:
    card:
      type: custom:auto-entities
      unique: true
      show_empty: false
      card:
        type: custom:layout-card
        layout_type: masonry
        width: 200px
        max-columns: 5
      card_param: cards
      filter:
        template: |
          {%- for team in integration_entities("teamtracker") -%}
            {%- if state_attr(team, "league") == "[[sport]]" -%}
               {%- if states(team) == "[[status]]" -%}
                    {{{"type": "custom:teamtracker-card",
                      "entity": team, 
                      "home_side": "right",
                      "outline": true,
                      "outline_color": 'white'}}},
              {%- endif -%} 
            {%- endif -%}
          {%- endfor -%}
      sort:
        method: attribute
        attribute: date
views:
  - title: Tennis
    icon: mdi:tennis
    type: panel
    badges: []
    cards:
      - type: custom:mod-card
        card_mod:
          style:
            tabbed-card $: |
              mwc-tab {
                background: var(--ha-card-background, var(--card-background-color, white));
                border-color: var(--ha-card-border-color, var(--divider-color, #e0e0e0));
                border-width: 2px;
                border-top-left-radius: 20px;
                border-top-right-radius: 20px;
                border-style: solid;
                overflow: hidden;
                width: 50%;
              }
              mwc-tab[active] {
                background: #EBFFD8 !important;
              }
        card:
          type: custom:tabbed-card
          styles:
            '--mdc-theme-primary': green
            '--mdc-tab-text-label-color-default': silver
            '--mdc-typography-button-font-size': 12px
          tabs:
            - attributes:
                label: ATP
                icon: mdi:tennis
              card:
                type: custom:tabbed-card
                styles:
                  '--mdc-theme-primary': green
                  '--mdc-tab-text-label-color-default': silver
                  '--mdc-typography-button-font-size': 12px
                tabs:
                  - attributes:
                      label: Rankings
                      icon: mdi:format-list-bulleted
                    card:
                      type: custom:decluttering-card
                      template: ranking_settings
                      variables:
                        - title: ATP Rankings
                        - entity: sensor.tennis_atp_ranking
                  - attributes:
                      label: Schedule
                      icon: mdi:calendar
                    card:
                      type: custom:decluttering-card
                      template: schedule_settings
                      variables:
                        - title: ATP Schedule
                        - entity: sensor.tennis_atp_schedule
                        - type: mens-singles
                  - attributes:
                      label: Scores
                      icon: mdi:scoreboard
                    card:
                      type: horizontal-stack
                      cards:
                        - type: vertical-stack
                          cards:
                            - type: markdown
                              content: |
                                <h3>ATP Live Matches</h3>
                            - type: custom:decluttering-card
                              template: game_stats
                              variables:
                                - sport: ATP
                                - status: IN
                            - type: markdown
                              content: |
                                <h3>ATP Upcoming Matches</h3>
                            - type: custom:decluttering-card
                              template: game_stats
                              variables:
                                - sport: ATP
                                - status: PRE
                            - type: markdown
                              content: |
                                <h3>ATP Completed Matches</h3>
                            - type: custom:decluttering-card
                              template: game_stats
                              variables:
                                - sport: ATP
                                - status: POST
            - attributes:
                label: WTA
                icon: mdi:tennis
              card:
                type: custom:tabbed-card
                styles:
                  '--mdc-theme-primary': green
                  '--mdc-tab-text-label-color-default': silver
                  '--mdc-typography-button-font-size': 12px
                tabs:
                  - attributes:
                      label: Rankings
                      icon: mdi:format-list-bulleted
                    card:
                      type: custom:decluttering-card
                      template: ranking_settings
                      variables:
                        - title: WTA Rankings
                        - entity: sensor.tennis_wta_ranking_2
                  - attributes:
                      label: Schedule
                      icon: mdi:calendar
                    card:
                      type: custom:decluttering-card
                      template: schedule_settings
                      variables:
                        - title: WTA Schedule
                        - entity: sensor.tennis_wta_schedule_2
                        - type: womens-singles
                  - attributes:
                      label: Scores
                      icon: mdi:scoreboard
                    card:
                      type: horizontal-stack
                      cards:
                        - type: vertical-stack
                          cards:
                            - type: markdown
                              content: |
                                <h3>WTA Live Matches</h3>
                            - type: custom:decluttering-card
                              template: game_stats
                              variables:
                                - sport: WTA
                                - status: IN
                            - type: markdown
                              content: |
                                <h3>WTA Upcoming Matches</h3>
                            - type: custom:decluttering-card
                              template: game_stats
                              variables:
                                - sport: WTA
                                - status: PRE
                            - type: markdown
                              content: |
                                <h3>WTA Completed Matches</h3>
                            - type: custom:decluttering-card
                              template: game_stats
                              variables:
                                - sport: WTA
                                - status: POST
 
Hope this helps someone!
             
            
               
               
               
            
           
          
            
              
                bburwell  
                (Bob B)
               
              
                  
                    February 11, 2025, 11:10pm
                   
                   
              791 
               
             
            
              Fantastic Job Jason!  Keep Going!
I see that you have a _2 with the wta schedule -  sensor.tennis_wta_schedule_2
My guess is you might have played around with one first and then made changes  or maybe not.
If you do want it to just read  sensor.tennis_wta_schedule you can go into settings->Devices&Services->entities  search for wta - delete the sensor  sensor.tennis_wta_schedule and then go into  sensor.tennis_wta_schedule_2 and rename it by deleting the _2.  You will need to update your dashboard as well.
Great Job on what you have done so far!
             
            
               
               
              1 Like 
            
           
          
            
            
              @bburwell  thatās exactly what happenedā¦couldnāt figure it out. but resolved now ā thanks for all your help!
             
            
               
               
               
            
           
          
            
            
              Are there any other workarounds for getting duplicate cards?
Tennis isnāt populating a value for the āteam_homeawayā attribute so Iāve removed that filter from the game stats tab which is allowing duplicates to appear.
             
            
               
               
               
            
           
          
            
              
                bburwell  
                (Bob B)
               
                 
              
                  
                    February 13, 2025,  9:39pm
                   
                   
              794 
               
             
            
              Iām not showing duplicate cards on mine today, but I just put Amanda in as a quick test.
Do you have both tennis players names in there - teamtracker sensor?
If so you may need to create a check to see if the friendly_name has already been used.  Similar to something I did with NCAAF/NCAAM to filter out conference only game.
             
            
               
               
               
            
           
          
            
            
              Yes, it occurs when I have both players tracked in team tracker.
I looked at your filter and came up with something that will remove the duplicates (not as easy since the home/away isnāt an option for tennis) ā which does filter out the duplicates for IN games.
However, it creates a āno card type configuredā error for the PRE and POST games. Not certain I understand whatās causing it to only work on the IN games.
This is what Iām using the game_stats section:
  game_stats:
    card:
      type: custom:auto-entities
      unique: true
      show_empty: false
      card:
        type: custom:layout-card
        layout_type: masonry
        width: 200px
        max-columns: 5
      card_param: cards
      filter:
        template: |
          {%- set matches = namespace(seen=[]) -%}
          {%- for team in integration_entities("teamtracker") -%}
            {%- set team_id = state_attr(team, "team_id") %}
            {%- set opponent_id = state_attr(team, "opponent_id") %}
            {%- if state_attr(team, "league") == "[[sport]]" -%}
              {%- if states(team) == "[[status]]" -%}
                {%- if team_id is not none and opponent_id is not none %}
                  {%- set match = [team_id, opponent_id] | sort | join('-') %}
                    {%- if match not in matches.seen %}
                      {%- set matches.seen = matches.seen + [match] %}
                        {{{"type": "custom:teamtracker-card",
                          "entity": team, 
                          "home_side": "right",
                          "outline": true,
                          "outline_color": 'white'
                        }}},
                    {%- endif %}
                {%- endif %}
              {%- endif %}
            {%- endif %}
          {%- endfor %}
      sort:
        method: attribute
        attribute: date
 
             
            
               
               
               
            
           
          
            
              
                bburwell  
                (Bob B)
               
                 
              
                  
                    February 15, 2025,  2:51pm
                   
                   
              796 
               
             
            
              So Jinja2 drives me crazy when you are trying to use namespaces.  Thatās why filtering on home works well because you donāt have to create, but in this case there isnāt a home.
For my NCAAF/M conferences I created a separate sensor that included the team names and then sorted on that (you can see it on my github ncaaf.yaml and template.yaml files but I donāt think you really need that here.
Maybe this is an alternative, havenāt really checked it for other than a couple players.
I see that team_id has the player id that ESPN should keep constant.  For example Benjamin Bonzi is 2355 which equates to his page on ESPN - Benjamin Bonzi Stats, News, Pictures, Bio, Videos - ESPN 
Since we know players competing against each other will be in each others card, maybe key off their idās and since we donāt care if they are on the right or left only list the lower value id.
Try this instead (btw I always sandbox changes in the decluttering which is why you will see it called duplicate_game_stats and then I change dashboard calls until I verify that it works.
  duplicate_game_stats:
    card:
      type: custom:auto-entities
      unique: true
      show_empty: false
      card:
        type: custom:layout-card
        layout_type: masonry
        width: 200px
        max-columns: 5
      card_param: cards
      filter:
        template: |
          {%- for team in integration_entities("teamtracker") -%}
            {%- set team_id = state_attr(team, "team_id") %}
            {%- set opponent_id = state_attr(team, "opponent_id") %}
            {%- if state_attr(team, "league") == "[[sport]]" and states(team) == "[[status]]" -%}
              {%- if team_id is not none and opponent_id is not none and team_id < opponent_id -%}
                {{{"type": "custom:teamtracker-card",
                  "entity": team, 
                  "home_side": "right",
                  "outline": true,
                  "outline_color": "white"}}},
              {%- endif -%}
            {%- endif -%}
          {%- endfor -%}
      sort:
        method: attribute
        attribute: date
 
This is what I get: 
and I have these in the tennis.yaml file
- platform: teamtracker
  league_id: "ATP"
  team_id: "Jannik Sinner"
  name: "Jannik Sinner"
  
- platform: teamtracker
  league_id: "ATP"
  team_id: "Luca Nardi"
  name: "Luca Nardi"  
- platform: teamtracker
  league_id: "ATP"
  team_id: "Daniel Altmaier"
  name: "Daniel Altmaier"  
- platform: teamtracker
  league_id: "ATP"
  team_id: "Benjamin Bonzi"
  name: "Benjamin Bonzi" 
- platform: teamtracker
  league_id: "ATP"
  team_id: "Luca Van Assche"
  name: "Luca Van Assche" 
- platform: teamtracker
  league_id: "ATP"
  team_id: "Manuel Guinard"
  name: "Manuel Guinard"  
- platform: teamtracker
  league_id: "ATP"
  team_id: "Jan-Lennard Struff"
  name: "Jan-Lennard Struff"  
- platform: teamtracker
  league_id: "WTA"
  team_id: "Amanda Anisimova"
  name: "Amanda Anisimova"    
 
             
            
               
               
               
            
           
          
            
              
                bburwell  
                (Bob B)
               
                 
              
                  
                    February 15, 2025,  3:04pm
                   
                   
              797 
               
             
            
              @jasonkjennings  here is one maybe you can figure out on tennis for me.
It seems to me that you would want to see who won the tournaments (at least for this year) on the page as well as the upcoming ones.
That is what I did for golf and was wondering if it is possible for tennis.  Tennis APIās from what I have seen (at least for ATP) are a little goofy because sometimes it includes WTA data.  Havenāt really looked at but that was what a cursory glance showed.
So here is what I have for golf (code is on github ).  Now I am having a heck of time finding golf rankings that I donāt have to scrape but eventually that will get worked out.  Alsoneed to flush out pre/live/post but Iām getting off track, Golf is a work in progress
It would be interesting to add this to tennis.
Here is the golf schedule page: 
And here is the code change (I liked your value_template so I added it) to give me the tournaments for this year - completed and future.
## PGA Schedule
##
- platform: rest
  scan_interval: 86400
  name: Golf PGA Schedule
  unique_id: sensor.golf_pga_schedule
  resource_template: >-
    https://site.web.api.espn.com/apis/site/v2/sports/golf/pga/scoreboard?region=us&lang=en&dates={{ now().replace(month=1, day=1).strftime('%Y%m%d') }}-{{ now().replace(month=12, day=31).strftime('%Y%m%d') }}
  value_template: "{{ value_json.events | default([]) | count }}"
  json_attributes:
    - events
 
             
            
               
               
               
            
           
          
            
              
                maurizio53  
                (Maurizio Fabiani)
               
              
                  
                    February 21, 2025, 12:06pm
                   
                   
              798 
               
             
            
              I am having problems with your card⦠can you show me how you set the teamtracker integration for every athlete? 
My sensors, for example, are named āsensor.matteo_berrettiniā but they are not shown in the view. Maybe i must use a different name for those athlete sensors?
             
            
               
               
               
            
           
          
            
              
                bburwell  
                (Bob B)
               
                 
              
                  
                    February 21, 2025,  2:57pm
                   
                   
              799 
               
             
            
              Depending on your setup you will need to create a sensor for Matteo Berrentttini.  In my setup I put the players in a sensor yaml called tennis.yaml.
I donāt really follow tennis, but to check on Matteo I added this a minute ago to my tennis.yaml and since he plays on the ATP that is the league_id.
- platform: teamtracker
  league_id: "ATP"
  team_id: "Matteo Berrettini"
  name: "Matteo Berrettini"  
 
It yields this: 
You would need to do that for every player you want to see in teamtracker.
If you are using code similar to what I did you can also click on the player in player rankings and it will take you to the ESPN website for that player and you can confirm the spelling of the name.
             
            
               
               
              1 Like 
            
           
          
            
            
              here are the WTA/ATP top 50 ā keep in mind that this is a static list and wonāt update over time:
ATP:
- platform: teamtracker
  league_id: "ATP"
  team_id: "Jannik Sinner"
  name: "Jannik Sinner"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Alexander Zverev"
  name: "Alexander Zverev"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Carlos Alcaraz"
  name: "Carlos Alcaraz"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Taylor Fritz"
  name: "Taylor Fritz"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Casper Ruud"
  name: "Casper Ruud"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Novak Djokovic"
  name: "Novak Djokovic"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Daniil Medvedev"
  name: "Daniil Medvedev"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Alex de Minaur"
  name: "Alex de Minaur"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Tommy Paul"
  name: "Tommy Paul"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Andrey Rublev"
  name: "Andrey Rublev"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Grigor Dimitrov"
  name: "Grigor Dimitrov"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Stefanos Tsitsipas"
  name: "Stefanos Tsitsipas"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Holger Rune"
  name: "Holger Rune"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Felix Auger-Aliassime"
  name: "Felix Auger-Aliassime"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Frances Tiafoe"
  name: "Frances Tiafoe"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Karen Khachanov"
  name: "Karen Khachanov"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Hubert Hurkacz"
  name: "Hubert Hurkacz"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Pablo Carreno Busta"
  name: "Pablo Carreno Busta"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Denis Shapovalov"
  name: "Denis Shapovalov"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Nick Kyrgios"
  name: "Nick Kyrgios"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Roberto Bautista Agut"
  name: "Roberto Bautista Agut"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Diego Schwartzman"
  name: "Diego Schwartzman"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Lorenzo Musetti"
  name: "Lorenzo Musetti"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Borna Coric"
  name: "Borna Coric"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Sebastian Korda"
  name: "Sebastian Korda"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Daniel Evans"
  name: "Daniel Evans"
- platform: teamtracker
  league_id: "ATP"
  team_id: "John Isner"
  name: "John Isner"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Miomir Kecmanovic"
  name: "Miomir Kecmanovic"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Alejandro Davidovich Fokina"
  name: "Alejandro Davidovich Fokina"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Jenson Brooksby"
  name: "Jenson Brooksby"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Adrian Mannarino"
  name: "Adrian Mannarino"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Albert Ramos-Vinolas"
  name: "Albert Ramos-Vinolas"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Lorenzo Sonego"
  name: "Lorenzo Sonego"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Filip Krajinovic"
  name: "Filip Krajinovic"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Alexander Bublik"
  name: "Alexander Bublik"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Marton Fucsovics"
  name: "Marton Fucsovics"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Emil Ruusuvuori"
  name: "Emil Ruusuvuori"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Brandon Nakashima"
  name: "Brandon Nakashima"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Aslan Karatsev"
  name: "Aslan Karatsev"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Pedro Martinez"
  name: "Pedro Martinez"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Sebastian Baez"
  name: "Sebastian Baez"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Benjamin Bonzi"
  name: "Benjamin Bonzi"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Ugo Humbert"
  name: "Ugo Humbert"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Francisco Cerundolo"
  name: "Francisco Cerundolo"
- platform: teamtracker
  league_id: "ATP"
  team_id: "Maxime Cressy"
  name: "Maxime Cressy"
 
WTA:
- platform: teamtracker
  league_id: "WTA"
  team_id: "Aryna Sabalenka"
  name: "Aryna Sabalenka"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Iga Swiatek"
  name: "Iga Swiatek"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Coco Gauff"
  name: "Coco Gauff"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Jasmine Paolini"
  name: "Jasmine Paolini"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Jessica Pegula"
  name: "Jessica Pegula"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Madison Keys"
  name: "Madison Keys"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Elena Rybakina"
  name: "Elena Rybakina"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Qinwen Zheng"
  name: "Qinwen Zheng"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Emma Navarro"
  name: "Emma Navarro"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Paula Badosa"
  name: "Paula Badosa"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Danielle Collins"
  name: "Danielle Collins"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Daria Kasatkina"
  name: "Daria Kasatkina"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Diana Shnaider"
  name: "Diana Shnaider"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Anhelina Kalinina"
  name: "Anhelina Kalinina"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Mirra Andreeva"
  name: "Mirra Andreeva"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Magda Linette"
  name: "Magda Linette"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Veronika Kudermetova"
  name: "Veronika Kudermetova"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Liudmila Samsonova"
  name: "Liudmila Samsonova"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Anna Kalinskaya"
  name: "Anna Kalinskaya"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Jelena Ostapenko"
  name: "Jelena Ostapenko"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Petra Kvitova"
  name: "Petra Kvitova"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Ekaterina Alexandrova"
  name: "Ekaterina Alexandrova"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Barbora Krejcikova"
  name: "Barbora Krejcikova"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Karolina Pliskova"
  name: "Karolina Pliskova"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Karolina Muchova"
  name: "Karolina Muchova"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Zhang Shuai"
  name: "Zhang Shuai"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Elise Mertens"
  name: "Elise Mertens"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Victoria Azarenka"
  name: "Victoria Azarenka"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Sloane Stephens"
  name: "Sloane Stephens"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Fiona Ferro"
  name: "Fiona Ferro"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Kaia Kanepi"
  name: "Kaia Kanepi"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Jule Niemeier"
  name: "Jule Niemeier"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Marie Bouzkova"
  name: "Marie Bouzkova"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Clara Tauson"
  name: "Clara Tauson"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Claire Liu"
  name: "Claire Liu"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Elina Svitolina"
  name: "Elina Svitolina"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Marta Kostyuk"
  name: "Marta Kostyuk"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Anastasia Potapova"
  name: "Anastasia Potapova"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Bianca Andreescu"
  name: "Bianca Andreescu"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Leylah Fernandez"
  name: "Leylah Fernandez"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Amanda Anisimova"
  name: "Amanda Anisimova"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Camila Giorgi"
  name: "Camila Giorgi"
- platform: teamtracker
  league_id: "WTA"
  team_id: "Alize Cornet"
  name: "Alize Cornet"
 
             
            
               
               
              2 Likes 
            
           
          
            
              
                maurizio53  
                (Maurizio Fabiani)
               
              
                  
                    February 24, 2025,  5:34pm
                   
                   
              801 
               
             
            
              @jasonkjennings   Just a question, using the config flow in the integration. am i forced to insert all those one by one, or there is another way simplier?
             
            
               
               
               
            
           
          
            
            
              Absolutelyā¦I dropped these into my sensors.yaml file (i actually created a folder which the config yaml points to and then and dropped these two files in that folder). Then just reload your config and all the sensors are there.
             
            
               
               
               
            
           
          
            
              
                maurizio53  
                (Maurizio Fabiani)
               
              
                  
                    February 24, 2025,  8:10pm
                   
                   
              803 
               
             
            
              Ok, but in this way i need first to delete the entries inside the ui integration?
EDIT: Ok solved⦠i see sensors added manually are automatically added to the ones created in the UI.
Thanksā¦
             
            
               
               
              1 Like 
            
           
          
            
              
                bburwell  
                (Bob B)
               
                 
              
                  
                    February 25, 2025,  2:16am
                   
                   
              804 
               
             
            
              For s&gās I am toying around with UFL.  Iāve added the ufl_sensors.yaml to my github.
There seems to be less data in UFL so needed to create a new decluttering template (ufl_settings).  Season doesnāt start until March 28th and ends June 14th.
Iām sure I will need to adjust (red zone/additional data points/schedule/etc.) but code is here for those that want it:  https://github.com/bburwell/HA-Sports-Scores/tree/main 
             
            
               
               
               
            
           
          
            
              
                maurizio53  
                (Maurizio Fabiani)
               
              
                  
                    February 25, 2025, 11:02am
                   
                   
              805 
               
             
            
              Is there a way to exclude from recorder and history the sensors from this integration without putting them one by one in the entities?
             
            
               
               
               
            
           
          
            
              
                bburwell  
                (Bob B)
               
              
                  
                    February 25, 2025,  3:22pm
                   
                   
              806 
               
             
            
              You should be able to add the sensors to your configuration.yaml.  I would need to double check but I believe all of the sensors in all of my yamlās start with the sport.
So all sports sensors start with their name NBA = sensor.nba_, NFL = sensor.nfl_ , Golf = sensor.golf_*, etc.
Here is my configuration.yaml recorder section but honestly I donāt pay attention to the what I am guessing you are going after is db size.
recorder:
  exclude:
    domains:
      - teamtracker
    entity_globs:
      - sensor.mlb_*
      - sensor.nfl_*
      - sensor.nhl_*
      - sensor.nba_*
      - sensor.wnba_*
      - sensor.ncaaf_*
      - sensor.f1_*
      - sensor.nascar_*
      - sensor.tennis_*
      - sensor.golf_*
      - sensor.ufl_*
 
You probably could write an automation to purge more frequently but would need to test.  Something like this:
alias: Purge Sports Sensor Data
description: ""
triggers:
  - at: "02:00:00"
    trigger: time
actions:
  - data:
      keep_days: 5
    target:
      entity_id:
        - sensor.mlb_*
        - sensor.nfl_*
        - sensor.nhl_*
        - sensor.nba_*
        - sensor.wnba_*
        - sensor.ncaaf_*
        - sensor.f1_*
        - sensor.nascar_*
        - sensor.tennis_*
        - sensor.golf_*
        - sensor.ufl_*
    action: recorder.purge_entities
mode: single
 
Might check this link as well 
https://community.home-assistant.io/t/how-to-keep-your-recorder-database-size-under-control/295795 
If it is a performance thing when you are looking at states in developer tools and it is taking a long time - make sure to uncheck the attributes box (@ehcah   showed me that) and it really helps when youre looking at sensors.
             
            
               
               
               
            
           
          
            
              
                maurizio53  
                (Maurizio Fabiani)
               
              
                  
                    February 25, 2025,  4:27pm
                   
                   
              807 
               
             
            
              
 bburwell:
 
So all sports sensors start with their name NBA = sensor.nba_, NFL = sensor.nfl_ , Golf = sensor.golf_*, etc.
 
 
Yes, i was thinking about it, but for my fault i forgot to name the sensors with the _tennis name. So now i am forced to rename all of them. Or put in the automation the sensors one by one⦠
Hmm⦠this is very interesting⦠i never thought about it⦠Thanks.
             
            
               
               
               
            
           
          
            
              
                bburwell  
                (Bob B)
               
                 
              
                  
                    March 1, 2025, 12:40am
                   
                   
              808 
               
             
            
              So I started looking at ESPN Endpoints.  I feel that there are a couple good sites that get into the endpoints and discuss syntax, usage etc. but there are a lot of different sites you need to go to get the overall endpoints that we use in HA.
So I put together a CSV file that has a bunch of endpoints that I will continue to update from time to time.
Absolutely not complete, but figured it might help some of us on this thread and those that are new that may be looking for a different soccer league as an example and needs help in getting the link.
Feel free to comment and if you have additional links let me know and I will add them to the file.
Here is the link: https://github.com/bburwell/HA-Sports-Scores .  The file is in the ESPN API endpoints.
Here is just a snippet of what is in the file. 
Update (3/3/2025) - trying to add additional paths for other sports but havenāt added sensors or dashboards for these.  Some of the sports added include:
Basketball (NBL) 
College (Hockey,lacrosse,womenās field hockey,volleyball,water-polo(?)) 
MMA (UFC) 
Lacrosse (PLL/NLL) 
 
             
            
               
               
              1 Like