The CQGMA Spot API provides recent GMA and WWFF spots as JSON data.
It is intended for lightweight clients, dashboards, tools, spot displays and integrations.
Please use the API fairly. The service is provided by CQGMA.org and should not be polled more often than once per minute.
| Purpose | URL |
|---|---|
| Last 10 spots | https://www.cqgma.org/api/spots/10/ |
| Last 25 spots | https://www.cqgma.org/api/spots/25/ |
| Last WWFF spots | https://www.cqgma.org/api/spots/wwff/ |
| Last GMA-only spots | https://www.cqgma.org/api/spots/gma/ |
The main WWFF endpoint is:
https://www.cqgma.org/api/spots/wwff/
This endpoint returns the current WWFF spot list as JSON.
The data is generated server-side from a cache file. The cache file is normally refreshed once per minute.
Please do not poll the API more often than once per minute.
Limits:
Maximum rate: 1 request per 60 seconds
Maximum daily requests: 1440 requests per client per UTC day
The daily limit includes all requests, including requests that receive a 429 Too Many Requests response.
This means that aggressive polling will use up the daily request limit quickly, even if many of the requests are blocked.
API responses are cacheable for 60 seconds.
Clients should respect these HTTP headers:
Cache-Control: public, max-age=60
Expires: ...
Last-Modified: ...
ETag: ...
Recommended client behavior:
1. Poll no more than once per minute.
2. Respect Retry-After after receiving 429 Too Many Requests.
3. Use HTTP caching with ETag and Last-Modified where possible.
4. Avoid parallel requests from the same IP address or same API key.
5. Do not request the same endpoint repeatedly in short intervals.
Responses may include headers such as:
X-RateLimit-Limit: 1440
X-RateLimit-Remaining: 1439
Retry-After: 60
If the request rate is too high, the server returns:
HTTP/1.1 429 Too Many Requests
{
"ok": false,
"error": "rate limit exceeded",
"message": "Please request CQGMA spots not more than once per minute.",
"retry_after_seconds": 42,
"limit_per_day": 1440,
"remaining_today": 1438,
"source": "CQGMA Spot API",
"website": "https://www.cqgma.org",
"info": "Free GMA and WWFF spot service provided by CQGMA.org. Please avoid excessive polling."
}
{
"ok": false,
"error": "daily limit exceeded",
"message": "Maximum 1440 spot requests per day allowed. This limit includes successful and blocked requests.",
"limit_per_day": 1440,
"reset": "00:00 UTC",
"source": "CQGMA Spot API",
"website": "https://www.cqgma.org",
"info": "Free GMA and WWFF spot service provided by CQGMA.org. Please use one request per minute maximum."
}
The exact JSON fields can change slightly depending on endpoint and spot type.
Common top-level fields:
| Field | Description |
|---|---|
| SOURCE | Source name of the feed |
| RECORDS | Number of returned spot records |
| TIMESTAMP | Unix timestamp of the feed generation |
| RCD | Array containing the spot records |
Common spot fields:
| Field | Description |
|---|---|
| DATE | Spot date |
| TIME | Spot time |
| SPOTTER | Callsign of the spotter |
| ACTIVATOR | Callsign of the activator |
| REF | Reference, for example GMA or WWFF reference |
| NAME | Name of the reference, summit, park or location |
| LAT | Latitude |
| LON | Longitude |
| MODE | Operating mode |
| QRG | Frequency |
| TEXT | Additional spot text or comment |
This example reads the last 10 GMA spots and displays them in a simple HTML table.
<?php
// ------------------------------------------------------------
// PHP example: read JSON feed from CQGMA Spot API
// ------------------------------------------------------------
function GetGMAjson()
{
$url = "https://www.cqgma.org/api/spots/10/";
$stream = stream_context_create(array(
'http' => array(
'timeout' => 30
)
));
$json = file_get_contents($url, false, $stream);
if ($json === false) {
echo "Could not read CQGMA spot feed.";
return;
}
$data = json_decode($json, true);
if (!is_array($data)) {
echo "Invalid JSON received.";
return;
}
echo htmlspecialchars($data["SOURCE"]) . "<br>" . PHP_EOL;
echo htmlspecialchars($data["RECORDS"]) . "<br>" . PHP_EOL;
echo date('d/m/Y H:i:s', $data["TIMESTAMP"]) . "<br>" . PHP_EOL;
echo "<table border='1'>" . PHP_EOL;
foreach ($data["RCD"] as $spot) {
echo "<tr>";
echo "<td>" . htmlspecialchars($spot["DATE"]) . "</td>" . PHP_EOL;
echo "<td>" . htmlspecialchars($spot["TIME"]) . "</td>" . PHP_EOL;
echo "<td>" . htmlspecialchars($spot["SPOTTER"]) . "</td>" . PHP_EOL;
echo "<td>" . htmlspecialchars($spot["ACTIVATOR"]) . "</td>" . PHP_EOL;
echo "<td>" . htmlspecialchars($spot["REF"]) . "</td>" . PHP_EOL;
echo "<td>" . htmlspecialchars($spot["NAME"]) . "</td>" . PHP_EOL;
echo "<td>" . htmlspecialchars($spot["LAT"]) . "</td>" . PHP_EOL;
echo "<td>" . htmlspecialchars($spot["LON"]) . "</td>" . PHP_EOL;
echo "<td>" . htmlspecialchars($spot["MODE"]) . "</td>" . PHP_EOL;
echo "<td>" . htmlspecialchars($spot["QRG"]) . "</td>" . PHP_EOL;
echo "<td>" . htmlspecialchars($spot["TEXT"]) . "</td>" . PHP_EOL;
echo "</tr>" . PHP_EOL;
}
echo "</table>" . PHP_EOL;
}
GetGMAjson();
?>
Please do not disable SSL certificate verification in production clients.
Older example code sometimes used disabled SSL verification for quick testing. For production tools, normal certificate verification should remain enabled.
If your client supports conditional requests, use ETag and Last-Modified to avoid unnecessary downloads.
CQGMA website:
support@cqgma.org