Measure the inputs behind your product
A chart can look complete while its underlying statistics are sparse. Before publishing a season comparison, count how many selected matches have each required field. Report completeness separately from the sporting statistic. A team with fewer observed shot counts should not appear to have fewer shots simply because more of its data is missing.
Choose the fields your feature actually uses, such as shots_total and possession_percent. Define the unit of observation: this example uses one team in one match. Mixing team rows with match counts doubles some denominators and makes coverage percentages difficult to interpret.
Keep field-level and endpoint-level gaps separate
Check the match statistics coverage flag before adding observations to the field report. Unsupported matches should have their own count. For supported observations, count a field as present when its value is not null, including a genuine zero. Do not require every field in the statistics object to be populated if your feature only needs a subset.
The synthetic report below includes three team-match observations and two fields. One observation has zero shots, one has unknown shots, and one has unknown possession. The calculation tracks those gaps independently rather than labelling the entire sample good or bad.
Run the reproducible example
This Python 3 example uses deliberately synthetic inputs, not a downloaded match or a forecast for a real fixture. Save it as example.py and run python3 example.py. It uses only the standard library and its assertions check the behavior discussed here. Replace the fixture inputs with validated API records when connecting your application; demo identifiers are not production lookup values.
def completeness(rows, fields):
report = {}
for field in fields:
present = sum(row.get(field) is not None for row in rows)
report[field] = {"present":present,"selected":len(rows),
"percent":round(100*present/len(rows),1) if rows else None}
return report
rows = [{"shots_total":0,"possession_percent":48.0},
{"shots_total":None,"possession_percent":52.0},
{"shots_total":10,"possession_percent":None}]
result = completeness(rows,["shots_total","possession_percent"])
assert result["shots_total"] == {"present":2,"selected":3,"percent":66.7}
assert result["possession_percent"]["present"] == 2
assert completeness([], ["shots_total"])["shots_total"]["percent"] is None
print(result)
Read the result
Both fields are present in two of three selected observations, or 66.7 percent after display rounding. The zero-shot observation is counted as present. An empty sample produces percent=null instead of a false quality conclusion.
Avoid misleading comparisons across samples
When comparing competitions, use the same field definitions, observation unit and date-selection rules. A sample of recent televised fixtures and a full historical season are different populations. Record the selected competition and season IDs, date window and retrieval period so the report can be reproduced.
Do not label the percentage as an uptime metric or a provider-wide coverage guarantee. It describes the selected observations at the time you retrieved them. If values arrive later, a repeat report may improve without any change to your application's code.
Use the report to choose interface behavior
A completeness report should lead to a product decision. You might show a metric only above a documented threshold, display a visible sample count, or provide a scores-only fallback when detailed statistics are incomplete. The threshold is your product policy and should not be presented as a data-source promise.
Retain the missing match IDs privately for debugging and retest after corrections or ingestion updates. Add tests for all-known, all-null and empty inputs. If no eligible observations were selected, report an undefined percentage rather than zero-percent quality; there was no sample from which to measure completeness.
Connect this to your project
Run a small completeness report before committing to a data-heavy feature, then keep the same checks in your release process. Use the buyer guide to connect coverage evidence with your application's actual requirements rather than choosing an API from a broad feature checklist.