Tutorial · 8 min · endpoints verified 2026-09-17

How to build a soccer fixture alert app

Turn the schedule into reliable kickoff, postponement and final-score notifications without assuming player statistics or event coverage.

API coverage and endpoint overview: Explore the soccer API

Why this is hard

A kickoff time is not a durable alert state

Fixtures move, matches are postponed and status can change after the first schedule read. A useful alert service stores canonical match identity and compares the newest state with the last state it delivered.

  • Store UTC and localize only at the presentation edge.
  • Use match ID for deduplication; team names and kickoff time can change.
  • Notify on explicit status transitions rather than an expired clock.
  • A tournament edition can have long gaps with no upcoming fixtures.

Path 1 · recommended

Have your AI agent build it

MCP can discover the schedule and return the stable match identity used by the notifier.

1. Connect the MCP server

Add the server in your MCP client and sign in with your Big Balls account. Your client registers itself and handles the token exchange — there is no key to copy.

MCP client configjson
{
  "mcpServers": {
    "bigballs-sports-data": {
      "url": "https://mcp.bigballsdata.com/mcp"
    }
  }
}

2. Tools your agent gets

  • get_matches

    Live, upcoming or historical matches for a sport or league.

  • get_coverage

    Machine-readable map of what we hold and what we do not.

3. Ask for what you want

Paste this at your agent. It is written to make the model check coverage before it designs anything, which is what stops it inventing a field we do not serve.

Prompttext
Build a soccer fixture alert service for the competition I name. Check coverage, fetch scheduled matches, store match id, UTC kickoff and status, and emit notifications only when those fields change. Treat an empty schedule as healthy and do not substitute another league.

What the agent cannot reach

An MCP or REST match read does not schedule background work for you. Persist the last observed state in your own system and choose a polling cadence that respects plan limits.

Path 2 · hand-coded

Build it yourself

Keep one small state record per match and make every notification idempotent.

  1. 01

    Check the live coverage map first

    Ask the coverage endpoint what is served before you make a field required in your interface. An unavailable field should produce an honest empty state, not a guessed value.

    Verify soccer coveragebash
    curl -s "https://api.bigballsdata.com/v1/coverage?sport=football" \
      -H "x-api-key: $BBS_API_KEY"
  2. 02

    Read the competition schedule

    Use the exact competition key returned by coverage. The response owns canonical match ID, kickoff and status.

    Upcoming fixturesbash
    curl -s "https://api.bigballsdata.com/v1/matches?sport=football&league=$LEAGUE&status=scheduled&limit=50" \
      -H "x-api-key: $BBS_API_KEY"
  3. 03

    Emit only state changes

    Compare the new row with the stored row. This prevents repeated kickoff alerts and lets postponements replace the original schedule.

    Idempotent alert decisiontypescript
    const changed = (before: Match | undefined, after: Match) =>
      !before || before.kickoff_utc !== after.kickoff_utc || before.status !== after.status;
    
    if (changed(stored.get(match.id), match)) {
      await notify(match);
      stored.set(match.id, match);
    }

Reference

Every endpoint this tutorial uses

All on the gateway at api.bigballsdata.com. Verified against production on 2026-09-17.

MethodPathReturnsWhy you need itPlan
GET/v1/coverage?sport=footballCompetition identity and measured schedule coverageConfirms the competition before a scheduler starts polling it.Free
GET/v1/matches?sport=football&league=Canonical match IDs, UTC kickoff, participants, score and statusProvides the durable state used for kickoff, postponement and result alerts.Free

Pricing, honestly

Free validates the alert loop

A small competition-scoped notifier fits the Free evaluation tier. Paid plans become relevant when more sports, longer history or production request volume enter the product.

Free key

jsonjson
One-sport schedule polling within the Free request allowance.

Solo

jsonjson
More sports, productive volume and the broader paid capability set.
  • Cache finished matches instead of polling them forever.
  • Back off on 429 and use response metadata when available.
  • An empty tournament schedule is not an ingestion failure by itself.

More tutorials

Other build guides

Known gaps

Operational boundaries to keep visible

The API supplies match state; notification delivery belongs to the application.

  • Choose and operate your own scheduler or queue.
  • Persist deduplication state outside a stateless request handler.
  • Do not infer postponed or cancelled from a blank score.

Questions

Which timezone should alerts use?
Store UTC from the API, then convert to each user's timezone when rendering the alert.
How do I avoid duplicate notifications?
Key state by canonical match ID and emit only when kickoff, status or the final score changes.
What does an empty upcoming schedule mean?
It can be healthy for a tournament between rounds or editions. Check coverage and the requested competition before treating it as an outage.

Ship the first fixture alert

Use one real competition, retain the match IDs, and make every notification safe to retry.