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。