QSO

QSO

目录

QSO 资源可用于读取、创建、更新和删除日志中的通联。它构建在与 Web 界面相同的日志引擎之上,因此重复台处理、模式/子模式拆分以及删除时的清理,行为与 Wavelog 自身完全一致。

  • 基础路径: /api/v2/qso
  • 权限范围: qso:read, qso:write, qso:delete
  • 起始版本: 3.1.0

所有操作都限定在令牌所有者的台站位置范围内。不属于其中任何一台站位置的 QSO 会被视为未找到。

注意

请先阅读 API v2 概览,了解认证、响应包络与错误码。下面每个请求都需要 Authorization: Bearer 请求头。

端点

方法 路径 权限范围 用途 起始版本
GET /api/v2/qso qso:read 列出 QSO(分页) 3.1.0
GET /api/v2/qso/{id} qso:read 获取单条 QSO 3.1.0
POST /api/v2/qso qso:write 创建 QSO 3.1.0
PATCH /api/v2/qso/{id} qso:write 部分更新 3.1.0
DELETE /api/v2/qso/{id} qso:delete 删除 QSO 3.1.0

注意(QSO 上不支持 PUT)

更新始终是部分更新。Wavelog 是你日志的权威数据源,而完全替换会让客户端把它根本不知道存在的字段清空——未来版本新增的每个 ADIF 字段都会被旧客户端悄悄抹掉。如果你想完整覆盖一条 QSO,请在 PATCH 中显式发送每个字段。

频率

在整个 JSON API 中,频率(freq、freq_rx)均以 Hz 表示——无论是创建请求体(单条与批量)、更新请求体还是响应中。你也可以传入带单位后缀的值,例如 "7.0475M",它会被解析为 7047500 Hz。

注意(ADIF 载荷使用 MHz)

唯一的例外是 ADIF 导入(import_type=adif)。ADIF 载荷内的频率按 MHz 读取,因为 ADIF 标准就是这样规定的。这只适用于 ADIF 文档本身——外围的 JSON 字段不受影响。

QSO 对象

响应返回如下结构(来自日志记录):

{
  "id": 4886,
  "station_id": 1,
  "call": "N9EAT",
  "band": "20m",
  "mode": "SSB",
  "submode": null,
  "freq": 14075000,
  "freq_rx": null,
  "qso_date": "2026-06-16 17:06:00",
  "rst_sent": "59",
  "rst_rcvd": "57",
  "gridsquare": "EN42",
  "name": "Marty",
  "comment": "",
  "notes": "",
  "qth": "",
  "prop_mode": "",
  "sat_name": ""
}

列出 QSO

GET /api/v2/qso

列表端点接受一组通用筛选条件,并把结果渲染为 JSON(默认)或 ADIF——数据只获取一次,仅 format 不同(参见将 QSO 导出为 ADIF)。

筛选条件(全部可选):

参数 默认值 说明
station_id 所有自有台站位置 以逗号分隔的台站位置 ID;不属于你的 ID 会返回 403 forbidden
callsign — 与已通联呼号精确匹配,例如 4W7EST(不区分大小写);输入无效会返回 400 validation_error
band — 波段筛选,例如 20m 或 SAT
mode — 模式/子模式筛选,例如 SSB 或 FT8(匹配主模式或子模式)
qsl_filter — lotw、qsl、eqsl、qrz、clublog 的逗号分隔列表(按 OR 组合)
since_id 0 仅返回主键大于此值的 QSO
qso_since — YYYY-MM-DD,包含在内的最早 QSO 日期(整天计入)
qso_until — YYYY-MM-DD,包含在内的最新 QSO 日期(整天计入)

qso_since 与 qso_until 按 QSO 日期筛选,两端均为闭区间,可以单独使用也可以成对使用。它们与 since_id 相互独立,后者沿数据库主键遍历,用于增量同步。日期格式错误会返回 400 validation_error。

注意(集体台令牌只能看到自己的 QSO)

对于级别低于 officer 的集体台令牌,列表仅限于当前操作成员自己记录的 QSO,meta.total 也只统计这些。ADIF 导出执行同一查询,因此 format=adif 返回的集合完全相同。officer 级别可以看到每位操作员的 QSO。

分页与渲染:

参数 默认值 说明
page 1 从 1 开始的页码
per_page 50(JSON)/ 1000(ADIF) 两种格式的最大值均为 5000
limit — 最新 N 条 QSO 的快捷方式(例如 limit=1 即你最后一条 QSO)。会覆盖 page/per_page
format json json 表示对象列表,adif 表示 ADIF 导出

per_page 是两种格式共用的批大小控制项。只是默认值不同——JSON 浏览用较小值,ADIF 批量同步用较大值——而最大值都是相同的 5000。

当你只想要最近几条通联时使用 limit:它返回最新的 N 条 QSO(应用任何筛选之后,按最新在前),并忽略 page/per_page。它的上限与 per_page 相同(5000)。

# Your most recent QSO
curl "https://<WAVELOG_URL>/index.php/api/v2/qso?limit=1" \
     -H "Authorization: Bearer wl2_your_token_here"
curl "https://<WAVELOG_URL>/index.php/api/v2/qso?band=20m&station_id=1&per_page=100" \
     -H "Authorization: Bearer wl2_your_token_here"
# Everything logged in June 2026
curl "https://<WAVELOG_URL>/index.php/api/v2/qso?qso_since=2026-06-01&qso_until=2026-06-30" \
     -H "Authorization: Bearer wl2_your_token_here"
{
  "data": [ { "id": 4886, "call": "N9EAT" } ],
  "meta": { "page": 1, "per_page": 100, "count": 1, "total": 1, "total_pages": 1, "has_more": false }
}

JSON 列表按最新在前排序。meta 块包含完整的分页状态——total、total_pages 与 has_more——因此你可以一直翻页到 has_more 为 false,无需再试探空页。字段说明参见分页。

将 QSO 导出为 ADIF

GET /api/v2/qso?format=adif

渲染与上面的列表相同的筛选结果集,但输出 ADIF 而非 JSON——因此列表筛选条件(station_id、callsign、band、mode、qsl_filter、since_id、qso_since、qso_until)全部适用。这是 v1 的 get_contacts_adif 端点对应的 v2 版本。

批大小为 per_page——在 ADIF 下默认为 1000(最高到共用的 5000 上限)。ADIF 下各行按 id 升序排列,响应中会给出 lastfetchedid(本页中最大的 id)。把它作为下一次请求的 since_id 回传,即可实现只拉取新通联的增量同步——或者用 page/per_page 配合 meta.has_more 标志翻页。

curl "https://<WAVELOG_URL>/index.php/api/v2/qso?format=adif&since_id=0&station_id=1&per_page=1000" \
     -H "Authorization: Bearer wl2_your_token_here"
{
  "data": {
    "exported": 3,
    "lastfetchedid": 3218,
    "adif": "Wavelog ADIF export\n<ADIF_VER:5>3.1.7\n…<EOH>\n…<EOR>\n"
  },
  "meta": { "page": 1, "per_page": 500, "count": 3, "total": 3, "total_pages": 1, "has_more": false }
}

没有新内容时,exported 为 0,adif 为 null。

获取单条 QSO

GET /api/v2/qso/{id}

curl https://<WAVELOG_URL>/index.php/api/v2/qso/4886 \
     -H "Authorization: Bearer wl2_your_token_here"

如果 QSO 不存在或不属于该令牌,会返回 404 not_found;对于级别低于 officer 的集体台令牌,如果该 QSO 由其他操作员记录,也同样返回 404 not_found。

创建 QSO

POST /api/v2/qso

可选的请求体字段 import_type 用于选择载荷格式:

import_type 含义
json(默认) 由 JSON 字段(见下文)构成的单条 QSO,或通过 qsos 数组一次创建多条
adif 批量 ADIF 导入

未知的 import_type 会返回 400 validation_error。

对于单条 json QSO,各字段直接放在顶层发送(而不是 ADIF 字符串)。

必填字段:

字段 格式 示例
station_profile_id 整数,必须属于令牌所有者 1
call 字符串 "N9EAT"
band 字符串 "20m"
mode 字符串(模式或子模式) "SSB"
qso_date YYYY-MM-DD "2026-06-16"
time_on HHMM、HHMMSS 或 HH:MM[:SS] "1706"

常见的可选字段包括 freq、freq_rx、time_off、rst_sent、rst_rcvd、gridsquare、name、comment,以及任何其他合法的 ADIF 字段名(小写)。PATCH 显式识别的字段见可编辑字段。

curl -X POST https://<WAVELOG_URL>/index.php/api/v2/qso \
     -H "Authorization: Bearer wl2_your_token_here" \
     -H "Content-Type: application/json" \
     -d '{
           "station_profile_id": 1,
           "call": "N9EAT",
           "band": "20m",
           "mode": "SSB",
           "freq": 14075000,
           "qso_date": "2026-06-16",
           "time_on": "1706",
           "rst_sent": "59",
           "rst_rcvd": "57",
           "gridsquare": "EN42",
           "name": "Marty"
         }'

成功后 API 返回 201 Created、指向新 QSO 的 Location 响应头,以及 data 中已创建的对象。重复台检测遵循日志的常规规则。

注意

与所有基于 API 的 QSO 导入一样,出于性能与错误处理的考虑,在此创建 QSO 不会触发向 QRZ 的实时上传,也不会执行呼号簿查询。

批量导入 QSO(JSON)

带 qsos 数组的 POST /api/v2/qso(仍为 import_type: "json")。

要在一次请求中创建多条 QSO,请发送 qsos 数组而不是顶层 QSO 字段。每个元素都是一个 QSO 对象,字段与单条创建相同;它们全部导入到顶层的公共 station_profile_id。

请求体字段:

字段 说明
station_profile_id 整数,必须属于令牌所有者(所有行共用)
qsos 非空的 QSO 对象数组(每个都需要 call、band、mode、qso_date、time_on)
dryrun 可选,设为 true 时只做校验,不导入任何内容
curl -X POST https://<WAVELOG_URL>/index.php/api/v2/qso \
     -H "Authorization: Bearer wl2_your_token_here" \
     -H "Content-Type: application/json" \
     -d '{
           "station_profile_id": 1,
           "qsos": [
             { "call": "N9EAT", "band": "20m", "mode": "FT8", "qso_date": "2026-06-16", "time_on": "1706" },
             { "call": "W1AW",  "band": "40m", "mode": "CW",  "qso_date": "2026-06-16", "time_on": "1712" }
           ]
         }'

响应是批量导入摘要——结构与 ADIF 导入相同:

{ "data": { "parsed": 2, "imported": 2, "skipped": 0, "messages": [] } }
字段 含义
parsed 收到的 QSO 对象数
imported 实际存储的行数
skipped 因重复而跳过的行数
messages 任何校验/错误消息

某一行缺少必填字段会使请求以 400 validation_error 失败,details.index 会指向出错的数组元素。

批量导入 QSO(ADIF)

带 import_type: "adif" 的 POST /api/v2/qso

通过 Web 界面与 v1 API 所使用的同一引擎批量导入 ADIF 载荷。

请求体字段:

字段 说明
import_type 必须为 "adif"
station_profile_id 整数,必须属于令牌所有者
adif ADIF 文档字符串
dryrun 可选,设为 true 时只解析,不导入任何内容
curl -X POST https://<WAVELOG_URL>/index.php/api/v2/qso \
     -H "Authorization: Bearer wl2_your_token_here" \
     -H "Content-Type: application/json" \
     -d '{
           "import_type": "adif",
           "station_profile_id": 1,
           "adif": "<CALL:5>N9EAT<QSO_DATE:8>20260102<TIME_ON:4>1300<BAND:3>20m<MODE:3>FT8<EOR>"
         }'

真实导入返回 201 Created 及摘要;dryrun 返回 200 OK 及解析数量:

{ "data": { "parsed": 1, "imported": 1, "skipped": 0, "messages": [] } }
{ "data": { "dryrun": true, "parsed": 1 } }
字段 含义
parsed 在 ADIF 载荷中找到的记录数
imported 实际存储的记录数
skipped 因重复而跳过的记录数
messages 任何校验/错误消息

如果无法导入任何内容且只发生硬错误,API 会返回 400 validation_error 并附带详细信息。

提示:集体台令牌

集体台令牌以当前操作成员的呼号记录,而不是共用的集体台呼号。低于 officer 级别时,operator 字段会被覆盖,而不仅仅是填入,并且 QSO 列表、ADIF 导出以及每一项针对单条 QSO 的操作都仅限于该成员自己的通联。参见集体台。

更新 QSO

PATCH /api/v2/qso/{id}——部分更新,只修改你发送的字段。任何省略的字段都保留其已存储的值。

curl -X PATCH https://<WAVELOG_URL>/index.php/api/v2/qso/4886 \
     -H "Authorization: Bearer wl2_your_token_here" \
     -H "Content-Type: application/json" \
     -d '{ "comment": "Nice ragchew", "rst_rcvd": "59" }'

响应在 data 中返回该 QSO 的最新状态。

说明:

  • qso_date 与 time_on 必须同时提供。time_off 默认为 time_on,且绝不会早于它。
  • 传入 station_profile_id 会把该 QSO 移动到你的另一个台站位置(会校验归属)。
  • 使用低于 officer 级别的集体台令牌时,你只能编辑自己记录的 QSO;其他操作员的 QSO 会返回 404 not_found。

可编辑字段

PATCH 接受以下字段(除 qso_date/time_on、time_off、mode、freq/freq_rx 与 station_profile_id 之外,这些字段有特殊处理):

call, band, band_rx, rst_sent, rst_rcvd, gridsquare, name, comment, notes, qth,
tx_pwr, prop_mode, sat_name, sat_mode, sota_ref, pota_ref, wwff_ref, iota, sig,
sig_info, darc_dok, state, cnty, cqz, ituz, qsl_via, srx, stx, srx_string, stx_string

注意

QSL / LoTW / eQSL 确认记录以及 DXCC / 国家重算字段有意不通过 API 提供编辑。

删除 QSO

DELETE /api/v2/qso/{id}

curl -X DELETE https://<WAVELOG_URL>/index.php/api/v2/qso/4886 \
     -H "Authorization: Bearer wl2_your_token_here"

删除会执行完整清理(OQRS 条目、QSL/eQSL 图片、缓存),与从 Web 界面删除完全一致。成功后 API 返回 204 No Content。

与 PATCH 一样,低于 officer 级别的集体台令牌只能删除自己的 QSO;其他操作员的 QSO 会返回 404 not_found。

Wavelog 手册(中文版) / QSO 0 字 0 行 bg8lng
2026-10-21T12:42:36.305328901Z 2026-10-21T12:43:58.218693270Z