---
name: football-api-client
description: >-
  Integrate Football API (football.fastoffice.site): Chinese JSON football data
  for fixtures, live scores, lineups, events, stats, odds, standings. Use when
  the user has a Football API key, asks to call 足球数据 API, 接入 Football API,
  or fetch leagues/fixtures/lineups.
---

# Football API 接入 Skill

面向购买了 **Football API** 密钥的客户。用本 Skill 指导 Agent 正确调用对外接口。

## 硬性规则（必须遵守）

1. **只**请求 `https://football.fastoffice.site/v1/...`
2. **禁止**猜测、提及或调用任何第三方上游数据商；客户只对接 Football API
3. 密钥只来自用户提供的环境变量或配置，**禁止**写死密钥、禁止提交到 git
4. 除 `/v1/health` 外，每个请求带请求头：`X-Api-Key: <KEY>`（不要用 Bearer）
5. 默认限流约 **30 次/分钟**；写重试时要退避，不要狂刷
6. 成功读 `数据`；失败读 `错误.码` / `错误.信息`，不要当 HTTP 200 就一定成功
7. 可选 query 参数**没值就不要传**（不要传 `page=`、`per_page=` 空字符串）

## Base 与鉴权

```
Base: https://football.fastoffice.site/v1
Header: X-Api-Key: YOUR_API_KEY
```

推荐环境变量：`FOOTBALL_API_KEY`

## 三种 ID（别混用）

| 字段 | 示例 | 从哪拿 | 用在哪 |
|------|------|--------|--------|
| 联赛ID | `comp_3039` | `GET /leagues` → `数据[].联赛ID` | `/fixtures`、`/standings` |
| 比赛ID | `mt_988360482` | `GET /fixtures` → `数据[].比赛ID` | `/fixtures/{id}` 及子资源 |
| 赛季ID | `sn_8406098` | `GET /fixtures` → `数据[].赛季ID` | `/standings` 必填 |

路径里的 `{id}` **永远是比赛ID**，不是联赛ID。

## 推荐调用顺序

1. `GET /health`（可选，免密钥）
2. `GET /leagues?page=1&per_page=100` 取联赛（上游全部联赛，分页）
3. `GET /fixtures?competition_id=comp_3039&date=2026-08-22` 取赛程
4. 用 `比赛ID` 调 `/fixtures/{id}/lineups` 等子接口
5. 积分榜：`GET /standings?competition_id=...&season_id=...`

## 接口摘要

| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/health` | 健康检查，免密钥 |
| GET | `/leagues` | 联赛列表；query：`page` `per_page`（默认每页 100） |
| GET | `/fixtures` | 赛程；query：`competition_id` `date` `status` `page` `per_page` |
| GET | `/fixtures/live` | 进行中；query：`competition_id` `page` `per_page` |
| GET | `/fixtures/{id}` | 单场基础信息，`id`=比赛ID |
| GET | `/fixtures/{id}/lineups` | 阵容 |
| GET | `/fixtures/{id}/events` | 事件时间轴 |
| GET | `/fixtures/{id}/stats` | 技术统计 |
| GET | `/fixtures/{id}/live-stats` | 实时技术统计 |
| GET | `/fixtures/{id}/xg` | 射门图 / xG |
| GET | `/fixtures/{id}/odds` | 赔率 |
| GET | `/fixtures/{id}/odds/live` | 即时赔率 |
| GET | `/standings` | 积分榜；必填 `competition_id` + `season_id` |

完整 OpenAPI：`https://football.fastoffice.site/openapi.json`  
在线文档：`https://8aubi4drop.apifox.cn/`  
产品页：`https://football.fastoffice.site/docs`

## 中文字段

联赛：`联赛ID` `中文名` `英文名`

赛程：`比赛ID` `联赛ID` `赛季ID` `状态` `开球时间` `主队` `客队` `比分` `原始`

子资源（阵容等）：`比赛ID` + `内容`

分页（列表接口）：`分页.页码` `分页.每页` `分页.总数`

## 错误码

`UNAUTHORIZED` `FORBIDDEN` `RATE_LIMITED` `NOT_FOUND` `OUT_OF_RANGE` `UPSTREAM_ERROR` `UPSTREAM_BUSY` `INTERNAL_ERROR`

## JavaScript 最小示例

```js
const BASE = "https://football.fastoffice.site/v1";
const KEY = process.env.FOOTBALL_API_KEY;

async function api(path) {
  const res = await fetch(`${BASE}${path}`, {
    headers: { "X-Api-Key": KEY },
  });
  const json = await res.json();
  if (json.错误) throw new Error(`${json.错误.码}: ${json.错误.信息}`);
  return json;
}

const { 数据: leagues } = await api("/leagues?per_page=100");
const { 数据: fixtures } = await api("/fixtures?competition_id=comp_3039&date=2026-08-22");
const matchId = fixtures[0]?.比赛ID;
if (matchId) {
  const { 数据 } = await api(`/fixtures/${matchId}/lineups`);
}
```

## Java 最小示例

```java
HttpClient client = HttpClient.newHttpClient();
HttpRequest req = HttpRequest.newBuilder()
    .uri(URI.create("https://football.fastoffice.site/v1/leagues?per_page=100"))
    .header("X-Api-Key", System.getenv("FOOTBALL_API_KEY"))
    .GET()
    .build();
HttpResponse<String> res = client.send(req, HttpResponse.BodyHandlers.ofString());
```

## 给 Agent 的实现要求

- 用真实路径与中文字段名；不要 invent 不存在的聚合接口
- 需要联赛 ID 时先调 `/leagues`；演示可用英超 `comp_3039`
- 子接口的 `{id}` 必须来自赛程返回的 `比赛ID`
- 实时数据可能有约 15 秒缓存
- 查询窗口约近 10 年；超范围会 `OUT_OF_RANGE`
