Skip to content
Statistics and squads

Football head-to-head API for historical meetings

Previews almost always include the record between two clubs. The head-to-head service returns supplied history for a pair of teams, so you do not have to assemble it from years of fixtures. This page covers the two team parameters, what a meeting record can and cannot tell readers, and how to keep history from being read as a forecast.

Primary endpoint

GET/api/v1/football/head-to-head

  • team1Id required, team ID
  • team2Id required, team ID

Access: Growth and Pro. Header: X-API-Key.

Illustration of two shields facing each other across a centre circle, joined by a line of small past-meeting markers.
Head-to-head is history between two teams, addressed by two team identifiers.
01

Two team identifiers in, one shared history out

The head-to-head service takes two required parameters, team1Id and team2Id. Each is a positive numeric team identifier from the source, sent as a string. Take both from a fixture or score response for the upcoming match, so that you know the identifiers refer to the right clubs in the same system. Looking teams up by name is risky; clubs with similar names exist in many countries.

Responses arrive in the standard gateway envelope, with data holding the source structure and meta recording the feed, UTC fetch time, cache time of about an hour and qualification. We publish no normalised schema for meetings, so read a real response to see how past matches and any summary values are represented. Identifiers remain strings and source attributes keep their at-sign prefix.

Whether the order of the two teams affects the response is something to check against a sample rather than assume. If your cache stores pairs, store them in a consistent order so the same pair is not requested twice under swapped parameters.

02

History is not a forecast

A head-to-head record describes what happened in previous meetings. It does not predict what will happen next. Squads change, managers change, and a run of results from years ago can tell you very little about a match next week. Present the record as history, and avoid language such as favourites, due a win or bogey team in your own voice unless you are clearly writing opinion.

FootballAPI.net is a data provider, not a bookmaker. We do not offer odds, and head-to-head data should not be repackaged as a betting signal. If your site also covers betting, keep this panel factual and separate from any pricing content.

  • Describe past meetings; do not forecast the next one.
  • Show the period the record covers.
  • Keep head-to-head panels away from prices and tips.
Building a head-to-head panelFlow: take both team IDs from a fixture, request head-to-head with team1Id and team2Id, cache the pair, and display the supplied history with context but no forecast.01Fixturetwo team IDs02team1Id/team2Idrequest03Cache pairhour or more04Show historyno forecast
Building a head-to-head panel. Two IDs in, a cached history out; the panel describes the past only.
03

Caching pairs on the server

Head-to-head records change only when the two clubs meet again, which is rarely more than a few times a season. Cache each pair for days, not minutes, and refresh after the next meeting between them is completed. The example builds a stable cache key from the two identifiers so the pair is shared however the parameters were ordered for the request.

On a busy matchday with ten previews, that is ten requests once, after which every reader is served from your cache.

TypeScript: cache head-to-head by team pairtypescript
const pairKey = (a: string, b: string) => [a, b].sort().join(":");

export async function headToHead(team1Id: string, team2Id: string) {
  const key = pairKey(team1Id, team2Id);
  const cached = await cache.get(key);
  if (cached) return cached;
  const q = new URLSearchParams({ team1Id, team2Id });
  const res = await fetch(`https://footballapi.net/api/v1/football/head-to-head?${q}`, {
    headers: { "X-API-Key": process.env.FOOTBALLAPI_KEY! },
  });
  const body = await res.json();
  if (res.ok) await cache.set(key, body, { ttlDays: 3 });
  return body;
}
04

Giving the record context

A bare win-draw-loss count invites over-reading. Readers understand a record better when they can see which competitions the meetings were in, where they were played and when. If the source supplies those details, show them. A record dominated by cup ties from a decade ago means something different from a record of recent league meetings.

If you compute your own summaries from the supplied meetings, such as a count over the last five, label them as your calculation and make the underlying matches visible. Readers should be able to check your arithmetic.

When the record is thin, say so. Two clubs that have met twice have a head-to-head of two matches, and treating that as meaningful is a disservice to readers.

05

Clubs that changed identity

Clubs merge, reform and rename. The source may represent a reformed club with a new team identifier, in which case its head-to-head record starts from the reformation. Whether your product presents that as continuous history is an editorial choice. If you decide to combine records across identifiers, do it explicitly with a documented mapping, and tell readers the record has been combined.

This is one of the few places in football data where fans care intensely about the answer, so it is worth getting right deliberately rather than by accident.

06

Where it fits on a preview page

On a typical preview, the head-to-head panel sits beneath the essentials: kick-off time, competition, recent form and team news. It is supporting material. Pair it with team crests if your plan includes images, and link each past meeting to an archive page if you hold the historical fixtures.

Keep the panel compact on mobile. A list of every meeting in a long rivalry is overwhelming on a small screen; show the most recent few with a control to expand the rest, and make sure the full list is still present in the page for readers who want it.

07

Triggering requests from the fixture list

The most efficient way to use head-to-head is to let your fixture data drive it. When a new upcoming match enters your preview window, take the two team identifiers from the fixture and request the pair if you do not already have a fresh copy. When the match finishes, mark the cached pair as stale so the next preview between those clubs fetches an updated record. That keeps requests proportional to the matches you actually preview, rather than to every possible pair of clubs.

For cup draws, where opponents are not known until shortly before the round, wait until both team identifiers are present in the fixture before requesting the pair.

08

Neutral venues and competitions

Head-to-head records mix meetings across competitions and venues. A cup final at a neutral ground, a league match at one club's stadium and a pre-season friendly, if the source records it, are different contexts. If the source supplies competition and venue for each meeting, let readers filter by them or at least see them. A record that looks one-sided overall may be much more balanced in league matches alone.

Avoid summarising home and away splits unless the supplied data clearly indicates which club was at home in each meeting; neutral venues make that assumption unsafe.

09

Common integration mistakes

The first is requesting a pair with identifiers from two different systems, for example a team identifier from one service and another from an unrelated source. Both values must be team identifiers from the same system, typically taken from the same fixture. The second is requesting every pair in a league up front. A twenty-team league has 190 pairs; requesting all of them daily is wasteful when only ten matter this weekend. The third is presenting an empty record as a sign of an error. Two clubs that have never met in the source's records simply have no shared history yet.

10

Plan scope

Head-to-head is a global service that is not included in Starter. It requires Growth at EUR 99 a month or Pro at EUR 249, plus separate activation for your account. A Starter key receives a 403 response with the subscription_required code, which is not billed.

Because pairs are cached for days, usage is low: a weekend of previews across several competitions might be a few dozen successful requests. Above the daily inclusion of 25,000 on Growth or 250,000 on Pro, requests cost EUR 0.002 each on the monthly EUR invoice. No free trial is offered and no VAT is currently charged.

Questions developers ask

Which parameters does head-to-head require?
team1Id and team2Id, both positive numeric team identifiers sent as strings.
Is head-to-head a prediction?
No. It describes supplied past meetings and should not be presented as a forecast or betting signal.
Is head-to-head on Starter?
No. It requires Growth or Pro and separate service activation.
How long should I cache a pair?
Days. The record only changes after the two teams meet again.
Does team order matter?
Check against a sample. Store pairs in a consistent order so you do not request the same pair twice.

Check the plan before you write the integration.

Starter EUR 29, Growth EUR 99, Pro EUR 249 per month. No free trial. No VAT currently charged.