Ops and QSOs
An op is one host’s on-air session, numbered per host in on-air order, so
K0TFU‘s twelfth op is /api/v1/operators/K0TFU/ops/12 and its page is
aprsota.org/K0TFU/ops/12. A QSO is one logbook entry on an op. A chase
is present whether or not the host’s QSL was ever sent.
Operator ops
GET /api/v1/operators/{callsign}/ops
The operator's hosted ops, newest first.
Every op this operator hosted that reached the air, including any op that is on the air right now.
| Parameter | In | Type | Meaning |
|---|---|---|---|
callsign | path | string | The operator's base call. An SSID form or mixed case answers 301 to the canonical URL. required |
page | query | integer | The page, 1-based. |
per_page | query | integer | Items per page, at most 100. |
state | query | string, one of on_air, ended | Only ops in this state. |
Example
{
"data": [
{
"callsign": "K0TFU",
"station": "K0TFU-6",
"number": 12,
"state": "on_air",
"description": "lunch at the lake",
"reference": {
"kind": "pota",
"code": "US-0072"
},
"grid": "DN40bs",
"position": {
"lat": 40.054167,
"lon": -111.525
},
"country": {
"code": "US",
"name": "United States of America"
},
"water": {
"kind": "lake",
"name": "Utah Lake"
},
"on_air_at": "2026-09-18T19:02:41Z",
"expires_at": "2026-09-18T20:17:00Z",
"ended_at": null,
"end_reason": null,
"signoff": null,
"qsos": 12,
"incomplete": 2,
"points": 11,
"url": "https://aprsota.org/K0TFU/ops/12",
"card_image_url": "https://aprsota.org/K0TFU/ops/12/card-3f9a1c2b7d4e.png"
}
],
"page": {
"number": 1,
"size": 20,
"total": 61,
"next_url": "https://aprsota.org/api/v1/ops?page=2"
}
}Operator op
GET /api/v1/operators/{callsign}/ops/{number}
The summary and logbook of a single op.
A chaser must have sent both the message and the position report in order for it to show in the entries, which are in chronological order.
| Parameter | In | Type | Meaning |
|---|---|---|---|
callsign | path | string | The operator's base call. An SSID form or mixed case answers 301 to the canonical URL. required |
number | path | integer | The op's per-host number. required |
Example
{
"callsign": "K0TFU",
"station": "K0TFU-6",
"number": 12,
"state": "on_air",
"description": "lunch at the lake",
"reference": {
"kind": "pota",
"code": "US-0072"
},
"grid": "DN40bs",
"position": {
"lat": 40.054167,
"lon": -111.525
},
"country": {
"code": "US",
"name": "United States of America"
},
"water": {
"kind": "lake",
"name": "Utah Lake"
},
"on_air_at": "2026-09-18T19:02:41Z",
"expires_at": "2026-09-18T20:17:00Z",
"ended_at": null,
"end_reason": null,
"signoff": null,
"qsos": 12,
"incomplete": 2,
"points": 11,
"url": "https://aprsota.org/K0TFU/ops/12",
"card_image_url": "https://aprsota.org/K0TFU/ops/12/card-3f9a1c2b7d4e.png",
"host": {
"callsign": "K0TFU",
"first_heard_at": "2026-07-22T01:14:09Z",
"last_heard_at": "2026-09-18T19:17:02Z",
"url": "https://aprsota.org/K0TFU"
},
"entries": [
{
"host": "K0TFU",
"host_station": "K0TFU-6",
"op_number": 12,
"chaser": "W1XYZ",
"chaser_station": "W1XYZ-5",
"number": 1,
"state": "confirmed",
"chased_at": "2026-09-18T19:14:19Z",
"beacon_at": "2026-09-18T19:15:02Z",
"confirmed_at": "2026-09-18T19:17:02Z",
"chase_text": "hi from the lake",
"qsl_text": "73",
"grid": "CN87xo",
"position": {
"lat": 40.054167,
"lon": -111.525
},
"country": {
"code": "US",
"name": "United States of America"
},
"water": {
"kind": "lake",
"name": "Utah Lake"
},
"points": 3,
"stamps": [
{
"kind": "ptt",
"title": "PTT",
"role": "host",
"points": 1,
"label": null
}
],
"combos": [],
"repeat": false,
"url": "https://aprsota.org/K0TFU/ops/12/qsos/W1XYZ",
"qsl_image_url": "https://aprsota.org/K0TFU/ops/12/qsos/W1XYZ/qsl-9b2e4d1f6a3c.png"
}
],
"countries": 1
}Operator QSOs
GET /api/v1/operators/{callsign}/qsos
The operator's logbook, including QSOs from hosted ops and chased ops, newest first.
Every confirmed QSO the operator was part of, as host or chaser, the same set the logbook page shows.
| Parameter | In | Type | Meaning |
|---|---|---|---|
callsign | path | string | The operator's base call. An SSID form or mixed case answers 301 to the canonical URL. required |
page | query | integer | The page, 1-based. |
per_page | query | integer | Items per page, at most 100. |
role | query | string, one of host, chaser | Only QSOs where the operator played this role. |
Example
{
"data": [
{
"host": "K0TFU",
"host_station": "K0TFU-6",
"op_number": 12,
"chaser": "W1XYZ",
"chaser_station": "W1XYZ-5",
"number": 1,
"state": "confirmed",
"chased_at": "2026-09-18T19:14:19Z",
"beacon_at": "2026-09-18T19:15:02Z",
"confirmed_at": "2026-09-18T19:17:02Z",
"chase_text": "hi from the lake",
"qsl_text": "73",
"grid": "CN87xo",
"position": {
"lat": 40.054167,
"lon": -111.525
},
"country": {
"code": "US",
"name": "United States of America"
},
"water": {
"kind": "lake",
"name": "Utah Lake"
},
"points": 3,
"stamps": [
{
"kind": "ptt",
"title": "PTT",
"role": "host",
"points": 1,
"label": null
}
],
"combos": [],
"repeat": false,
"url": "https://aprsota.org/K0TFU/ops/12/qsos/W1XYZ",
"qsl_image_url": "https://aprsota.org/K0TFU/ops/12/qsos/W1XYZ/qsl-9b2e4d1f6a3c.png"
}
],
"page": {
"number": 1,
"size": 20,
"total": 61,
"next_url": "https://aprsota.org/api/v1/ops?page=2"
}
}Operator QSO
A contact is keyed by the host’s op, the chaser’s base call, and the contact’s ordinal on that op. The ordinal is omitted for the first contact, which is the common case. A chaser who works the same host twice in one op has two real QSOs, each with its own page and card, and only the first scores.
GET /api/v1/operators/{callsign}/ops/{number}/qsos/{chaser}
The chaser's first confirmed QSO on this op.
The information on the digital QSL card. Confirmed QSOs only.
| Parameter | In | Type | Meaning |
|---|---|---|---|
callsign | path | string | The operator's base call. An SSID form or mixed case answers 301 to the canonical URL. required |
number | path | integer | The op's per-host number. required |
chaser | path | string | The chaser's base call; SSID forms and other cases 301. required |
Example
{
"host": "K0TFU",
"host_station": "K0TFU-6",
"op_number": 12,
"chaser": "W1XYZ",
"chaser_station": "W1XYZ-5",
"number": 1,
"state": "confirmed",
"chased_at": "2026-09-18T19:14:19Z",
"beacon_at": "2026-09-18T19:15:02Z",
"confirmed_at": "2026-09-18T19:17:02Z",
"chase_text": "hi from the lake",
"qsl_text": "73",
"grid": "CN87xo",
"position": {
"lat": 40.054167,
"lon": -111.525
},
"country": {
"code": "US",
"name": "United States of America"
},
"water": {
"kind": "lake",
"name": "Utah Lake"
},
"points": 3,
"stamps": [
{
"kind": "ptt",
"title": "PTT",
"role": "host",
"points": 1,
"label": null
}
],
"combos": [],
"repeat": false,
"url": "https://aprsota.org/K0TFU/ops/12/qsos/W1XYZ",
"qsl_image_url": "https://aprsota.org/K0TFU/ops/12/qsos/W1XYZ/qsl-9b2e4d1f6a3c.png"
}GET /api/v1/operators/{callsign}/ops/{number}/qsos/{chaser}/{contact}
One contact by ordinal: a chaser's second or later QSO on this op.
A repeat is still a QSO with its own page and card but it doesn't score any points. An explicit /1 answers 301 to the bare form.
| Parameter | In | Type | Meaning |
|---|---|---|---|
callsign | path | string | The operator's base call. An SSID form or mixed case answers 301 to the canonical URL. required |
number | path | integer | The op's per-host number. required |
chaser | path | string | The chaser's base call. required |
contact | path | integer | The contact's ordinal on the op, 2 or more. required |
Example
{
"host": "K0TFU",
"host_station": "K0TFU-6",
"op_number": 12,
"chaser": "W1XYZ",
"chaser_station": "W1XYZ-5",
"number": 1,
"state": "confirmed",
"chased_at": "2026-09-18T19:14:19Z",
"beacon_at": "2026-09-18T19:15:02Z",
"confirmed_at": "2026-09-18T19:17:02Z",
"chase_text": "hi from the lake",
"qsl_text": "73",
"grid": "CN87xo",
"position": {
"lat": 40.054167,
"lon": -111.525
},
"country": {
"code": "US",
"name": "United States of America"
},
"water": {
"kind": "lake",
"name": "Utah Lake"
},
"points": 3,
"stamps": [
{
"kind": "ptt",
"title": "PTT",
"role": "host",
"points": 1,
"label": null
}
],
"combos": [],
"repeat": false,
"url": "https://aprsota.org/K0TFU/ops/12/qsos/W1XYZ",
"qsl_image_url": "https://aprsota.org/K0TFU/ops/12/qsos/W1XYZ/qsl-9b2e4d1f6a3c.png"
}