Skip to content

Instantly share code, notes, and snippets.

@hemna
Last active June 3, 2026 14:07
Show Gist options
  • Select an option

  • Save hemna/a8188e356e3d6703f557eaa1cec2689d to your computer and use it in GitHub Desktop.

Select an option

Save hemna/a8188e356e3d6703f557eaa1cec2689d to your computer and use it in GitHub Desktop.
HAMAPI Protocol Reference (BETA) - Callsign watchlist notification protocol for APRS

HAMAPI Protocol Reference (BETA)

Overview

HAMAPI is a callsign watchlist and notification service for APRS. It lets users subscribe to callsigns they want to monitor and receive periodic APRS message notifications when those callsigns are active on the network.

What it does:

  • Users add callsigns to a personal watchlist via APRS messages to HAMAPI
  • HAMAPI monitors all APRS traffic for watched callsigns
  • When a watched callsign is heard, HAMAPI sends the subscriber a notification indicating the callsign, packet type, and time it was seen
  • Notifications are rate-limited per subscriber — after one fires, the next is suppressed until a configurable interval has elapsed (default: 8 hours)
  • On service start or new subscription, the first observed packet fires immediately so the subscriber knows the callsign is currently active

Use cases:

  • Know when a friend's station comes on the air
  • Monitor a repeater or digipeater's activity
  • Track whether a remote station is still transmitting
  • Get periodic confirmation that a watched station remains active

How it works:

Users interact with HAMAPI by sending standard APRS messages. HAMAPI acknowledges every command and maintains per-subscriber state in a database. Notifications are delivered as APRS messages with retry-until-ACK delivery.


Command Summary

Command Payload format Description
on^w CALL[,CALL2,...] [MINUTES] Watch callsign(s) with optional notify interval (min: 30, default: 480)
on^u CALL[,CALL2,...] Unwatch callsign(s)
on^cc OLDCALL,NEWCALL Change subscriber callsign (move watchlist to new callsign)
on^e CALL[,CALL2,...] Enable specific watch entry
on^d CALL[,CALL2,...] Disable specific watch entry
on^+ (none) Enable all notifications globally
on^- (none) Disable all notifications globally
on^l (none) List watched callsigns (server log only)
on^q HH HH or off Set or clear quiet hours
lb^ [CALLSIGN] Query last beacon position

Wire Format

All commands use the cmd^payload format as the APRS message text:

WB4BOR>APRS,TCPIP*::HAMAPI   :on^w KM6LYW,WB4BOR-11{42
  • cmd — command family prefix (on or lb)
  • ^ — separator
  • payload — command-specific arguments
  • {42 — APRS message ID (assigned by the sender's client)

HAMAPI addresses are padded to 9 characters per the APRS message spec: HAMAPI (with trailing spaces).


Acknowledgement Behaviour

When HAMAPI receives any valid command message that carries a message ID, it sends back an APRS ACK immediately upon receipt:

HAMAPI>APRS,TCPIP*::WB4BOR   :ack42

The ACK is sent three times to guard against packet loss:

Send When
1st Immediately on receipt
2nd +2 minutes
3rd +4 minutes

The ACK is the confirmation that the command was received and processed. No separate response text is sent for on^ commands.


on^ Commands — Online Notification

Watch callsigns

on^w CALLSIGN[,CALLSIGN2,...] [INTERVAL_MINUTES]

Add one or more callsigns to the subscriber's watchlist. HAMAPI will send a notification when any watched callsign is heard on APRS, subject to the configured notification interval.

  • CALLSIGN — one or more callsigns, comma-separated, case-insensitive
  • INTERVAL_MINUTES — optional integer; minimum minutes between periodic notifications for this callsign (default: 480 minutes / 8 hours if omitted)

The interval controls how frequently you are reminded that a callsign is active. After a notification fires, the next one will not fire until at least INTERVAL_MINUTES have elapsed — regardless of how many packets arrive in between.

Interval constraints:

Input Behaviour
Omitted Default: 480 minutes (8 hours)
0 to 29 Clamped to 30 minutes (minimum)
30+ Used as-is

Examples:

on^w KM6LYW              <- default 480-minute (8-hour) interval
on^w KM6LYW 30           <- notify every 30 minutes
on^w KM6LYW 60           <- notify every hour
on^w KM6LYW 480          <- notify every 8 hours
on^w KM6LYW,WB4BOR-11 30 <- notify every 30 minutes for both

on^w KM6LYW ← default 480-minute (8-hour) interval on^w KM6LYW 30 ← notify every 30 minutes on^w KM6LYW 60 ← notify every hour on^w KM6LYW 480 ← notify every 8 hours on^w KM6LYW,WB4BOR-11 15 ← notify every 15 minutes for both


---

### Unwatch callsign

on^u CALLSIGN[,CALLSIGN2,...]


Remove one or more callsigns from the watchlist permanently. Accepts a single
callsign or a comma-separated list.

Examples:

on^u KM6LYW on^u KM6LYW,WB4BOR-11


---

### Change subscriber callsign

on^cc OLDCALLSIGN,NEWCALLSIGN


Change the subscriber's own callsign. All watchlist entries, notification
settings (interval, quiet hours), and enabled state are moved from the old
callsign to the new one. Future notifications will be delivered to `NEWCALLSIGN`.

Use this when you change your APRS station callsign (e.g. from `WB4BOR` to
`WB4BOR-1` when switching clients or SSIDs). Your watched callsigns remain
the same — only the delivery address changes.

Example:

on^cc WB4BOR,WB4BOR-1


After this command, notifications for KM6LYW, REPEAT, etc. are sent to
`WB4BOR-1` instead of `WB4BOR`.

---

### Enable / disable a specific watch entry

on^e CALLSIGN[,CALLSIGN2,...] — enable on^d CALLSIGN[,CALLSIGN2,...] — disable


Temporarily enable or disable notification for specific watched callsigns without
removing them from the watchlist.

Examples:

on^e KM6LYW on^d KM6LYW,WB4BOR-11


---

### Enable / disable all notifications

on^+ — enable all notifications globally on^- — disable all notifications globally


Global toggle that overrides all per-callsign settings. A `+` re-enables
everything; a `-` suppresses all outbound notifications.

---

### List watched callsigns

on^l


List all currently enabled watched callsigns for this subscriber. The list is
logged server-side; no APRS response is sent (ACK only).

---

### Quiet hours

on^q START_HOUR END_HOUR — set quiet hours on^q off — clear quiet hours


Suppress notifications during a daily window. Hours are integers 0-23 in the
subscriber's configured timezone (UTC if no timezone is set).

Supports overnight ranges (e.g. `22` to `06`).

Examples:

on^q 22 06 <- quiet from 10 PM to 6 AM on^q 00 08 <- quiet from midnight to 8 AM on^q off <- always notify


---

## `lb^` Command — Last Beacon Query

lb^[CALLSIGN]


Query the database for the most recent position packet from a callsign.

- If `CALLSIGN` is omitted, the sender's own callsign is used.
- SSID-style message IDs appended by some clients (e.g. `WB4BOR-11{LB6812`) are
  stripped automatically.

Examples:

lb^ <- query sender's own last beacon lb^KM6LYW lb^WB4BOR-11


### Response format

HAMAPI>APRS,TCPIP*::WB4BOR :lb^CALLSIGN:LAT,LON,ALT,COURSE,SPEED,TIMESTAMP,SYMBOL{N


| Field       | Description                              |
|-------------|------------------------------------------|
| `CALLSIGN`  | Callsign that was queried                |
| `LAT`       | Latitude, decimal degrees (5 dp)         |
| `LON`       | Longitude, decimal degrees (5 dp)        |
| `ALT`       | Altitude, metres (0 decimal places)      |
| `COURSE`    | Course, degrees (0 decimal places)       |
| `SPEED`     | Speed, km/h (1 decimal place)            |
| `TIMESTAMP` | Unix timestamp of the packet             |
| `SYMBOL`    | Two-character APRS symbol (`table`+`code`) |

Example response:

lb^KM6LYW:37.76900,-122.41940,15,90,0.0,1717258220,/>


If no position data is found for the callsign, no response is sent (ACK only).

---

## Outbound Notifications

When a watched callsign is heard on APRS, HAMAPI sends a notification to the
subscriber as a standard APRS message:

HAMAPI>APRS,TCPIP*::WB4BOR :on^KM6LYW via pos 18:05Z{N


### Notification payload format

on^ via HH:MMZ


| Field      | Description |
|------------|-------------|
| `CALLSIGN` | The watched callsign whose packet triggered the notification |
| `TYPE`     | Short label for the APRS packet type (see table below) |
| `HH:MM`    | UTC time HAMAPI received the triggering packet (24-hour clock) |
| `Z`        | Literal suffix indicating UTC |

### Packet type labels

| Label       | APRS packet type                        |
|-------------|-----------------------------------------|
| `pos`       | Position report                         |
| `mic-e`     | Mic-E compressed position report        |
| `msg`       | APRS message                            |
| `wx`        | Weather report                          |
| `status`    | Status packet                           |
| `obj`       | Object                                  |
| `item`      | Item                                    |
| `telemetry` | Telemetry data or telemetry definition  |
| `?`         | Unknown / unparseable packet            |

### Parsing for client implementors

The message text always matches this pattern:

on^ via HH:MMZ


Suggested parse steps:

1. Check that the text starts with `on^` — this identifies it as an online notification.
2. Strip the `on^` prefix.
3. Split on ` via ` (space-via-space) to separate `CALLSIGN` (left) from `TYPE_AND_TIME` (right).
4. Split `TYPE_AND_TIME` on the final space to get `TYPE` and `HH:MMZ`.
5. Strip the trailing `Z` from `HH:MMZ` and parse as `HH:MM` UTC.
6. Convert the UTC time to the user's local timezone for display.

**Display example:**

last seen at 11:05 AM via pos packet


### Notification timing

Notifications fire in two cases:

1. **Immediately** — on the first packet seen after:
   - A user adds the callsign to their watchlist (`on^w`)
   - The HAMAPI service restarts

2. **Periodically** — each time a packet arrives from the watched callsign
   once at least `notify_interval_minutes` have elapsed since the last
   notification was sent to that subscriber.  The timer is per-subscriber
   and resets only when a notification fires, not on every incoming packet.

### Delivery

Retry-until-ACK: HAMAPI sends the notification up to 3 times (immediately,
+2 min, +4 min) and stops as soon as the subscriber's client ACKs the message.
Outbound notifications are rate-limited to 1 packet per second.

---

## Position Beacon

HAMAPI transmits a position beacon hourly and on each reconnect to APRS-IS:

HAMAPI>APRS,TCPIP*:!4147.56NL12322.97W&http://aprschat.online


Position: Happy Camp, CA (41 47.56'N 123 22.97'W). Symbol: `\&` (gateway diamond).

---

## APRS-IS Connection

HAMAPI connects to the North America Tier 2 pool (`noam.aprs2.net:14580`) with
server-side filter `g/HAMAPI` so it receives only messages addressed to it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment