LeagueSpy API v2

시장에서 가장 정확한 축구 라인업 예측을 제공합니다. 부상, 징계, 스쿼드 로테이션 패턴을 추적하여 누가 선발로 나오고, 누가 벤치에 앉고, 누가 결장하는지를 누구보다 먼저 예측합니다.

Base URL https://api.leaguespy.com
Version 2.0.0
Protocol REST / JSON
API 티어 비교

빠른 시작

1
API 키를 발급받으세요 — 문의하기 또는 담당 영업 매니저를 통해 액세스를 요청하세요.
2
첫 번째 API 호출을 수행하세요:
curl -H "X-API-Key: YOUR_KEY" \
  "https://api.leaguespy.com/v2/fixtures/updates?limit=1"
3
첫 번째 응답에서 라인업 데이터를 수신합니다. league_id 또는 team_id로 결과를 필터링하거나, updated_since를 사용하여 변경된 데이터만 폴링하세요.

인증

모든 요청에는 API 키가 필요합니다. 헤더 또는 쿼리 파라미터로 전달하세요.

# Header (recommended)
curl -H "X-API-Key: YOUR_KEY" \
  "https://api.leaguespy.com/v2/fixtures/updates"

# Query parameter
curl "https://api.leaguespy.com/v2/fixtures/updates?api_key=YOUR_KEY"
키 보안. API 키는 최소 32자 이상이어야 합니다. 클라이언트 측 코드나 공개 리포지토리에 노출하지 마세요.

티어

각 API 키는 티어에 바인딩됩니다. 티어에 따라 데이터 최신성, 업데이트 빈도, 필드 가시성이 결정됩니다.

티어동기화설명
professional3시간마다예측 선발 라인업과 벤치, 사유가 포함된 결장 선수, 발표 즉시 반영되는 공식 라인업. 대회 목록 보기.
realtime≤15분전체 데이터: 확률과 예상 출전 시간, 스쿼드 역할, 결장 영향, 복귀 선수, 포지션 경쟁, 시즌 통계. 대회 목록 보기.
현재 티어는 모든 응답의 meta.tier 및 subscription.tier에서 확인할 수 있습니다.

경기 업데이트 목록 조회

GET /v2/fixtures/updates

가장 최근에 업데이트된 순서로 정렬된 경기 라인업 프리뷰를 반환합니다. 예측 선발 XI, 벤치, 결장 선수 및 확정 라인업(가능한 경우)을 포함합니다.

쿼리 파라미터

파라미터타입기본값설명
limitinteger20페이지당 결과 수. 범위: 1–100.
offsetinteger0페이지네이션 오프셋. 범위: 0–5000.
team_idstring—팀 공개 ID로 필터링 (홈 또는 어웨이 일치).
league_idstring—리그 공개 ID로 필터링.
fixture_idstring—경기 공개 ID로 필터링.
updated_sincestring—타임존 포함 ISO 8601 날짜/시간. 이 시간 이후에 업데이트된 경기만 반환합니다. 최대 조회 기간: 48시간.
2026-06-05T08:30:00Z
cursorstring—안정적인 증분 폴링을 위한 페이지네이션 커서 (값을 해석하지 말고 그대로 사용). 이전 응답의 next_cursor 값을 사용하세요. updated_since와 함께 사용해야 합니다. offset과 함께 사용할 수 없습니다.
includestring—선택 응답 블록 (쉼표 구분). league_stats는 선수 객체에 시즌 통계를, broadcasts는 경기의 TV 및 스트리밍 중계사를 추가합니다.
langstring—이름·포지션·사유를 반환할 언어 (예: ko). 현지화 참조.
공개 ID. v2의 모든 엔티티 ID는 정수가 아닌 문자열입니다. 내부 형식을 해석하지 말고 API가 반환한 값을 그대로 사용하세요.

요청 예시

curl -H "X-API-Key: YOUR_KEY" \
  "https://api.leaguespy.com/v2/fixtures/updates?league_id=lg_xyz789&limit=5"
API 티어 비교

응답

{
  "data": [
    {
      "fixture_id": "VJfWANbE",
      "home_team_id": "11uGdbIt",
      "home_team_name": "Levante",
      "home_team_name_en": "Levante",
      "home_team_logo": "https://img.leaguespy.com/teams/11uGdbIt.png",
      "away_team_id": "aGpkiedc",
      "away_team_name": "Athletic Club",
      "away_team_name_en": "Athletic Club",
      "away_team_logo": "https://img.leaguespy.com/teams/aGpkiedc.png",
      "league_id": "QBIQ7xJS",
      "league_name": "La Liga",
      "league_name_en": "La Liga",
      "league_logo": "https://img.leaguespy.com/leagues/QBIQ7xJS.png",
      "country_name": "Spain",
      "country_name_en": "Spain",
      "season_id": "n82fEZtc",
      "season_name": "2026/2027",
      "starting_at": "2026-10-21T18:00:00Z",
      "status": "scheduled",
      "home_score": null,
      "away_score": null,
      "updated_at": "2026-10-21T09:16:54.882613Z",
      "lineup": {
        "home": {
          "formation": "4-1-4-1",
          "is_confirmed": false,
          "is_nomination_announced": false,
          "starting_xi": [
            {
              "name": "Ryan M.",
              "name_en": "Ryan M.",
              "player_id": "BFKC5XyX",
              "squad_role": "regular",
              "detailed_position": "Goalkeeper",
              "formation_position": 1,
              "start_xi_probability": 99,
              "bench_probability": 0,
              "expected_minutes": 90,
              "expected_sub_off_probability": 0,
              "expected_sub_off_minute": null
            },
            {
              "name": "Ratkov P.",
              "name_en": "Ratkov P.",
              "player_id": "jzHpyPj5",
              "squad_role": "backup",
              "detailed_position": "Centre Forward",
              "formation_position": 11,
              "start_xi_probability": 10,
              "bench_probability": 40,
              "expected_minutes": 60.0,
              "expected_sub_off_probability": 100,
              "expected_sub_off_minute": 60
            }
          ],
          "bench": [
            {
              "name": "Axel Tape",
              "name_en": "Axel Tape",
              "player_id": "W10cOGaz",
              "squad_role": "youth",
              "detailed_position": "Right Back",
              "start_xi_probability": 0,
              "bench_probability": 50,
              "expected_minutes": 0,
              "expected_sub_in_probability": 0,
              "expected_sub_in_minute": null
            }
          ],
          "missing": [
            {
              "name": "Primo A.",
              "name_en": "Primo A.",
              "player_id": "Y78HfNjW",
              "squad_role": null,
              "detailed_position": "Goalkeeper",
              "missing_type": "injury",
              "reason": "Shoulder Injury",
              "missed_in_row": 10,
              "days_missed": 157,
              "expected_return": {
                "from": "2026-11-29",
                "to": "2027-02-24"
              },
              "absence_impact": null
            },
            {
              "name": "Sotelo H.",
              "name_en": "Sotelo H.",
              "player_id": "oSwdFDDa",
              "squad_role": "backup",
              "detailed_position": "Central Midfield",
              "missing_type": "doubtful",
              "reason": "Knee Injury",
              "missed_in_row": 3,
              "days_missed": 31,
              "expected_return": null,
              "absence_impact": "low",
              "play_probability": 30,
              "start_xi_probability": 17
            }
          ],
          "new_arrivals": [],
          "returning": [
            {
              "name": "Marc Santos",
              "name_en": "Marc Santos",
              "player_id": "F1PnN5eB",
              "squad_role": "youth",
              "detailed_position": "Left Back",
              "games_missed": 2,
              "days_out": 8,
              "returning_to": "bench"
            }
          ],
          "positional_battles": [
            {
              "position": "Right Back",
              "formation_position": 2,
              "contenders": [
                {
                  "name": "Toljan J.",
                  "name_en": "Toljan J.",
                  "player_id": "0G8ozWJE",
                  "squad_role": "rotation",
                  "probability": 50
                },
                {
                  "name": "Nacho Pérez",
                  "name_en": "Nacho Pérez",
                  "player_id": "fIaRlrWZ",
                  "squad_role": "regular",
                  "probability": 50
                }
              ]
            }
          ],
          "lineup_changes": {
            "count": 4,
            "in": [
              {
                "name": "Toljan J.",
                "name_en": "Toljan J.",
                "player_id": "0G8ozWJE"
              },
              {
                "name": "Mandi A.",
                "name_en": "Mandi A.",
                "player_id": "6DY8rtL6"
              },
              {
                "name": "Olasagasti J. A.",
                "name_en": "Olasagasti J. A.",
                "player_id": "6dWOnhit"
              },
              {
                "name": "Ratkov P.",
                "name_en": "Ratkov P.",
                "player_id": "jzHpyPj5"
              }
            ],
            "out": [
              {
                "name": "Nacho Pérez",
                "name_en": "Nacho Pérez",
                "player_id": "fIaRlrWZ"
              },
              {
                "name": "Ifeanyi Ndukwe",
                "name_en": "Ifeanyi Ndukwe",
                "player_id": "c3gj48hd"
              },
              {
                "name": "Enzo Bardeli",
                "name_en": "Enzo Bardeli",
                "player_id": "RrdKtGfe"
              },
              {
                "name": "Thiago Fernández",
                "name_en": "Thiago Fernández",
                "player_id": "k2fmKhNO"
              }
            ]
          }
        }
      }
    }
  ],
  "meta": {
    "total": 1,
    "limit": 20,
    "offset": 0,
    "next_cursor": null,
    "has_more": false,
    "tier": "realtime",
    "timezone": "UTC"
  },
  "rate_limit": {
    "remaining": 119,
    "limit": 120,
    "resets_in_seconds": 60
  },
  "subscription": {
    "plan": "LeagueSpy Realtime",
    "sport": "Football",
    "tier": "realtime"
  }
}
{
  "data": [
    {
      "fixture_id": "VJfWANbE",
      "home_team_id": "11uGdbIt",
      "home_team_name": "Levante",
      "home_team_name_en": "Levante",
      "home_team_logo": "https://img.leaguespy.com/teams/11uGdbIt.png",
      "away_team_id": "aGpkiedc",
      "away_team_name": "Athletic Club",
      "away_team_name_en": "Athletic Club",
      "away_team_logo": "https://img.leaguespy.com/teams/aGpkiedc.png",
      "league_id": "QBIQ7xJS",
      "league_name": "La Liga",
      "league_name_en": "La Liga",
      "league_logo": "https://img.leaguespy.com/leagues/QBIQ7xJS.png",
      "country_name": "Spain",
      "country_name_en": "Spain",
      "season_id": "n82fEZtc",
      "season_name": "2026/2027",
      "starting_at": "2026-10-21T18:00:00Z",
      "status": "scheduled",
      "home_score": null,
      "away_score": null,
      "updated_at": "2026-10-21T09:16:54.882613Z",
      "lineup": {
        "home": {
          "formation": "4-1-4-1",
          "is_confirmed": false,
          "is_nomination_announced": false,
          "starting_xi": [
            {
              "name": "Ryan M.",
              "name_en": "Ryan M.",
              "player_id": "BFKC5XyX",
              "formation_position": 1
            },
            {
              "name": "Ratkov P.",
              "name_en": "Ratkov P.",
              "player_id": "jzHpyPj5",
              "formation_position": 11
            }
          ],
          "bench": [
            {
              "name": "Axel Tape",
              "name_en": "Axel Tape",
              "player_id": "W10cOGaz"
            }
          ],
          "missing": [
            {
              "name": "Primo A.",
              "name_en": "Primo A.",
              "player_id": "Y78HfNjW",
              "missing_type": "injury",
              "reason": "Shoulder Injury"
            },
            {
              "name": "Sotelo H.",
              "name_en": "Sotelo H.",
              "player_id": "oSwdFDDa",
              "missing_type": "doubtful",
              "reason": "Knee Injury"
            }
          ],
          "new_arrivals": [],
          "lineup_changes": {
            "count": 4,
            "in": [
              {
                "name": "Toljan J.",
                "name_en": "Toljan J.",
                "player_id": "0G8ozWJE"
              },
              {
                "name": "Mandi A.",
                "name_en": "Mandi A.",
                "player_id": "6DY8rtL6"
              },
              {
                "name": "Olasagasti J. A.",
                "name_en": "Olasagasti J. A.",
                "player_id": "6dWOnhit"
              },
              {
                "name": "Ratkov P.",
                "name_en": "Ratkov P.",
                "player_id": "jzHpyPj5"
              }
            ],
            "out": [
              {
                "name": "Nacho Pérez",
                "name_en": "Nacho Pérez",
                "player_id": "fIaRlrWZ"
              },
              {
                "name": "Ifeanyi Ndukwe",
                "name_en": "Ifeanyi Ndukwe",
                "player_id": "c3gj48hd"
              },
              {
                "name": "Enzo Bardeli",
                "name_en": "Enzo Bardeli",
                "player_id": "RrdKtGfe"
              },
              {
                "name": "Thiago Fernández",
                "name_en": "Thiago Fernández",
                "player_id": "k2fmKhNO"
              }
            ]
          }
        }
      }
    }
  ],
  "meta": {
    "total": 1,
    "limit": 20,
    "offset": 0,
    "next_cursor": null,
    "has_more": false,
    "tier": "professional",
    "timezone": "UTC"
  },
  "rate_limit": {
    "remaining": 29,
    "limit": 30,
    "resets_in_seconds": 60
  },
  "subscription": {
    "plan": "LeagueSpy Professional",
    "sport": "Football",
    "tier": "professional"
  }
}

단일 경기 조회

GET /v2/fixtures/{fixture_id}

공개 ID로 단일 경기의 라인업 데이터를 반환합니다. 응답 구조는 위의 data 배열의 단일 항목과 동일하며, 최상위 레벨에 rate_limit과 subscription이 포함됩니다.

Path 파라미터

파라미터타입설명
fixture_idstring경기의 공개 ID.

예시

curl -H "X-API-Key: YOUR_KEY" \
  "https://api.leaguespy.com/v2/fixtures/fx_a1b2c3"

응답

Fixture 객체가 data 객체로 감싸져 반환되며, 최상위 레벨에 rate_limit과 subscription이 포함됩니다.

{
  "data": {
    "fixture_id": "fx_a1b2c3",
    "home_team_name": "FC Barcelona",
    "away_team_name": "Real Madrid",
    "lineup": { /* ... */ }             // Same structure as list response
  },
  "rate_limit": { /* ... */ },
  "subscription": { /* ... */ }
}


헬스 체크

GET /health

인증이 필요하지 않습니다. 간단한 상태 객체를 반환합니다.

{ "status": "ok" }

Fixture 객체

/v2/fixtures/updates의 data 배열 항목이며, /v2/fixtures/{fixture_id}의 data입니다.

필드타입설명
fixture_idstring경기 ID (내부 형식을 해석하지 않고 그대로 사용하는 문자열).
home_team_idstring홈팀 ID.
home_team_namestring홈팀 이름 (?lang=에 따라 현지화).
home_team_name_enstring영어(원어) 이름. 모든 요청에 포함되며 데이터 매칭에 사용할 수 있습니다.
home_team_logostring (URL)홈팀 로고. 로고가 없으면 기본 이미지입니다.
away_team_idstring원정팀 ID.
away_team_namestring원정팀 이름 (?lang=에 따라 현지화).
away_team_name_enstring영어(원어) 이름. 모든 요청에 포함되며 데이터 매칭에 사용할 수 있습니다.
away_team_logostring (URL)원정팀 로고 (없으면 기본 이미지).
league_idstring대회 ID.
league_namestring대회 이름 (?lang=에 따라 현지화).
league_name_enstring영어(원어) 이름. 모든 요청에 포함되며 데이터 매칭에 사용할 수 있습니다.
league_logostring (URL)대회 로고 (없으면 기본 이미지).
country_namestring대회가 속한 국가. 국제 대회는 지역명을 사용합니다: World, Europe, Asia, South America, North & Central America 등.
country_name_enstring영어(원어) 이름. 모든 요청에 포함되며 데이터 매칭에 사용할 수 있습니다.
season_idstring시즌 ID.
season_namestring시즌 표기: 해를 넘기는 시즌은 2026/2027, 단일 연도 시즌은 2026.
starting_atstring킥오프 시각 (UTC, YYYY-MM-DDTHH:MM:SSZ). 일정이 변경되면 이 값도 바뀝니다.
statusstring경기 상태: scheduled, live, finished, postponed, cancelled 등. status 값 참조.
home_scoreinteger | null홈팀 득점: 경기 중에는 현재 스코어, 종료 후에는 최종 스코어입니다. 킥오프 전, 연기·취소된 경기, 스코어를 알 수 없는 경우에는 null. 득점은 updated_at을 바꾸지 않고 경기는 킥오프 1시간 후 /v2/fixtures/updates에서 빠지므로, 실시간·최종 스코어는 /v2/fixtures/{fixture_id}로 확인하세요.
away_scoreinteger | null원정팀 득점: 경기 중에는 현재 스코어, 종료 후에는 최종 스코어입니다. 킥오프 전, 연기·취소된 경기, 스코어를 알 수 없는 경우에는 null. 득점은 updated_at을 바꾸지 않고 경기는 킥오프 1시간 후 /v2/fixtures/updates에서 빠지므로, 실시간·최종 스코어는 /v2/fixtures/{fixture_id}로 확인하세요.
periodstring | null진행 중인 경기의 구간: first_half(전반), half_time(하프타임), second_half(후반), break(연장전 전, 연장 하프타임, 승부차기 전 휴식), extra_time(연장전), penalties(승부차기). 경기 중이 아니면 null.
minuteinteger | null경기 진행 중의 경기 시간(분) (1~45, 46~90, 91~120). 추가 시간에는 45, 90, 105, 120에 머물고 추가된 분은 extra_minute로 표시됩니다 (45+2 = minute 45, extra_minute 2). 하프타임, 휴식, 승부차기 중이거나 경기 중이 아니면 null. 약 30초 이내로 정확합니다.
extra_minuteinteger | nullminute에 더해지는 추가 시간(분). 추가 시간이 아니면 0, minute가 null이면 null.
updated_atstring이 경기의 라인업 데이터, 상태 또는 킥오프 시간이 마지막으로 변경된 시각. ISO 8601 UTC 형식이며 소수점 이하 초 자릿수는 일정하지 않습니다. 증분 폴링에 사용하세요.
lineupobjectlineup.home, lineup.away 팀 객체.
broadcastsarray | null국가별 TV 및 스트리밍 중계사. broadcasts 참조. ?include=broadcasts 사용 시에만 포함되며, 그 외에는 null. 선택 항목: 해당하는 경우에만 포함됩니다.

Lineup 객체

lineup.home과 lineup.away에 각각 들어가는 팀별 객체입니다.

필드타입설명
formationstring | null포메이션 (예: 4-2-3-1). is_confirmed가 false인 동안은 예측값, 이후에는 공식값. 알 수 없으면 null.
is_confirmedboolean공식 선발 라인업이 발표되면 true. 이후 starting_xi, bench, formation은 공식 데이터입니다.
is_nomination_announcedboolean공식 경기 명단이 확인되면 true. 현재는 is_confirmed와 함께 바뀝니다.
starting_xiarray선발 11명. 확정 전에는 예측 라인업, 확정 후에는 공식 라인업입니다. 아직 라인업이 없으면 [].
bencharray교체 명단. 확정 전에는 예측 명단, 확정 후에는 공식 명단입니다. []일 수 있습니다.
missingarray이 경기에 결장하거나 출전이 불투명한 선수. 알려진 선수가 없으면 [].
new_arrivalsarray이번 경기 명단에 포함된 최근 영입 선수. 없으면 [].
returningarrayRT 이번 경기 선발 또는 벤치에 포함되었으나 팀의 최근 경기에 빠졌던 선수. 최대 4명.
positional_battlesarrayRT 누가 선발로 나설지 불확실한 포지션.
lineup_changesobject | null팀의 직전 경기 대비 starting_xi 변경 사항. 라인업 변경 참조. 두 라인업을 비교할 수 없으면 null.

데이터 제공 흐름

  • 경기는 라인업 데이터가 생기면 킥오프 최대 7일 전부터 /v2/fixtures/updates에 표시되며, 킥오프 1시간 후까지 유지됩니다 (연기, 중단, 취소 등의 경기는 48시간).
  • 예측 라인업과 결장 선수가 먼저 제공되며, 예측을 지원하는 대회라면 킥오프 최대 7일 전부터 제공됩니다 (한 주에 두 경기를 치르는 팀은 두 경기 모두). 예측은 공식 라인업 발표 전까지 새로운 정보가 있을 때마다 갱신됩니다. 확정 전에는 is_confirmed가 false이고 starting_xi / bench는 예측값입니다.
  • 공식 라인업은 발표되는 즉시 예측을 대체하며, 발표 시점은 보통 킥오프 40~60분 전입니다 (유럽 주요 리그와 UEFA 클럽 대회는 약 50~60분 전). is_confirmed가 true로 바뀌며 이후 예측으로 되돌아가지 않습니다. 일부 하위 리그 경기는 킥오프 직전에야 공식 라인업이 제공됩니다.
  • 라인업 데이터, status, starting_at이 바뀔 때마다 updated_at이 갱신되므로 updated_since 폴링으로 모든 변경을 확인할 수 있습니다.
  • /v2/fixtures/{fixture_id}는 구독 시작일 이후의 경기를 제공합니다.

Player 객체

starting_xi 및 bench의 선수.

starting_xi[]

필드타입설명
namestring선수 이름 (?lang=에 따라 현지화).
name_enstring영어(원어) 이름. 모든 요청에 포함되며 데이터 매칭에 사용할 수 있습니다.
player_idstring | null선수 ID. 선수를 식별할 수 없는 경우에만 null.
squad_rolestring | nullRT 이번 시즌 스쿼드 내 역할. squad_role 참조.
detailed_positionstringRT 주 포지션. 포지션 참조. 항상 영어. 선택 항목: 해당하는 경우에만 포함됩니다.
detailed_position_labelstringRT 요청한 언어로 된 포지션 이름. ?lang= 사용 시에만 포함됩니다. 선택 항목: 해당하는 경우에만 포함됩니다.
formation_positioninteger | null포메이션 내 위치, 1~11. formation_position 참조.
exact_positionstring공식 전술 위치 코드 (예: RCB). 일부 공식 라인업에만 포함. 선택 항목: 해당하는 경우에만 포함됩니다.
start_xi_probabilityinteger | nullRT 선발 출전 확률(%), 0~99: 팀의 최근 공식 경기 10경기 선발 기준. 공식 라인업 선수는 99. 최근 경기 기록이 없으면 null.
bench_probabilityinteger | nullRT 교체 명단에 포함될 확률(%), 0~99.
expected_minutesnumberRT 가장 유력한 출전 시간(분): 90, 교체될 가능성이 절반을 넘으면 예상 교체 시점. 0~90.
expected_sub_off_probabilityinteger | nullRT 교체 아웃될 확률(%). 골키퍼는 0.
expected_sub_off_minuteinteger | nullRT 예상 교체 시점(분), 1~89. 교체 확률이 25% 미만이면 null.
was_doubtfulboolean경기 전 출전이 불투명했지만 라인업에 포함된 경우 true. 선택 항목: 해당하는 경우에만 포함됩니다.
debutboolean클럽 데뷔전이 될 수 있는 경우 true (new_arrivals 참조). 선택 항목: 해당하는 경우에만 포함됩니다.
returning_after_missedinteger일부 공식 라인업에서만 제공: 이 경기 전까지 연속으로 결장한 경기 수. 선택 항목: 해당하는 경우에만 포함됩니다.
league_statsobject시즌 통계, league_stats 참조. ?include=league_stats 사용 시에만 포함됩니다.

bench[]

필드타입설명
namestring선수 이름.
name_enstring영어(원어) 이름. 모든 요청에 포함되며 데이터 매칭에 사용할 수 있습니다.
player_idstring | null선수 ID.
squad_rolestring | nullRT 이번 시즌 스쿼드 내 역할.
detailed_positionstringRT 주 포지션 (항상 영어). 선택 항목: 해당하는 경우에만 포함됩니다.
detailed_position_labelstringRT 요청한 언어로 된 포지션 이름. ?lang= 사용 시에만 포함됩니다. 선택 항목: 해당하는 경우에만 포함됩니다.
start_xi_probabilityinteger | nullRT 선발 출전 확률(%). 예측 라인업에서는 같은 detailed_position의 starting_xi 선수 중 가장 낮은 값보다 높지 않습니다. 공식 라인업의 교체 선수는 0.
bench_probabilityinteger | nullRT 교체 명단에 포함될 확률(%).
expected_minutesnumber | nullRT 가장 유력한 출전 시간(분): 0, 투입될 가능성이 절반을 넘으면 투입 후 예상 출전 시간.
expected_sub_in_probabilityinteger | nullRT 교체 투입 확률(%). 골키퍼는 0.
expected_sub_in_minuteinteger | nullRT 예상 투입 시점(분), 1~89. 투입 확률이 25% 미만이면 null.
was_doubtfulboolean경기 전 출전이 불투명했지만 명단에 포함됨. 선택 항목: 해당하는 경우에만 포함됩니다.
debutboolean클럽 데뷔전 가능성 있음. 선택 항목: 해당하는 경우에만 포함됩니다.
league_statsobject시즌 통계. ?include=league_stats 사용 시에만 포함됩니다.

결장 선수 객체

missing[]의 선수: 이 경기 결장 또는 출전 불투명.

필드타입설명
namestring선수 이름.
name_enstring영어(원어) 이름. 모든 요청에 포함되며 데이터 매칭에 사용할 수 있습니다.
player_idstring | null선수 ID.
squad_rolestring | nullRT 이번 시즌 스쿼드 내 역할.
detailed_positionstringRT 주 포지션 (항상 영어). 선택 항목: 해당하는 경우에만 포함됩니다.
detailed_position_labelstringRT 요청한 언어로 된 포지션 이름. ?lang= 사용 시에만 포함됩니다. 선택 항목: 해당하는 경우에만 포함됩니다.
missing_typestring결장 유형. doubtful은 출전 가능성이 남아 있음을 의미합니다. missing_type 참조.
reasonstring | null고정 목록에서 가져온 짧은 사유 (예: Knee Injury, Red Card, Transfer to <클럽> (<국가>)). 사유 목록 참조. 항상 영어이며, 번역은 reason_label에 있습니다. 알 수 없으면 null.
reason_labelstring요청한 언어로 된 결장 사유. ?lang= 사용 시에만 포함됩니다. 선택 항목: 해당하는 경우에만 포함됩니다.
missed_in_rowintegerRT 이 경기 직전까지 경기 명단에서 빠진 연속 경기 수 (친선 경기 포함, 팀 합류 이후 기준). 0은 직전 경기 명단에 포함. 이전 명단 기록이 없는 10은 10경기 이상.
days_missedinteger | nullRT 이번 결장이 시작된 첫 경기부터 이 경기까지의 일수. 아직 결장한 경기가 없으면 null.
expected_returnobject | nullRT 부상 또는 출장 정지 선수의 예상 복귀 기간: 복귀가 예상되는 가장 이른 날짜와 가장 늦은 날짜입니다. 출장 정지는 두 날짜 모두 징계가 끝난 뒤 첫 경기 날짜입니다. 새로운 정보가 들어오면 갱신됩니다. 그 외 결장이거나 예상할 수 없으면 null.
expected_return.from / .tostringRT 날짜, YYYY-MM-DD. 날짜가 하나로 정해진 경우 from과 to가 같습니다.
absence_impactstring | nullRT 결장이 팀에 미칠 영향의 크기. absence_impact 참조.
start_xi_probabilityintegerRT 일부 doubtful 선수에만 해당: 선발 출전 확률(%), 0~100. 선택 항목: 해당하는 경우에만 포함됩니다.
play_probabilityintegerRT 일부 doubtful 선수에만 해당: 교체 출전을 포함한 출전 확률(%), 0~100. 선택 항목: 해당하는 경우에만 포함됩니다.
transfer_datestringtransfer_out에만 해당: 팀을 떠난 날짜 (YYYY-MM-DD). 선택 항목: 해당하는 경우에만 포함됩니다.
to_team_countrystringtransfer_out에만 해당: 새 클럽의 국가 (?lang=에 따라 현지화). 선택 항목: 해당하는 경우에만 포함됩니다.
to_team_country_enstring영어(원어) 이름. 모든 요청에 포함되며 데이터 매칭에 사용할 수 있습니다. 선택 항목: 해당하는 경우에만 포함됩니다.
to_team_tierinteger | nulltransfer_out에만 해당: 새 클럽 소속 리그의 등급 (1 = 1부 리그). 선택 항목: 해당하는 경우에만 포함됩니다.
league_statsobject시즌 통계. ?include=league_stats 사용 시에만 포함됩니다.

신규 영입 객체

new_arrivals[]의 선수: 최근 클럽에 합류해 이번 경기 선발 또는 벤치에 포함된 선수. 이적 후 첫 3경기 동안 표시됩니다.

필드타입설명
namestring선수 이름.
name_enstring영어(원어) 이름. 모든 요청에 포함되며 데이터 매칭에 사용할 수 있습니다.
player_idstring선수 ID.
signed_fromstring | null이전 소속 클럽과 국가, 클럽 (국가) 형식 (?lang=에 따라 현지화). 알 수 없으면 null.
signed_from_enstring영어(원어) 이름. 모든 요청에 포함되며 데이터 매칭에 사용할 수 있습니다. 선택 항목: 해당하는 경우에만 포함됩니다.
transfer_datestring합류 날짜 (YYYY-MM-DD).
stagestring새 클럽에서의 데뷔 진행 단계. stage 참조.
games_since_arrivalinteger합류 후 팀이 치른 경기 수, 0~2.
startsinteger합류 후 선발 출전 경기 수, 0~2.

복귀 선수 객체

RT returning[]의 선수: 팀의 최근 경기에 빠졌다가 이번 경기 선발 또는 벤치에 포함된 선수. 팀당 최대 4명, 결장 기간이 긴 순서.

필드타입설명
namestringRT 선수 이름.
name_enstringRT 영어(원어) 이름. 모든 요청에 포함되며 데이터 매칭에 사용할 수 있습니다.
player_idstringRT 선수 ID.
squad_rolestring | nullRT 이번 시즌 스쿼드 내 역할.
detailed_positionstring | nullRT 주 포지션 (항상 영어).
detailed_position_labelstringRT 요청한 언어로 된 포지션 이름. ?lang= 사용 시에만 포함됩니다. 선택 항목: 해당하는 경우에만 포함됩니다.
games_missedintegerRT 이 경기 전 연속 결장 경기 수, 1~10 (10 = 10경기 이상).
days_outinteger | nullRT 첫 결장 경기부터 이 경기까지의 일수.
returning_tostringRT starting_xi 또는 bench: 이번 경기에서 선발과 벤치 중 어디에 포함되었는지.

포지션 경쟁 객체

RT positional_battles[] 항목: 예측 선발 선수가 확실하지 않은 포지션. 경쟁자는 같은 포지션의 벤치 선수 중 최근 경기 선발 횟수가 선발 선수에 가깝되 넘지 않는 선수입니다. probability는 각 선수가 이번 경기에 선발로 나설 확률이므로, 선발 선수의 값에는 예측 선발 라인업에 포함된 점이 반영되고 경쟁자들은 나머지를 나눠 갖습니다 (예: 78 대 22).

필드타입설명
positionstringRT 경쟁 포지션 (항상 영어).
position_labelstringRT 요청한 언어로 된 포지션 이름. ?lang= 사용 시에만 포함됩니다. 선택 항목: 해당하는 경우에만 포함됩니다.
formation_positionintegerRT 포메이션 내 위치, 1~11.
contendersarrayRT 경쟁 선수 목록 (2명 이상). 첫 번째 선수가 현재 starting_xi에 들어 있는 선수입니다.
contenders[].namestringRT 선수 이름.
contenders[].name_enstringRT 영어(원어) 이름. 모든 요청에 포함되며 데이터 매칭에 사용할 수 있습니다.
contenders[].player_idstringRT 선수 ID.
contenders[].squad_rolestring | nullRT 이번 시즌 스쿼드 내 역할.
contenders[].probabilityintegerRT 이 선수가 선발 출전할 확률(%), 0~99.

라인업 변경 객체

lineup_changes는 starting_xi를 팀의 직전 경기(모든 대회 포함) 선발 11명과 비교합니다. 클럽 친선 경기는 제외하며, 대표팀은 친선 경기도 포함합니다. 라인업 확정 전에는 예측 라인업, 확정 후에는 공식 라인업을 비교합니다. 선발 명단이 완전한 직전 경기가 없거나 현재 선발 명단이 아직 완전하지 않으면 null입니다. 팀이 그 사이 다른 경기를 치른 경우에도 비교가 갱신될 때까지 (늦어도 경기 당일까지) null입니다.

필드타입설명
countinteger직전 경기에 선발로 나오지 않았던 starting_xi 선수 수. 0은 선발 11명이 같다는 뜻입니다.
inarray이번 경기에는 선발이지만 직전 경기에는 선발이 아니었던 선수.
outarray직전 경기에는 선발이었지만 이번 starting_xi에는 없는 선수.
in[].name / out[].namestring선수 이름 (?lang=에 따라 현지화).
in[].name_en / out[].name_enstring영어(원어) 이름. 모든 요청에 포함되며 데이터 매칭에 사용할 수 있습니다.
in[].player_id / out[].player_idstring선수 ID.

시즌 통계 (league_stats)

?include=league_stats 사용 시 starting_xi[], bench[], missing[] 선수에 추가되는 선택 블록. 컵 대회나 국제 경기에서도 항상 선수 소속 클럽의 국내 리그 기준입니다.

필드타입설명
league_stats.current_seasonobject | null이번 리그 시즌에 이 팀 소속으로 남긴 기록. 없으면 null. ?include=league_stats 사용 시에만 포함됩니다.
league_stats.previous_seasonobject | null이전 리그 시즌 기록 (가장 많이 출전한 클럽 기준). 팀이 새 시즌 리그 4경기를 치를 때까지만 제공됩니다. ?include=league_stats 사용 시에만 포함됩니다.
…league / league_idstring리그 이름 (?lang=에 따라 현지화) 및 ID. ?include=league_stats 사용 시에만 포함됩니다.
…league_enstring영어(원어) 이름. 모든 요청에 포함되며 데이터 매칭에 사용할 수 있습니다. ?include=league_stats 사용 시에만 포함됩니다.
…seasonstring시즌 표기. ?include=league_stats 사용 시에만 포함됩니다.
…team / team_idstring기록이 속한 팀 (?lang=에 따라 현지화) 및 ID. ?include=league_stats 사용 시에만 포함됩니다.
…team_enstring영어(원어) 이름. 모든 요청에 포함되며 데이터 매칭에 사용할 수 있습니다. ?include=league_stats 사용 시에만 포함됩니다.
…appearances / starts / sub_appearancesinteger출전, 선발, 교체 출전 경기 수. ?include=league_stats 사용 시에만 포함됩니다.
…substituted_off / bench_appearancesinteger교체 아웃 경기 수, 벤치 명단 포함 경기 수. ?include=league_stats 사용 시에만 포함됩니다.
…minutes / goals / assistsinteger출전 시간(분), 득점, 도움. ?include=league_stats 사용 시에만 포함됩니다.
…yellow_cards / second_yellow_cards / red_cardsinteger경고, 경고 누적 퇴장, 즉시 퇴장. ?include=league_stats 사용 시에만 포함됩니다.

현지화

두 fixtures 엔드포인트 중 어디에든 ?lang=ko를 붙이면 됩니다. 요청하시면 API 키의 기본 언어를 한국어로 설정해 드립니다. 언어 파라미터가 없거나 ?lang=en이면, 키에 기본 언어가 설정되어 있지 않은 한 영어로 응답합니다. GET /v2/languages는 지원 언어 목록을 반환합니다.

이름은 해당 필드에서 바로 번역됩니다: 팀, 리그, 국가, 선수 이름 (league_stats 포함), signed_from, to_team_country. 번역이 없는 이름은 영어로 반환됩니다. 영어 원문은 모든 요청에서 *_en 필드(home_team_name_en, name_en 등)에 함께 제공되므로 자체 데이터와 매칭할 수 있습니다.

고정 값은 번역하지 않습니다: detailed_position, positional_battles[].position, reason은 항상 영어입니다. 언어를 지정하면 번역이 detailed_position_label, position_label, reason_label에 추가됩니다. status, missing_type, squad_role, absence_impact, stage 등의 코드와 ID, 숫자, 날짜, 포메이션, 시즌 표기도 번역하지 않습니다 (코드의 한국어 의미는 아래 값 목록 참조).

응답 값의 언어나 형식이 바뀌는 경우에는 이메일과 변경 이력을 통해 미리 안내해 드립니다.


중계 정보 (broadcasts)

?include=broadcasts 사용 시 경기에 추가되는 선택 블록: 해당 경기의 중계사를 국가별로 제공합니다. 잉글랜드, 스코틀랜드, 웨일스, 북아일랜드는 United Kingdom으로 함께 표시됩니다. 중계 정보는 보통 킥오프 약 3일 전부터 제공되며, 빈 배열은 아직 알려진 중계사가 없다는 뜻입니다. 중계사는 updated_at 변경 없이 추가되거나 바뀔 수 있으므로, 경기를 표시할 때 이 블록을 읽어 주세요.

필드타입설명
countrystring국가 (?lang=에 따라 현지화). 선택 항목: 해당하는 경우에만 포함됩니다.
country_enstring국가의 영어 이름. 모든 요청에 포함됩니다. 선택 항목: 해당하는 경우에만 포함됩니다.
channels[].channelstring중계사 또는 채널. ?lang=ko 사용 시 한국 중계사는 한국어 표기를 사용하는 경우 한국어로 표시됩니다. 선택 항목: 해당하는 경우에만 포함됩니다.
channels[].channel_enstring중계사의 원래 이름. 모든 요청에 포함됩니다. 선택 항목: 해당하는 경우에만 포함됩니다.
channels[].typestringtv (TV 채널) 또는 streaming (스트리밍 서비스 또는 앱). 선택 항목: 해당하는 경우에만 포함됩니다.

Meta, 요청 한도 및 구독 정보

meta는 모든 목록 응답에, rate_limit과 subscription은 모든 응답에 포함됩니다.

필드타입설명
meta.totalinteger | null조건에 맞는 전체 경기 수. 커서 모드에서는 null.
meta.limitinteger사용된 페이지 크기.
meta.offsetinteger | null사용된 오프셋. 커서 모드에서는 null.
meta.next_cursorstring | null다음 페이지 커서. 마지막 페이지에서는 null.
meta.has_moreboolean추가 페이지가 있으면 true.
meta.tierstringprofessional 또는 realtime.
meta.timezonestring항상 UTC.
rate_limit.remaininginteger현재 1분 구간의 남은 요청 수.
rate_limit.limitinteger분당 허용 요청 수.
rate_limit.resets_in_secondsinteger구간 초기화까지 남은 초.
subscription.planstring플랜 이름 (예: LeagueSpy Realtime).
subscription.sportstring항상 Football.
subscription.tierstringprofessional 또는 realtime.

값 목록

status

postponed, suspended, interrupted, cancelled, abandoned, awarded 상태의 경기는 킥오프 후 48시간 동안 /v2/fixtures/updates에 유지됩니다. 상태 또는 킥오프 시간이 바뀌면 updated_at이 갱신됩니다.

값의미
scheduled시작 전.
tba킥오프 시간 미정.
delayed당일 킥오프 지연.
live경기 중 (하프타임, 연장, 승부차기 포함).
interrupted경기 도중 중단 (예: 악천후), 재개될 수 있음.
finished종료 (연장 또는 승부차기 후 포함).
postponed연기. 새 일정이 정해지면 starting_at에 반영.
suspended중단, 다른 날 재개 예정.
cancelled취소, 진행되지 않음.
abandoned중단 후 재개되지 않음.
awarded경기 외적인 결정으로 결과 확정 (예: 몰수승, 부전승).
unknown상태 미확인.

missing_type

값의미
injury부상 또는 질병.
suspended출장 정지 (경고 누적, 퇴장, 징계).
doubtful출전 불투명: 출전 가능성 있음. start_xi_probability, play_probability가 제공될 수 있음.
national_team국가대표 차출.
out_of_selection출전 가능하지만 경기 명단 제외 (감독 판단, 휴식, 미등록).
transfer_out최근 클럽을 떠남 (이적 또는 임대). 이적 후 몇 경기 동안 표시.
other기타 사유로 출전 불가 (예: 경기 감각 부족, 개인 사정).

absence_impact

값의미
critical핵심 선수, 결장 시작 직후. 큰 영향 예상.
high뚜렷한 영향 예상.
medium체감할 수 있는 영향.
low작은 영향.
minimal영향 거의 없음 (비주전 또는 유스 선수).
null알 수 없음 (선수 역할 미분류).

squad_role

값의미
key_player이번 시즌 팀의 핵심 선수.
regular주전 선수. 장기 부상, 질병, 출장 정지 또는 출전 불투명 선수는 건강할 때의 역할을 유지합니다.
rotation자주 출전하는 로테이션 자원.
backup출전 기회가 적은 백업 자원.
youth1군 출전이 적은 유망주.
null미분류 (예: 이번 시즌 경기 수 부족).

new_arrivals[].stage

값의미
pre_debut새 클럽 경기 명단에 처음 포함.
bench_debut명단에 포함된 적 있으나 아직 미출전.
played출전했으나 아직 선발 출전 없음.
started선발 출전 경험 있음.

returning[].returning_to

값의미
starting_xi선발로 복귀.
bench벤치로 복귀.

결장 사유 (reason)

reason은 항상 이 목록 또는 이적 템플릿 중 하나입니다. ?lang=ko 사용 시 한국어(오른쪽 열)로 반환됩니다.

값한국어 (?lang=ko)
Abdominal strain복근 부상
Achilles Tendon Injury아킬레스건 부상
Ankle Injury발목 부상
Arm Injury팔 부상
Back Injury허리 부상
Broken Hand손 골절
Broken Leg다리 골절
Broken ankle발목 골절
Broken calfbone종아리뼈 골절
Broken cheekbone광대뼈 골절
Broken collarbone쇄골 골절
Broken hipbone고관절 골절
Broken jawbone턱뼈 골절
Broken nose코뼈 골절
Broken rib갈비뼈 골절
Broken shinbone정강이뼈 골절
Broken tailbone꼬리뼈 골절
Broken thighbone대퇴골 골절
Calf Injury종아리 부상
Chest Injury가슴 부상
Coach's decision감독 판단
Concussion뇌진탕
Contusion타박상
Convalescence회복 중
Cruciate Ligament Injury십자인대 부상
Dislocation탈구
Doping도핑 징계
Doubtful출전 불투명
Elbow Injury팔꿈치 부상
Excluded명단 제외
Eye injury눈 부상
Face Injury얼굴 부상
Finger Injury손가락 부상
Foot Injury발 부상
Forearm injury아래팔 부상
Fracture골절
Groin Injury사타구니 부상
Hamstring Injury햄스트링 부상
Hand Injury손 부상
Head Injury머리 부상
Health problems건강 문제
Heart Problems심장 이상
Heel Injury발뒤꿈치 부상
Hernia탈장
Hip Injury고관절 부상
Illness질병
Inactive명단 제외
Injury부상
International duty국가대표 차출
Jaw injury턱 부상
Knee Injury무릎 부상
Knee Ligament Injury무릎 인대 부상
Knock가벼운 부상
Lack of regular playing time at club소속팀 출전 시간 부족
Lacking Match Fitness경기 감각 부족
Leg Injury다리 부상
Ligament Injury인대 부상
Loan agreement임대 계약 조항
Lower Back Injury허리 부상
Lower-Body Injury하체 부상
Meniscus Injury반월판 부상
Muscle Injury근육 부상
Muscle Tear근육 파열
Muscle Tightness근육 경직
Neck Injury목 부상
Not considered전력 외
Not in squad명단 제외
Off the roster엔트리 제외
Other기타
Overload피로 누적
Pelvis Injury골반 부상
Personal Reasons개인 사정
Red Card퇴장 징계
Rest휴식
Ribs Injury갈비뼈 부상
Shin Injury정강이 부상
Shoulder Injury어깨 부상
Stomach Disorder위장 장애
Surgery수술
Suspended출장 정지
Tendon Injury힘줄 부상
Thigh Injury허벅지 부상
Toe Injury발가락 부상
Tooth injury치아 부상
Transfer이적
Transfer negotiations이적 협상
Upper Back Injury등 부상
Upper-Body Injury상체 부상
Without a club무소속
Wrist Injury손목 부상
Yellow Cards경고 누적

이적 템플릿

Transfer to <club> (<country>), Transfer/loan to <club> (<country>), Loan ended (returned to <club> (<country>))

클럽 (국가) 이적, 클럽 (국가) 이적/임대, 임대 종료 후 클럽 (국가) 복귀

포지션

detailed_position 및 positional_battles[].position 값. 수비·미드필드·공격 중 라인만 알려진 경우 Defender, Midfielder, Attacker가 사용됩니다.

값한국어 (?lang=ko)
Goalkeeper골키퍼
Centre Back센터백
Left Back레프트백
Right Back라이트백
Left Wing Back왼쪽 윙백
Right Wing Back오른쪽 윙백
Defensive Midfield수비형 미드필더
Central Midfield중앙 미드필더
Attacking Midfield공격형 미드필더
Left Midfield왼쪽 미드필더
Right Midfield오른쪽 미드필더
Left Wing왼쪽 윙어
Right Wing오른쪽 윙어
Striker스트라이커
Centre Forward센터포워드
Second Striker세컨드 스트라이커
Defender수비수
Midfielder미드필더
Attacker공격수

formation_position

1은 골키퍼이며, 이후 수비부터 공격 순으로 각 라인을 팀 시점에서 오른쪽부터 왼쪽으로 번호를 매깁니다. 예 (4-3-3): 1 GK, 2–5 포백 (2 라이트백 … 5 레프트백), 6–8 미드필더, 9–11 공격수.

formation

수비부터 공격 순, 골키퍼 제외. 예: 4-2-3-1, 4-3-3, 4-4-2, 3-4-2-1, 4-1-4-1, 3-4-3, 3-5-2, 5-4-1, 5-3-2, 3-4-1-2, 3-1-4-2, 4-3-1-2, 4-1-3-2, 4-4-1-1, 4-2-2-2, 4-5-1.

exact_position 코드

GK, RB, RCB, CB, LCB, LB, RWB, LWB, RDM, DM, LDM, RCM, CM, LCM, RM, LM, RAM, AM, LAM, RW, LW, CF, ST.

확률 및 시간(분)

모든 확률은 0~100의 정수 퍼센트입니다 (start_xi_probability, bench_probability는 최대 99). 공식 라인업에서 선발 선수는 start_xi_probability: 99, 교체 선수는 0입니다. 교체 시점 필드(expected_sub_off_minute, expected_sub_in_minute)는 1~89이며, null은 교체가 예상되지 않음(확률 25% 미만)을 뜻합니다.

null, 빈 배열, 키 생략

빈 배열 []은 알려진 정보가 없음을 뜻하며 오류가 아닙니다. null은 알 수 없음을 의미합니다. 플래그(was_doubtful, debut)는 true일 때만 포함됩니다. 새 키가 추가될 수 있으므로 처음 보는 키는 무시하도록 구현하세요.


에러 코드

모든 에러는 error_code와 detail을 포함한 JSON 본문을 반환합니다. Rate limit 에러에는 retry_after도 포함됩니다.

{
  "error_code": "RATE_LIMIT_EXCEEDED",
  "detail": "Rate limit exceeded. Please wait before making more requests.",
  "retry_after": 60
}
HTTPError Code의미재시도?
400INVALID_DATETIME잘못된 날짜/시간 형식아니오 — 요청 수정
400INVALID_ID_FORMAT잘못된 공개 ID 형식아니오 — ID 수정
400UPDATED_SINCE_TOO_OLD조회 기간이 48시간을 초과아니오 — 전체 데이터셋은 offset 페이지네이션 사용
400INVALID_CURSOR손상되거나 변조된 커서아니오 — 커서 없이 쿼리 재시작
400CURSOR_EXPIRED2시간 이상 경과된 커서아니오 — 커서 없이 쿼리 재시작
400INVALID_PARAMScursor + offset 동시 사용 또는 updated_since 없이 cursor 사용아니오 — 요청 수정
401MISSING_API_KEYAPI 키 미제공아니오 — 헤더 추가
401INVALID_API_KEY인식되지 않는 키아니오 — 키 확인
403VERSION_ACCESS_DENIED이 키로 v2 액세스 불가아니오 — 문의 필요
404ID_NOT_FOUND엔티티가 존재하지 않음아니오 — ID 확인
405—잘못된 HTTP 메서드아니오 — GET 사용
429RATE_LIMIT_EXCEEDED요청 과다예 — retry_after 대기
500INTERNAL_ERROR서버 오류예 — 30초 후 재시도
503SERVICE_UNAVAILABLE서비스 일시 중단예 — 30초 후 재시도

응답 헤더

모든 응답에 포함됩니다.

헤더설명
X-Request-Id고유 요청 식별자. 버그 보고 시 포함하세요.
X-RateLimit-Limit해당 티어의 분당 최대 요청 수.
X-RateLimit-Remaining현재 윈도우에서 남은 요청 수.
X-RateLimit-Reset윈도우가 재설정되는 Unix 타임스탬프.
Retry-After대기해야 하는 초. 429 응답에만 존재합니다.

초기 데이터 동기화

새로운 연동은 다음 2단계 접근 방식을 따라 로컬 데이터셋을 구축하고 유지하세요:

# 1단계: 전체 데이터셋 다운로드 (1회)
# updated_since 없이 offset 페이지네이션 사용
all_fixtures = []
offset = 0
sync_started_at = datetime.now(timezone.utc).isoformat()

while True:
    resp = httpx.get(API_URL, headers=headers, timeout=30,
                     params={"limit": 100, "offset": offset})
    page = resp.json()
    all_fixtures.extend(page["data"])

    if not page["meta"]["has_more"]:
        break
    offset += page["meta"]["limit"]

# 2단계: 증분 업데이트 (지속)
# updated_since + cursor로 전환
last_check = sync_started_at

while True:
    params = {"limit": 100, "updated_since": last_check}
    cursor = None

    while True:
        if cursor:
            params["cursor"] = cursor
        resp = httpx.get(API_URL, headers=headers, params=params, timeout=30)
        data = resp.json()

        for fixture in data["data"]:
            upsert_fixture(fixture)  # 업서트 로직

        if not data["meta"]["has_more"]:
            break
        cursor = data["meta"]["next_cursor"]

    last_check = datetime.now(timezone.utc).isoformat()
    time.sleep(300)  # 5분마다 폴링
1단계는 offset을 사용합니다. 초기 전체 다운로드는 updated_since가 48시간 조회 제한이 있으므로 표준 offset 페이지네이션을 사용합니다. 전체 데이터셋을 확보한 후에는 이후 모든 업데이트에 커서 기반 증분 폴링으로 전환하세요.

커서 페이지네이션

updated_since로 업데이트를 폴링할 때는 offset 대신 커서 기반 페이지네이션을 사용하세요. 커서 페이지네이션은 데이터 일관성을 보장하여 페이지 요청 사이에 데이터가 변경되더라도 레코드를 놓치거나 중복으로 받지 않습니다.

작동 방식

각 응답의 meta 객체에 next_cursor 필드가 포함됩니다. 이 값을 다음 요청의 cursor 쿼리 파라미터로 전달하여 이전에 멈춘 지점에서 정확히 이어서 조회할 수 있습니다.

왜 offset을 사용하지 않나요? Offset 페이지네이션에서는 요청 사이에 새로운 업데이트가 데이터셋을 이동시킬 수 있어 레코드가 건너뛰어지거나 중복될 수 있습니다. 커서 페이지네이션은 새 데이터의 도착에 영향받지 않는 안정적인 북마크를 사용합니다.

예시: 다중 페이지 조회

# 1. 첫 번째 요청 — updated_since로 시작, cursor 없음
GET /v2/fixtures/updates?updated_since=2026-06-05T08:00:00Z&limit=50

# 응답:
{
  "data": [...50개 경기...],
  "meta": {
    "next_cursor": "eyJ1Ijoi...abc.d4e5f6",
    "has_more": true,
    "total": null
  }
}

# 2. 다음 페이지 — 이전 응답의 cursor 전달
GET /v2/fixtures/updates?updated_since=2026-06-05T08:00:00Z&limit=50&cursor=eyJ1Ijoi...abc.d4e5f6

# 3. 마지막 페이지 — 더 이상 데이터 없음
{
  "data": [...12개 경기...],
  "meta": {
    "next_cursor": null,
    "has_more": false
  }
}
커서 규칙.
• 커서 값은 해석하지 말고 그대로 사용하세요. 파싱, 수정, 장기 저장도 하지 마세요.
• 커서는 2시간 후 만료됩니다. 만료 시 cursor 파라미터 없이 쿼리를 재시작하세요.
• cursor는 updated_since가 필수입니다. cursor만 단독 전송하면 400을 반환합니다.
• cursor와 offset은 함께 사용할 수 없습니다. updated_since 없이 전체 데이터셋 탐색에만 offset을 사용하세요.
• updated_since는 최대 48시간 조회를 지원합니다.

폴링 전략

커서 기반 폴링과 updated_since를 사용하여 마지막 동기화 이후의 변경 사항만 효율적으로 가져오세요.

import httpx
import time
from datetime import datetime, timezone

API_URL = "https://api.leaguespy.com/v2/fixtures/updates"
headers = {"X-API-Key": "YOUR_KEY"}
last_check = datetime.now(timezone.utc).isoformat()

while True:
    params = {"limit": 100, "updated_since": last_check}
    cursor = None

    while True:  # 모든 결과 페이지 순회
        if cursor:
            params["cursor"] = cursor
        resp = httpx.get(API_URL, headers=headers, params=params, timeout=30)
        data = resp.json()

        for fixture in data["data"]:
            process_fixture(fixture)

        if not data["meta"]["has_more"]:
            break
        cursor = data["meta"]["next_cursor"]

    last_check = datetime.now(timezone.utc).isoformat()
    time.sleep(300)  # 5분마다 폴링
권장 간격. Professional 티어: 5–10분 (데이터 3시간 지연). Real-time 티어: 1–5분. 429 응답 시에는 반드시 지수 백오프(Exponential Backoff)를 적용하세요.

변경 이력

날짜버전변경 사항
2026-10-272.4.0?include=broadcasts 추가: 국가별 TV 및 스트리밍 중계사. 경기 실시간 시계 추가: period, minute, extra_minute.
2026-10-212.3.0missing[] 선수에 expected_return 추가 (Realtime): 부상 및 출장 정지 선수의 예상 복귀 기간.
2026-10-192.2.0home_score, away_score 추가. lineup_changes 추가: 팀의 직전 경기 대비 선발 라인업 변경 사항. 모든 이름의 영어 원문을 모든 요청에서 *_en으로 제공. detailed_position, position, reason은 다시 항상 영어로 제공하고 번역은 *_label로 이동.
2026-10-082.1.0status 필드 추가 (연기, 취소, 중단 등 경기 상태). 상태 및 킥오프 시간 변경 시 updated_at 갱신. 한국어 현지화 범위를 포지션과 결장 사유까지 확대. reason은 항상 고정 목록에서 제공. 전체 응답 필드 문서 갱신.
2026-06-052.0.4부분 데이터가 있는 경기에 대한 응답 일관성 개선. API 문서 업데이트.
2026-01-082.0.2일정이 빡빡한 시기의 스쿼드 로테이션을 전담하는 분석가를 충원하여 리서치 팀 확대.
2025-11-202.0.1하위 리그 커버리지 확대. 상위 5대 리그 이외 대회의 데이터 최신성 개선.
2025-09-10—API 응답 시간 <120ms(p95)로 단축. 엣지 최적화 배포로 인프라 마이그레이션.
2025-08-15—경기당일 스쿼드 감지 (is_nomination_announced). 결장 선수 분류 개선.
2025-06-20—필터 옵션 확대: team_id, league_id, fixture_id 쿼리 파라미터.
2025-03-012.0.0v2 GA 출시. 티어 기반 액세스, 구조화된 rate limiting, 엔티티 이름 강화, updated_since 폴링.
2024-11-152.0.0-betav2 beta. 새로운 응답 스키마, 확정 라인업 플로우 (is_confirmed), nomination 추적.
2024-09-011.4.0Rate limiting 개편. X-RateLimit-* 응답 헤더 추가. 키별 추적.
2024-09-01—더 많은 시간대를 커버하도록 리서치 팀 확대. 하루 종일 더 빠른 업데이트.
2024-08-15—API 인프라: gzip 압축 활성화, 페이로드 크기 대폭 감소. Health check 엔드포인트 추가.
2024-07-101.3.0티어 시스템 도입 (Essential / Professional / Real-Time). 티어별 데이터 최신성 보장.
2024-05-011.2.0선발 확률 필드 추가. 교체 선수 예상 출전 시간 — 판타지 및 DFS 플랫폼용으로 설계.
2024-05-01—예측 정확도 마일스톤: 커버리지 전체 리그에서 선발 XI 일치율 대폭 개선.
2024-03-151.1.0포메이션 감지 및 벤치 예측이 응답 스키마에 추가.
2024-03-15—결장 사유 정보 강화. 부상 유형 및 출장 정지 세부 분류.
2023-11-011.0.1페이지네이션 지원. 응답 스키마 안정화. updated_at 필드 추가.
2023-11-01—3부 리그 커버리지: League One & Two (잉글랜드), 3. Liga (독일), National (프랑스).
2023-08-10—예측 정확도 개선. 시즌 중 감독 교체 및 로테이션 패턴 처리 개선.
2023-08-011.0.0v1 GA 출시. 키 인증 기반 공개 API. 70개 대회 커버리지.
2023-02-01—2부 리그 확대: Championship, 2. Bundesliga, Serie B, Ligue 2, Segunda División. 총 50개 리그.
2022-12-10—API webhook 지원 비공개 베타. 선택된 경기의 라인업 변경에 대한 푸시 기반 알림.
2022-10-20—남미 출시: Brasileirão Série A, Argentine Primera División, Copa Libertadores.
2022-08-01—아시아 시장 진출: J1 League (일본), K League 1 (한국), A-League (호주).
2022-04-15—모든 커버 리그에 라인업 전담 분석가를 배치하여 리서치 팀 확대.
2022-01-10—커버리지 35개 리그로 확대. Eredivisie, Primeira Liga, Süper Lig, Belgian Pro League, Scottish Premiership 추가.
2021-11-01—API 업타임 99.95% SLA 달성. 고가용성 클라우드 인프라로 마이그레이션.
2021-09-01—경기 준비 전문 인력을 충원하여 리서치 팀 확대.
2021-06-15—5개 리그 추가. 총 커버리지: 12개국 25개 대회.
2021-02-01—JSON 응답 형식 안정화. API 키 인증 도입.
2020-10-15—스쿼드 전문 인력을 충원하여 리서치 팀 확대. 모든 커버 팀의 선수별 스쿼드 역할 관리.
2020-08-01—라인업 데이터에 예측 벤치 추가. 결장 선수 사유 상세 카테고리 확대.
2020-05-10—리서치 팀 전 세계 40명으로 확대. 중위권 팀 커버리지 강화.
2020-02-01—부상 및 결장 추적 개선. 결장 분류 세분화.
2019-09-15—리서치 팀 확대. 모든 결장 선수에 대한 결장 영향도 평가.
2019-06-01—커버리지 25개 리그로 확대. MLS, Liga MX, Russian Premier League, Swiss Super League 추가.
2019-01-10—리서치 팀 20명으로 확대. 비인기 경기 커버리지 개선.
2018-11-01—API 응답 캐싱 도입. 평균 응답 시간 800ms에서 200ms 미만으로 단축.
2018-08-15—10개 리그 추가: Eredivisie, Primeira Liga, Austrian Bundesliga, Danish Superliga 등.
2018-03-01—리서치 팀 확대 이후 상위 10개 리그 전반에서 예측 정확도가 크게 향상.
2017-11-01—국내 컵 커버리지 추가: FA Cup, Copa del Rey, DFB-Pokal, Coppa Italia, Coupe de France.
2017-08-01—유럽 상위 10대 리그로 확대. Eredivisie, Primeira Liga, Russian Premier League, Turkish Süper Lig, Belgian Pro League 추가.
2017-02-15—상위 5대 리그 전담 리서치 팀 구성.
2016-11-25—LeagueSpy 출시. 상위 5대 리그: Premier League, La Liga, Serie A, Bundesliga, Ligue 1. 예측 선발 XI.