开发文档

Flight Scout 接口文档
真实路由对齐文档

本页直接依据当前后端实现整理,只展示下游可直接接入的公开数据接口。对外业务能力统一挂载在 /v1 下,如果你通过同域名反代接入,接口基础地址通常就是站点根域名本身。

公开接口

7

覆盖搜索、日历、隐藏城市、机场联想与用量查询。

接入鉴权

X-API-Key

所有公开业务接口统一使用接口密钥,公开 POST 接口建议额外携带 Idempotency-Key。

接入方式

同域名直连

如果站点与接口同域部署,BASE_URL 通常就是当前站点根域名。

公开挂载

/v1/*

公开数据平面

面向开发者与业务系统的主接口,统一使用 X-API-Key 鉴权。

总览

接入概览

接入前先确认

  • 先在控制台创建接口密钥,再调用 /v1/*;不要把明文接口密钥直接硬编码进浏览器前端。
  • 免费版工作区最多只能保留 1 个有效接口密钥;如果你要轮换密钥,需要先撤销旧密钥,或者升级到付费方案。
  • 所有公开 POST 接口都建议带上 Idempotency-Key,方便你做重试、消息队列消费和防重放。
  • 如果你只想先打通一个最小闭环,推荐顺序是 airports/search -> flights/search -> account/usage。

鉴权与幂等

  • 公开业务接口统一挂在 /v1 下,调用时必须携带 X-API-Key。
  • 所有公开 POST 接口都建议附带 Idempotency-Key,服务端会按 tenant、endpoint 与请求哈希做幂等回放。
  • 成功响应统一返回 request_id、data、meta、error 四个顶层字段。
  • 限流由密钥网关实时校验;命中后会返回 429,并带 Retry-After 响应头。
  • 额度相关接口和计费型请求还会返回 X-Flight-Scout-Quota-* 响应头,便于客户端直接读取剩余额度与周期结束时间。

推荐调用链路

  • 机场输入联想:先调用 /v1/airports/search 获取 IATA 机场码。
  • 标准实时查询:使用 /v1/flights/search 或 /v1/flights/calendar。
  • 隐藏城市轻量预览:用 /v1/flights/hidden-city/search,适合快速判断是否值得展开。
  • 隐藏城市完整扫描:先 POST /v1/flights/hidden-city/jobs,再轮询 /v1/jobs/{job_id}。
  • 用量分析:通过 /v1/account/usage 拉取按计量项聚合后的请求量与点数。

计量权重

  • flight.search.request = 1 点调用额度
  • flight.calendar.request = 3 点调用额度
  • flight.hidden_city.job.request = 10 点调用额度
  • flight.hidden_city.sync.request = 15 点调用额度
  • GET /v1/airports/search、GET /v1/jobs/{job_id}、GET /v1/account/usage 不做显式计费。

常见错误

  • 401 unauthorized:缺少或错误的 X-API-Key。
  • 404 not_found:常见于轮询不存在的 job_id。
  • 422 validation_error:请求参数缺失、日期格式错误或枚举值不合法。
  • 409 conflict:常见于复用同一个 Idempotency-Key 但请求体不同。
  • 429 rate_limited:当前密钥命中限流,响应头会带 Retry-After。
  • 402 quota_exceeded:当前请求会超出套餐包含额度,可从 meta.remaining_units、meta.cycle_ends_at 和 X-Flight-Scout-Quota-* 获取额度上下文。
  • 503 provider_disabled:某个上游查询节点暂时不可用,可稍后重试或切换查询条件。
统一响应结构
{
  "request_id": "0d2a52d1-9387-44e9-b690-7f0c14c527ce",
  "data": {
    "search": {
      "origin": "SHA",
      "destination": "HND",
      "date": "2026-06-12"
    },
    "offers": [
      {
        "price": {
          "amount": 1280,
          "currency": "CNY"
        },
        "stops": 0,
        "duration_minutes": 175,
        "route_summary": "MU539 SHA -> HND"
      }
    ],
    "booking_summary_attached": 0
  },
  "meta": {
    "cache_hit": false
  },
  "error": null
}
快速开始

快速开始

如果你的站点和接口已经通过反向代理挂到同一域名,直接把 BASE_URL 设置成当前域名即可。前端浏览器场景建议通过你自己的服务端代理转发接口密钥,而不是在客户端硬编码密钥。

如果你当前是免费版工作区,请把它当作单密钥沙盒来用。控制台最多只保留 1 个有效接口密钥;轮换密钥时先撤销旧密钥,或者升级到付费方案后再做多环境并行接入。

curl
export BASE_URL="https://your-domain.com"
export API_KEY="fs_live_your_api_key"

curl -X POST "$BASE_URL/v1/flights/search" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "origin": "SHA",
    "destination": "HND",
    "date": "2026-06-12",
    "passengers": 1,
    "cabin_class": "economy",
    "sort_by": "best"
  }'
fetch
const baseUrl = "https://your-domain.com";
const apiKey = process.env.FLIGHT_SCOUT_API_KEY;

const response = await fetch(`${baseUrl}/v1/flights/search`, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-API-Key": apiKey,
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: JSON.stringify({
    origin: "SHA",
    destination: "HND",
    date: "2026-06-12",
    passengers: 1,
    cabin_class: "economy",
    sort_by: "best",
  }),
});

const payload = await response.json();
console.log(payload.data.offers);
公开接口

公开数据接口

以下接口全部基于当前后端 /v1 路由整理,并按真实返回结构、默认值、计量规则与调用方式展示。

POST/v1/flights/calendar

价格日历搜索

X-API-Key3 点调用额度

按日期范围搜索价格日历并挑选候选出发日,适合做低价日历、灵活日期推荐和价格趋势看板。

请求字段

  • origin / destination3 位 IATA 机场码,服务端自动转大写。
  • date_start / date_end搜索窗口起止日期。
  • locale日历搜索的本地化参数,默认 zh-HK。
  • currency返回货币,默认 CNY。
  • window_days单次窗口跨度,1 到 90,默认 30。
  • max_pages最大抓取页数,1 到 10,默认 3。
  • timeout日历搜索超时秒数,1 到 60,默认 12。

返回重点

  • data.calendar_query本次日历查询的标准化上下文。
  • data.calendar标准化后的日历结果主体,包含最低价日期与价格排行。
  • data.chosen_date服务端选出的推荐日期,可为 null。
  • meta.cache_hit是否命中缓存。

使用建议

  • 返回里的 calendar 已做平台标准化,适合前端自行做热力图或价格带渲染。
  • 如果你最终仍要查具体报价,通常会在 chosen_date 上再调用 flights/search。
curl
curl -X POST "$BASE_URL/v1/flights/calendar" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "origin": "PVG",
    "destination": "CDG",
    "date_start": "2026-07-03",
    "date_end": "2026-07-15",
    "passengers": 1,
    "locale": "zh-HK",
    "currency": "CNY",
    "window_days": 30
  }'
fetch
const res = await fetch(`${baseUrl}/v1/flights/calendar`, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-API-Key": apiKey,
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: JSON.stringify({
    origin: "PVG",
    destination: "CDG",
    date_start: "2026-07-03",
    date_end: "2026-07-15",
    passengers: 1,
    locale: "zh-HK",
    currency: "CNY",
    window_days: 30,
  }),
});

const payload = await res.json();
console.log(payload.data.chosen_date, payload.data.calendar);
POST/v1/flights/hidden-city/search

隐藏城市同步搜索

X-API-Key15 点调用额度

低延迟的同步隐藏城市查询,适合做快速预览和决策判断。

请求字段

  • origin / destination / date目标航线与出发日期。
  • max_polls查询轮询次数,1 到 4。
  • max_destinations同步扫描要探索的延伸目的地数量上限,1 到 10。
  • min_savings最小节省金额过滤。

返回重点

  • data.target原始目标航线摘要。
  • data.direct_reference.price目标航线的参考价。
  • data.direct_reference.selection_mode参考价选择方式:`direct_lowest`、`one_stop_fallback`、`lowest_available_fallback`、`candidate_pool_fallback`、`unavailable`。
  • data.direct_reference.direct_available / one_stop_available目标航线是否存在直飞、是否存在 1 次中转。
  • data.direct_reference.stops最终选中的参考航班经停数。
  • data.candidates隐藏城市候选报价,包含 savings、航段、时长与隐藏城市说明。
  • data.hidden_city_count识别出的隐藏城市候选数量。

使用建议

  • 服务端会关闭 `booking_summary`,并在 30 秒内超时返回。
  • 轻量版适合快速预览和同步场景。
  • 服务端会返回当前扫描范围内的全部候选,不接受 `max_candidates`。
  • 候选会按 savings 降序、price 升序排序,但不会按城市或行程去重。
  • 如果 `selection_mode` 不是 `direct_lowest`,就表示参考价不是直飞;例如 `one_stop_fallback` 代表目标航线没有直飞,只找到了 1 次中转参考价。
  • 如果你需要更完整的候选集合,请改用异步 job 版本。
curl
curl -X POST "$BASE_URL/v1/flights/hidden-city/search" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "origin": "LAX",
    "destination": "JFK",
    "date": "2026-09-12",
    "min_savings": 200
  }'
fetch
const res = await fetch(`${baseUrl}/v1/flights/hidden-city/search`, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-API-Key": apiKey,
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: JSON.stringify({
    origin: "LAX",
    destination: "JFK",
    date: "2026-09-12",
    min_savings: 200,
  }),
});

const payload = await res.json();
console.log(payload.data.candidates);
POST/v1/flights/hidden-city/jobs

隐藏城市异步任务

X-API-Key10 点调用额度

完整的隐藏城市异步扫描入口。请求会进入后台队列,由服务端在后台完成更重的组合搜索。

请求字段

  • origin / destination / date目标航线与出发日期。
  • max_destinations异步版本上限为 10。
  • with_booking_summary异步版本允许附带订票摘要。
  • booking_summary_limit0 到 3,仅在附带订票摘要时生效。

返回重点

  • data.job_id任务主键,用于后续轮询。
  • data.status创建时固定为 queued。
  • data.status_url轮询地址,格式为 /v1/jobs/{job_id}。
  • meta.queued始终为 true,表示任务已入队。

使用建议

  • 该接口返回 HTTP 202。
  • 服务端会返回当前扫描范围内的全部候选,不接受 `max_candidates`。
  • 候选会按 savings 降序、price 升序排序,但不会按城市或行程去重。
  • 推荐在客户端保存 job_id,并用指数退避轮询 /v1/jobs/{job_id}。
curl
curl -X POST "$BASE_URL/v1/flights/hidden-city/jobs" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "origin": "LAX",
    "destination": "JFK",
    "date": "2026-09-12",
    "max_destinations": 8,
    "with_booking_summary": true,
    "booking_summary_limit": 2
  }'
fetch
const enqueue = await fetch(`${baseUrl}/v1/flights/hidden-city/jobs`, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-API-Key": apiKey,
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: JSON.stringify({
    origin: "LAX",
    destination: "JFK",
    date: "2026-09-12",
    max_destinations: 8,
    with_booking_summary: true,
    booking_summary_limit: 2,
  }),
});

const payload = await enqueue.json();
console.log(payload.data.job_id, payload.data.status_url);
GET/v1/jobs/{job_id}

异步任务状态查询

X-API-Key不计费

轮询隐藏城市异步任务的执行状态。适合与 job 创建接口配合,获取最终结果、错误信息与过期时间。

路径与语义

  • job_id由 /v1/flights/hidden-city/jobs 返回的任务主键。
  • status可能为 queued、running、succeeded、failed、expired。

返回重点

  • data.result任务成功后写入的响应载荷;失败时通常为空。
  • data.error失败原因或错误信息。
  • data.created_at / started_at / finished_at / expires_at任务生命周期时间戳。
  • data.status当前任务状态。

使用建议

  • 该接口不计入调用额度。
  • 任务一旦过期,状态会被服务端标记为 expired。
curl
curl -H "X-API-Key: $API_KEY" \
  "$BASE_URL/v1/jobs/6c7b2e5d-b0e8-4b6e-9d07-6fa232e9c4a5"
fetch
const res = await fetch(`${baseUrl}/v1/jobs/${jobId}`, {
  headers: {
    "X-API-Key": apiKey,
  },
});

const payload = await res.json();
console.log(payload.data.status, payload.data.result);
GET/v1/account/usage

账号用量汇总

X-API-Key不计费

查询当前工作区的用量汇总结果。服务端按 meter_name 聚合请求次数和计费点数,适合控制台、账单预估与告警系统。

查询参数

  • period支持 all、day、month,默认 all。

返回重点

  • data.tenant_id当前租户 ID。
  • data.total_requests聚合后的总请求次数。
  • data.total_units聚合后的总计费单位。
  • data.meters按 meter_name 聚合的明细数组,含 count 与 units。
  • data.quota.used_units当前额度周期内已消耗的总点数。
  • data.quota.remaining_units当前额度周期剩余点数;支持超额计费的套餐会在超额后返回 0。
  • data.quota.window_started_at / window_ends_at当前额度周期起止时间。
  • data.quota.statuswithin_limit、exhausted、overage 或 tracked。

使用建议

  • 该接口不会额外增加用量。
  • period=month 使用最近 30 天窗口,不是自然月。
  • quota 字段表示当前额度周期,不受 period 参数影响。
  • 服务端也会返回 X-Flight-Scout-Quota-* 响应头,方便 CLI、网关和自动化任务直接读取。
curl
curl -H "X-API-Key: $API_KEY" \
  "$BASE_URL/v1/account/usage?period=month"
fetch
const res = await fetch(`${baseUrl}/v1/account/usage?period=month`, {
  headers: {
    "X-API-Key": apiKey,
  },
});

const payload = await res.json();
console.log(payload.data.total_units, payload.data.quota.remaining_units, payload.data.meters);