Overview
https://afu.tools/api/v1 returns everything this site shows: band plan with class privileges, repeaters with radius search and CSV export, DOK directory, licence exam dates with feeds, contest calendar, POTA and SOTA references, propagation data and callsign lookups.
The data is collected regularly from official and club sources and served as ready-made snapshots. Which source is refreshed how often is listed below.
For each area there is a real, shortened example response to expand, so you can see the field names before writing your first request. And every response says itself which sources must be credited when passing the data on: Attribution.
Access
Every request needs a key. It makes the rate limit count towards you and not towards your IP address, which others may share. Keys are free with an afu.tools account.
Keys come with an afu.tools account. Sign in, then you can create keys here and in your account, see them and revoke them. The account is free.
Already have a key from before, requested without an account? It stays valid. If you create an account with the same email address, it shows up there by itself. Stuck? info@afu.tools.
Sent as a header or as a bearer token:
$ curl -H "X-API-Key: afu_…" https://afu.tools/api/v1/bands $ curl -H "Authorization: Bearer afu_…" https://afu.tools/api/v1/bands
Without a key: status 401. Exceptions are /api/v1/health and the subscription addresses ending in feed.ics or feed.rss. A calendar app or feed reader can't send a key, and a subscription that only works in a browser wouldn't be one. The server recognises the afu.tools pages and our other own applications by their origin; they don't need one either.
The files under /data/ belong to the site and answer 403 from outside. The same data is available via the endpoints below, filtered and with radius search.
We count which access calls which endpoint how often and from which address. Not the query itself: for a callsign lookup, the record says it was used, not who was searched for. More in the privacy notice.
Ground rules
- Credit the sourceIf you use the data, credit afu.tools and the original source, visible to whoever sees the result. Which ones those are, every response tells you itself: Attribution.
- GET onlyResponses are JSON in UTF-8. Exceptions are the CSV exports and the feeds.
- Rate limiting120 requests per minute and key, 30 for callsign lookups, 10 for CSV exports. Above that you get status 429 with
Retry-After. - Cross-origin allowedThe API can be called directly from a web page.
- Error format
{"error": "…", "status": 404} - Machine-readable/api/v1/openapi.json. There is deliberately no Swagger UI, it loads its scripts from a third-party CDN.
Attribution in every response
Anyone passing data on has to say where it comes from, and for that they need to know who. So it isn't just on a page you'd have to look up: every response carries the attribution. In JSON as the block quellenangabe, for CSV exports and feeds, which aren't JSON, as the header X-Quellen. The line from nennung is the one that must appear with the result.
{
"nennung": "Quellen: afu.tools; Bundesnetzagentur",
"hinweis": "Wer diese Daten weitergibt oder anzeigt, nennt die hier aufgeführten Quellen sichtbar für den, der das Ergebnis sieht: die ursprüngliche Quelle und afu.tools.",
"doku": "https://afu.tools/api#quellenangabe",
"zusammenstellung": {
"name": "afu.tools",
"url": "https://afu.tools",
"lizenz": "Nennung von afu.tools"
},
"datensaetze": [
{
"id": "exams",
"datensatz": "Prüfungstermine",
"wofuer": "Termine mit Umkreissuche, Kalender- und RSS-Abo",
"stand": "2026-09-01T01:25:00Z",
"quellen": [
{
"name": "Bundesnetzagentur",
"url": "https://www.bundesnetzagentur.de/DE/Fachthemen/Telekommunikation/Frequenzen/SpezielleAnwendungen/Amateurfunk/start.html",
"lizenz": "amtliche Veröffentlichung"
}
]
}
]
}
- nennungThe ready-made line to print, sources separated by semicolons. Source names contain commas themselves, hence no commas.
- datensaetzeWhat the response is made of. Per dataset the identifier, what it is used for, the time of the last fetch (
stand,nullfor anything queried live) and the sources with name, address and terms. - zusammenstellungafu.tools itself. The compilation is work and is credited too, even if a response happens to come from no third-party source.
- lizenz nullNo explicit terms known. Then the ground rule applies: credit the source.
- Headers
X-Quellencarries the same line,X-Quellen-Dokupoints here. Both are on every response, CSV and feeds included. - FeedsIn the calendar the attribution is in
X-WR-CALDESC, in RSS in<copyright>.
The full version, i.e. all datasets with terms and freshness plus the mapping from endpoint to dataset, is at /api/v1/quellen. For humans, the same list is on the Sources page.
/api/v1/quellenExample response GET /api/v1/quellen
{
"quellenangabe": { … },
"generated": "2026-09-01T08:01:15Z",
"hinweis": "Wer diese Daten weitergibt oder anzeigt, nennt die hier aufgeführten Quellen sichtbar für den, der das Ergebnis sieht: die ursprüngliche Quelle und afu.tools.",
"zusammenstellung": {
"name": "afu.tools",
"url": "https://afu.tools",
"lizenz": "Nennung von afu.tools"
},
"doku": "https://afu.tools/api#quellenangabe",
"count": 20,
"datensaetze": [
{
"id": "anlaufstellen",
"datensatz": "Anlaufstellen je Betriebsart",
"wofuer": "Digimode- und Anruffrequenzen",
"stand": "2026-09-01T04:07:01Z",
"quellen": [
{
"name": "Vorgabefrequenzen von WSJT-X",
"url": "https://wsjt.sourceforge.io/",
"lizenz": null
},
{
"name": "Vorgabefrequenzen von JS8Call",
"url": "http://js8call.com/",
"lizenz": null
},
{
"name": "Bandplan der IARU Region 1",
"url": "https://www.iaru-r1.org/reference/band-plans/",
"lizenz": null
},
{
"name": "Emergency Centres of Activity, IARU Region 1",
"url": "https://www.iaru-r1.org/on-the-air/emergency-communications/",
"lizenz": null
},
{
"name": "NCDXF/IARU International Beacon Project",
"url": "https://www.ncdxf.org/beacon/",
"lizenz": null
}
]
},
"... 19 weitere"
],
"endpunkte": {
"/": [],
"/anlaufstellen": [
"anlaufstellen"
],
"/ausland": [
"ausland"
],
"...": "47 weitere"
},
"programme": [
{
"name": "Leaflet 1.9.4",
"url": "https://leafletjs.com",
"lizenz": "BSD-2-Clause"
},
"... 1 weitere"
]
}
In the examples further down, this block is shortened to "quellenangabe": { … } and long lists are cut down to one or two entries; the rest appears as "… N weitere" (N more). Otherwise every example would say the same thing three times.
Band plan
/api/v1/bands/api/v1/bands/20m/api/v1/frequency/145.500/api/v1/frequency/14070kHzReturns per band the allocations under Annex 1 of the Amateurfunkverordnung (AFuV, German amateur radio regulations) with status, permitted power per class and the additional provisions, plus the segments of the IARU band plan. /frequency answers the question of what applies at a given frequency.
Example response GET /api/v1/bands/20m
{
"quellenangabe": { … },
"key": "20m",
"label": "20 m",
"from_hz": 14000000,
"to_hz": 14350000,
"allocations": [
{
"from_hz": 14000000,
"to_hz": 14350000,
"status": "P",
"classes": {
"A": {
"value": 750,
"unit": "PEP"
},
"E": null,
"N": null
},
"notes": [
3,
13
]
}
],
"segments": [
{
"from_hz": 14000000,
"to_hz": 14060000,
"max_bandwidth_hz": 200,
"mode": "CW",
"usage": null
},
{
"from_hz": 14060000,
"to_hz": 14350000,
"max_bandwidth_hz": 2700,
"mode": "All modes",
"usage": null
}
],
"activities": [
{
"freq_hz": 14060000,
"description": "CW QRP Centre of Activity"
},
{
"freq_hz": 14070000,
"description": "PSK Centre of Activity"
},
{
"freq_hz": 14074000,
"description": "FT8 Centre of Activity"
},
{
"freq_hz": 14100000,
"description": "International Beacon Project"
},
{
"freq_hz": 14300000,
"description": "Global Emergency Centre of Activity"
}
]
}
Example response GET /api/v1/frequency/145.500
{
"quellenangabe": { … },
"freq_hz": 145500000.0,
"band": "2m",
"label": "2 m",
"allocation": {
"from_hz": 144000000,
"to_hz": 146000000,
"status": "P",
"classes": {
"A": {
"value": 750,
"unit": "PEP"
},
"E": {
"value": 75,
"unit": "PEP"
},
"N": {
"value": 6.1,
"unit": "ERP"
}
},
"notes": [
6,
13
]
},
"segments": [
{
"from_hz": 144100000,
"to_hz": 146000000,
"max_bandwidth_hz": 2700,
"mode": "All modes",
"usage": null
}
],
"notes": {
"6": "Belegte Bandbreite höchstens 40 kHz.",
"13": "Teile des Bereichs sind auch dem Amateurfunkdienst über Satelliten zugewiesen."
},
"source": {
"name": "Anlage 1 AFuV (Nutzungsbedingungen Amateurfunkdienst)",
"url": "https://www.gesetze-im-internet.de/afuv_2005/anlage_1.html",
"retrieved": "2026-08-23"
}
}
Repeaters
/api/v1/repeaters?band=2m&mode=FM&near=JO50HB&km=50/api/v1/repeaters?q=DB0/api/v1/repeaters?source=fm-funknetz.de/api/v1/repeaters?mode=FM-Funknetz&near=JO50HB&km=100/api/v1/repeaters/export.csv?format=chirp&near=JO50HB&km=50/api/v1/repeaters/export.csv?format=rigstudio&band=70cmFilter by band, mode, source and with q across callsign, place, locator, network and remarks. If a station appears in several sources, it is one entry with a list under sources. near takes a locator or lat,lon; with a radius, distance and bearing come back too. The CSV exports use the format of common radio programming software, or they go straight into Rigstudio.
| Field | Meaning |
|---|---|
tone_hz | CTCSS frequency in hertz |
tone_mode |
tone transmit only, tsql also decode, dcs, 1750 |
dcs | DCS code, three digits |
call_1750 | Repeater opens with the 1750 Hz tone burst |
tone_raw | original text from the source, for unclear entries |
Tone details are maintained by the repeater keepers themselves and are patchy accordingly.
Example response GET /api/v1/repeaters?band=2m&near=JO50HB&km=25&limit=2
{
"quellenangabe": { … },
"generated": "2026-09-01T04:07:00Z",
"sources": [
"fm-funknetz.de",
"repeatermap.de"
],
"tone_note": "Tonangaben stammen aus den Freitextfeldern der Quellen und sind von den Betreibern gepflegt. Nicht jeder Eintrag ist aktuell.",
"count": 2,
"repeaters": [
{
"callsign": "DB0NH",
"rx_mhz": 145.3375,
"tx_mhz": 145.3375,
"offset_mhz": 0.0,
"tone_hz": 88.5,
"tone_mode": "tone",
"dcs": null,
"call_1750": false,
"tone_raw": "88.5 Hz",
"mode": "FM",
"netz": "FM-Funknetz",
"band": "2m",
"qth": "Bühl, Ufr., BY",
"locator": "JO50HB",
"keeper": "DL1XXX",
"talkgroups": "96126",
"remarks": null,
"lat": 50.075,
"lon": 10.6663,
"source": "fm-funknetz.de",
"last_seen": "2026-09-01",
"sources": [
"fm-funknetz.de"
],
"distance_km": 3.3,
"bearing_deg": 65
},
"... 1 weitere"
]
}
Example response GET /api/v1/repeaters/export.csv?format=chirp&band=2m&near=JO50HB&km=25
Location,Name,Frequency,Duplex,Offset,Tone,rToneFreq,cToneFreq,DtcsCode,DtcsPolarity,Mode,TStep,Skip,Comment 1,DB0NH,145.337500,,0.000000,Tone,88.5,88.5,023,NN,FM,5.00,,"Bühl, Ufr., BY FM-Funknetz JO50HB" 2,DB0GH,144.850000,,0.000000,Tone,88.5,88.5,023,NN,FM,5.00,,"Gaedheim, BY FM-Funknetz JO50EA"
DOK and local clubs
/api/v1/dok/B37/api/v1/dok/B/api/v1/dok?q=Hassberge/api/v1/sdok?q=AktivitExample response GET /api/v1/dok/B37
{
"quellenangabe": { … },
"type": "ov",
"ov": {
"id": "B37",
"name": "Hassberge",
"link": "https://www.darc.de/der-club/distrikte/b/ortsverbaende/37/",
"chairman_call": "DK5DEN",
"district_id": "B"
},
"district": {
"id": "B",
"name": "Franken",
"link": "https://www.darc.de/der-club/distrikte/b/",
"chairman_call": "DG4NBI"
}
}
Example response GET /api/v1/sdok?q=Aktivit&limit=2
{
"quellenangabe": { … },
"generated": "2026-09-01T01:25:00Z",
"count": 417,
"sdok": [
{
"sdok": "DLFF26",
"reason": "WWFF Aktivitäten",
"callsign": "DP44WCA",
"start": "2026-04-28",
"end": "2026-12-31",
"dok": "U23"
},
{
"sdok": "SOP26",
"reason": "Aktivitätsmonat für Diplom Sea Of Peace",
"callsign": "DL0SOP",
"start": "2026-07-01",
"end": "2026-07-31",
"dok": "V04"
}
]
}
Exam dates
/api/v1/exams?status=verfuegbar/api/v1/exams?near=JO50HB&km=200&klasse=Klasse%20N/api/v1/exams/history/api/v1/exams/feed.rss?near=JO50HB&km=200/api/v1/exams/feed.ics?status=alleThe feeds take the same filters as the list. status=alle includes fully booked dates too, otherwise only free places are returned.
Example response GET /api/v1/exams?near=JO50HB&km=200
{
"quellenangabe": { … },
"generated": "2026-09-01T01:25:00Z",
"source": {
"name": "Bundesnetzagentur, Prüfungstermine Amateurfunk",
"url": "https://www.bundesnetzagentur.de/DE/Fachthemen/Telekommunikation/Frequenzen/SpezielleAnwendungen/Amateurfunk/start.html"
},
"count": 15,
"exams": [
{
"id": 20,
"date": "2026-09-08",
"ort": "Eschborn",
"standort": "Eschborn",
"tageszeit": null,
"pruefung": "Alle Prüfungen",
"code": null,
"status": "ausgebucht",
"first_seen": "2026-06-21 20:57:47",
"available_since": null,
"booked_since": "2026-06-21 20:57:47",
"stand": "28. August 2026",
"lat": 50.1433,
"lon": 8.5706,
"distance_km": 147
},
{
"id": 84,
"date": "2026-09-08",
"ort": "Nürnberg",
"standort": "Nürnberg",
"tageszeit": null,
"pruefung": "Alle Prüfungen",
"code": null,
"status": "ausgebucht",
"first_seen": "2026-08-19 06:00:00",
"available_since": null,
"booked_since": "2026-08-19 06:00:00",
"stand": "28. August 2026",
"lat": 49.4521,
"lon": 11.0767,
"distance_km": 75
},
"... 13 weitere"
]
}
Contest calendar
/api/v1/contests?days=365&klasse=N/api/v1/contests/feed.ics?klasse=NThe dates are calculated from the published contest rules; each entry names the rule and links the rules. bands are the bands in the rules, klassen says per German licence class (N, E, A) which of them it may use according to the band plan. A class without a band is missing there. With klasse=N (or E, A), list and calendar subscription keep only the contests where this class has at least one band. Dates only listed in the DARC contest calendar carry "quelle": "darc"; the regular activity evenings among them ("art": "aktivitaet", such as CWT, NRAU or RSGB activity contests) only come with aktivitaeten=1, in the list as in the subscription.
Example response GET /api/v1/contests?days=30
{
"quellenangabe": { … },
"generated": "2026-09-01T04:07:01Z",
"note": "Die Termine sind aus den Wiederholungsregeln der Ausschreibungen berechnet und gegen die Termine des Jahres 2026 gegengeprüft. Einzelne Ausgaben werden gelegentlich verschoben, verbindlich ist die Ausschreibung des Veranstalters. Wo keine Uhrzeit steht, war sie nicht gesichert, sie steht dann in der Ausschreibung.",
"count": 7,
"contests": [
{
"key": "aa-ssb",
"name": "All Asian DX Contest, SSB",
"mode": "SSB",
"rule": "erstes volles September-Wochenende",
"url": "https://www.jarl.org/English/4_Library/A-4-3_Contests/2023AADX_rule.htm",
"date": "2026-09-05",
"start": "2026-09-05T00:00:00Z",
"end": "2026-09-07T00:00:00Z",
"allday": false
},
{
"key": "iaru-fd-ssb",
"name": "IARU Region 1 Fieldday, SSB",
"mode": "SSB",
"rule": "erstes volles September-Wochenende",
"url": "https://www.darc.de/der-club/referate/conteste/",
"date": "2026-09-05",
"start": "2026-09-05T13:00:00Z",
"end": "2026-09-06T12:59:00Z",
"allday": false
},
"... 5 weitere"
]
}
DX calendar
/api/v1/dx?days=90&art=aktivitaet/api/v1/dx?cont=OC,AS&dxcc=3B7,VP8/api/v1/dx?iota=OC-008&belegt=2/api/v1/dx/feed.ics?cont=OC&alarm=3/api/v1/dx/feed.rss?dxcc=3YAnnounced DX activities, merged from three public calendars. Only the date is taken over; country, continent, CQ and ITU zone are derived from the callsign. The description of the activity stays with the source, every entry links there.
Filters: cont (continent, two letters), dxcc (prefix of the entity), iota, call, entity, cq, itu, art (aktivitaet up to 90 days or dauer), days, q, belegt (requires a minimum number of sources naming the date), beleg (see below), stufe (rarity of the entity: sehr_selten, selten, ungewoehnlich, haeufig) and typ (dxpedition, sonder for special callsigns or sonstige). Several values per filter separated by commas. alarm sets a reminder in the calendar subscription that many days before the start.
Calendar and feed addresses need no access key: a calendar app can't send one. Everything else follows the ground rules above.
Analyses across the archive
/api/v1/dx/bestand/api/v1/dx/statistik?sortierung=selten&bis=2025/api/v1/dx/verlauf?cont=OC&von=2015/api/v1/dx/entitaet/3B6Announced activities are recorded, and the NG3K yearly archive back to 1996 has been imported. That answers what the current list alone can't: how often an entity was announced at all, when last and at what intervals.
statistik groups per DXCC entity and gives count, years, first and last announcement, total and average duration and luecke_tage, the mean gap between two announcements. Sort with sortierung (anzahl, selten, zuletzt, laenge, name), filter as above with cont, dxcc, iota, art plus von and bis as years. verlauf returns the same selection per year, entitaet all individual dates of one entity.
Did it really happen?
No announcement source knows that. So every activity gets an evidence level in the field beleg, built from three free sources: the user list of Club Log (first and last QSO per log), the activity list of LoTW and the daily archives of the Reverse Beacon Network. You can filter by it wherever the other filters work, feeds and calendars included.
| Value | Meaning |
|---|---|
| log | Log uploaded to Club Log, the QSO period matches the announcement. Strongest evidence. |
| gehoert | Verifiably heard during the announced period. Accurate to the day, but only covers CW and RTTY as long as the evidence comes from the RBN archive. |
| ruf_bekannt | The callsign is known to Club Log or LoTW, but there is no log for this period. That is no evidence for this activity, just the information that the callsign has been on the air before. Typical for permanent stations whose combined log runs for years. |
| keine_spur | Nothing found. That is no proof to the contrary: anyone who only QSLs direct and uploads nowhere leaves none of these traces. |
| offen | Not yet assessable: in the future, still running, or ended less than 60 days ago. Something that hasn't happened yet can't have a log. Positive evidence still counts immediately, so a running activity can already be gehoert (heard). |
| unpruefbar | The announcement doesn't name a real callsign, just a placeholder. Without a callsign there's nothing to look up. |
What the numbers are and what they aren't: they count announcements, not confirmed activities. None of the sources records whether an expedition really took place. Also listed is what is interesting for DXers: Estonia appearing only once doesn't mean nobody operates there, but that it was rarely the destination of an announced activity. The year 2022 is missing at the source; /dx/bestand names such gaps explicitly.
Example response GET /api/v1/dx?cont=OC&limit=2
{
"quellenangabe": { … },
"generated": "2026-09-01T03:40:05Z",
"note": "Angekündigt ist nicht zugesagt: Termine verschieben sich, maßgeblich ist die Ankündigung der Expedition selbst.",
"quellen": [
{
"name": "ADXO (NG3K, Bill Feidt)",
"url": "https://www.ng3k.com/Misc/adxo.html",
"abruf": "https://www.ng3k.com/Misc/adxo.html",
"key": "ng3k"
},
{
"name": "DX Calendar (VA3RJ)",
"url": "https://www.qsl.net/va3rj/dx_cal.html",
"abruf": "https://www.qsl.net/va3rj/dx_cal.html",
"key": "va3rj"
},
"... 1 weitere"
],
"dxcc_quelle": {
"name": "BIG CTY (AD1C, Jim Reisert)",
"url": "https://www.country-files.com/big-cty/",
"lizenz": "MIT"
},
"kontinente": {
"AF": "Afrika",
"AN": "Antarktis",
"...": "5 weitere"
},
"count": 31,
"dxpeditions": [
{
"call": "V73HW",
"start": "2025-03-15",
"end": "2027-03-15",
"tage": 731,
"iota": "OC-028",
"qsl": null,
"unsicher": true,
"quellen": [
{
"key": "va3rj",
"name": "DX Calendar (VA3RJ)",
"url": "https://www.qsl.net/va3rj/dx_cal.html"
}
],
"art": "dauer",
"entity": "Marshall Islands",
"dxcc": "V7",
"cont": "OC",
"cq": 31,
"itu": 65,
"lat": 9.08,
"lon": 167.33,
"beleg": "offen",
"beleg_detail": "läuft noch",
"stufe": "ungewoehnlich",
"stufe_grund": "GDXF Most Wanted Platz 53, 62.7 % der Teilnehmer fehlt das Gebiet noch",
"aktive_rufzeichen": 54,
"tage_pro_jahr": 17.28,
"gehoert_tage": 0,
"beobachtet_tage": 2,
"gdxf_rang": 53,
"gdxf_prozent": 62.7,
"zuletzt_angekuendigt": "2026-05-23",
"typ": "dxpedition"
},
"... 1 weitere"
]
}
Example response GET /api/v1/dx/statistik?sortierung=selten&limit=2
{
"quellenangabe": { … },
"hinweis": "Gezählt sind Ankündigungen, keine bestätigten Aktivitäten. Die Quellen führen auf, was für DX-Betrieb angekündigt wurde; ein Land, das selten auftaucht, ist deshalb selten Reiseziel und nicht unbedingt selten in der Luft.",
"gesamt": {
"n": 12860,
"entitaeten": 343,
"von": 1996,
"bis": 2027,
"belegt": 3663
},
"count": 2,
"entitaeten": [
{
"dxcc": "ES",
"entitaet": "Estonia",
"kontinent": "EU",
"n": 1,
"jahre": 1,
"erst": "1997-06-26",
"letzt": "1997-06-26",
"tage_gesamt": 5,
"tage_schnitt": 5.0,
"belegt": 0,
"luecke_tage": null
},
{
"dxcc": "CX",
"entitaet": "Uruguay",
"kontinent": "SA",
"n": 1,
"jahre": 1,
"erst": "1999-11-14",
"letzt": "1999-11-14",
"tage_gesamt": 10,
"tage_schnitt": 10.0,
"belegt": 0,
"luecke_tage": null
}
]
}
Example response GET /api/v1/dx/bestand
{
"quellenangabe": { … },
"hinweis": "Gezählt sind Ankündigungen, keine bestätigten Aktivitäten. Die Quellen führen auf, was für DX-Betrieb angekündigt wurde; ein Land, das selten auftaucht, ist deshalb selten Reiseziel und nicht unbedingt selten in der Luft.",
"aktivitaeten": 12883,
"von": "1996-06-16",
"bis": "2028-01-01",
"entitaeten": 343,
"jahre": 31,
"fehlende_jahrgaenge": [
2022
],
"quellen": [
{
"quellen": "ng3k-archiv",
"n": 12555
},
{
"quellen": "va3rj",
"n": 223
},
"... 6 weitere"
],
"belege": {
"unbewertet": 2,
"gehoert": 1856,
"keine_spur": 5172,
"log": 1807,
"offen": 272,
"ruf_bekannt": 1769,
"unpruefbar": 2005
},
"hoerbelege": [
{
"quelle": "cluster",
"tage": 43,
"rufzeichen": 36
},
{
"quelle": "dxcache",
"tage": 43,
"rufzeichen": 36
},
"... 1 weitere"
],
"beleg_stufen": {
"log": "Log bei Club Log hochgeladen, QSO-Zeitraum überlappt die Ankündigung",
"gehoert": "im angekündigten Zeitraum nachweislich gehört (RBN oder Cluster)",
"...": "4 weitere"
}
}
/dx/spots also filters with quelle (cluster, dxcache, rbn, combinable with commas). An RBN spot also carries snr_db (signal-to-noise ratio) and wpm (speed, for RTTY/PSK the BPS equivalent); for a cluster spot both are null. View with filters, distance and bearing at /rbn, as on the DX cluster.
Example response GET /api/v1/dx/spots?minuten=240&limit=2
{
"quellenangabe": { … },
"count": 2,
"fenster_minuten": 240,
"bestand": {
"n": 14944,
"von": "2026-08-31T07:41:33Z",
"bis": "2026-09-01T08:02:12Z"
},
"stufen": {
"sehr_selten": "sehr selten, kaum eine Funkstelle vor Ort",
"selten": "selten, nur wenige Funkstellen vor Ort",
"ungewoehnlich": "ungewöhnlich, überschaubar viele Funkstellen",
"haeufig": "häufig"
},
"hinweis_modus": "`modus` steht so im Spot. `modus_vermutet` ist aus der Frequenz abgeleitet und nur eine Schätzung.",
"spots": [
{
"zeit": "2026-09-01T08:02:12Z",
"call": "HB9XXX",
"freq_khz": 7075.0,
"band": "40m",
"modus": null,
"spotter": "DL1XXX",
"bemerkung": "POTA CH-0219 tnx p2p DE-0531",
"quelle": "cluster",
"dxcc": "HB",
"entitaet": "Switzerland",
"kontinent": "EU",
"cq": 14,
"itu": 28,
"lat": 46.87,
"lon": 8.12,
"snr_db": null,
"wpm": null,
"stufe": "haeufig",
"stufe_grund": "nicht in den GDXF-Top-150; Betrieb vor Ort; Mitschnitt läuft erst 2 Tage und zählt noch nicht mit",
"gdxf_rang": null,
"gdxf_prozent": null,
"aktive_rufzeichen": 1741,
"tage_pro_jahr": 0.55,
"gehoert_tage": 1,
"beobachtet_tage": 2,
"zuletzt_angekuendigt": "2001-04-24",
"ank_start": null,
"ank_ende": null,
"ank_iota": null,
"beleg": null,
"modus_vermutet": "FT8"
},
"... 1 weitere"
]
}
Who hears me: Reverse Beacon Network and PSK Reporter
/api/v1/dx/gehoert/DL1ABC?minuten=1440/api/v1/dx/gehoert/DL1ABC?quelle=psk&modus=FT8&band=20m/api/v1/dx/rbn/DL1ABC/api/v1/dx/rbn/DL1ABC?minuten=1440&band=20m,40m&modus=CWAll RBN reports for a callsign in the period (minuten, 5 to 2880, default 60), also with a suffix such as /P. skimmer summarises per skimmer: number of reports, best and average signal, bands, first and last report, plus the location from the RBN skimmer list (locator, lat, lon). If a skimmer isn't in the list, genau is false and the location is the centre of its country. je_band counts without the band filter, spots are the latest individual reports (limit, at most 1000). Reports are kept for two days. View with map at /rbn.
/dx/gehoert combines three sources (quelle, comma-separated, default all): rbn (RBN, CW and RTTY), rbndigi (RBN, FT8 and FT4) and psk (PSK Reporter). Instead of skimmer the list is called empfaenger, per receiver with quellen, modi and location (for PSK Reporter from the receiver's locator). psk says where the PSK part comes from: mitschnitt for callsigns from DE, AT, CH, LI and LU (our own capture, 48 hours), abfrage for all others (queried from PSK Reporter, 24 hours, up to five minutes old). The dB values of CW and FT8 are not comparable, they refer to different bandwidths. wolke summarises per receiver, band and mode, as a list [Empfänger, Band, Betriebsart, bestes dB, mittleres dB, Meldungen] (receiver, band, mode, best dB, average dB, reports), at most 5000 rows; /rbn uses it to plot signal against distance. With stumm=1 you also get nicht_gehoert: the receivers that reported others on the same bands and modes in the period but not this callsign, aggregated to 0.2 degrees as [lat, lon, Zahl, genau, digital] (digital 0: CW and RTTY). Counted to the hour; for PSK Reporter our own capture only knows receivers that hear stations from DACH.
Operating abroad
/api/v1/ausland/api/v1/ausland?klasse=e&moeglich=true/api/v1/ausland?land=spanien/api/v1/ausland?region=2/api/v1/ausland?rufzeichen=HB9XYZrufzeichen resolves a heard callsign to exactly one country via the ITU callsign series and returns the series too. A fixed pair beats a single character, otherwise K3… would land at every K country instead of the USA. If no series is found, you get 404.
All countries of the world with the question of whether a German class A, E or N licence allows operating there. With moeglich=true a guest licence counts as possible, it just has to be applied for in advance. Each entry also lists the ITU region, the ITU callsign series, the time zones and the centre of the country, plus the addresses of the national society and the responsible administration. Where each of these details comes from is in quellen and sachquellen of the response.
Example response GET /api/v1/ausland?rufzeichen=HB9XYZ
{
"quellenangabe": { … },
"generated": "2026-09-01T04:07:01Z",
"rufzeichen": "HB9XYZ",
"serie": "HB",
"quellen": {
"cept": {
"name": "CEPT-Empfehlung T/R 61-01",
"ausgabe": "Ausgabe 18. Oktober 2024",
"url": "https://docdb.cept.org/Docs/doc98/official/pdf/TR6101.PDF"
},
"umsetzung_a": {
"name": "ECO, Umsetzungsstand T/R 61-01",
"ausgabe": "abgerufen am 24.08.2026",
"url": "https://docdb.cept.org/implementation/925"
},
"...": "3 weitere"
},
"sachquellen": [
{
"feld": "Mittelpunkt, Entfernung, Peilung",
"name": "Google Public Data, countries.csv (dspl)",
"url": "https://github.com/google/dspl/blob/master/samples/google/canonical/countries.csv"
},
{
"feld": "Rufzeichenserie",
"name": "ITU, Anhang 42 der Vollzugsordnung für den Funkdienst, über die Wikipedia-Aufstellung „ITU prefix“",
"url": "https://en.wikipedia.org/wiki/ITU_prefix"
},
"... 2 weitere"
],
"count": 1,
"laender": [
{
"code": "CH",
"land": "Schweiz",
"a": "cept",
"e": "ja",
"n": "nein",
"praefix_cept": "HB9",
"hinweis": "Klasse A laut CEPT-Datenbank umgesetzt, Stand 01.09.2009. Klasse E laut CEPT-Datenbank umgesetzt, Stand 01.09.2009.",
"links": [
{
"titel": "Union Schweizerischer Kurzwellen-Amateure [USKA]",
"url": "http://www.uska.ch"
}
],
"koord": [
46.8182,
8.2275
],
"itu_region": 1,
"praefixe": [
"HB",
"HE"
],
"zonen": [
"Europe/Zurich"
]
}
]
}
Propagation
/api/v1/funkwetter/api/v1/funkwetter?kurz=1/api/v1/funkwetter/offen?von=dl/api/v1/funkwetter/sonde/JR055What the /funkwetter page shows, recalculated every 15 minutes: kopf with SFI, sunspots, A, Kp, X-ray class, solar wind, Bz, MUF and foEs over DL; lage as one sentence; baender per HF band with tag, nacht and jetzt (good, fair, poor, closed); vhf with sporadic E per band and aurora; karte with the MUF grid (4°, MHz × 10, centre of the first cell in lat0/lon0), the measurement density per cell (0 to 9) and the contour lines as GeoJSON; sonden with the last reliable value of each ionosonde and its operator; plus the series of Kp, X-ray, solar wind, D-RAP and aurora. verlauf is the hourly state for the last tage days (default 30). With kurz=1 only header, summary and bands.
/funkwetter/offen counts how many RBN and PSK Reporter receivers have heard stations from DL (von=dl) or Europe (von=eu) in the last 30 minutes, per band and continent. /funkwetter/sonde/{URSI} returns the values of one ionosonde over 48 hours as [t, CS, foF2, foEs, MUF(3000)].
If you pass on the ionosonde values, credit GIRO (Reinisch and Galkin 2011) and the operator of the ionosonde; the values are under CC BY-NC-SA 4.0, so not for commercial use. The embeddable images (/funkwetter/bild/baender.png, muf.png, banner.png, also as .svg, with ?thema=dunkel) need no access key.
Example response GET /api/v1/funkwetter/offen?von=dl (shortened)
{
"quellenangabe": { … },
"baender": ["160m", "80m", "…", "2m"],
"kontinente": ["EU", "NA", "SA", "AS", "AF", "OC"],
"matrix": {
"20m": {
"NA": { "empf": 41, "meldungen": 512, "snr": 31 },
"AS": { "empf": 12, "meldungen": 64, "snr": 22 }
}
},
"sender": 119,
"minuten": 30,
"von": "dl",
"stand": "2026-10-07T11:00:00Z"
}
Portable
/api/v1/spots?near=JO50HB&km=25/api/v1/spots?near=50.07,10.67&km=50&type=sota/api/v1/solarExample response GET /api/v1/spots?near=JO50HB&km=25&limit=2
{
"quellenangabe": { … },
"generated": "2026-09-01T04:07:01Z",
"count": 10,
"spots": [
{
"type": "pota",
"ref": "DE-0581",
"name": "Hohe Wann Nature Reserve",
"lat": 50.0366,
"lon": 10.5747,
"distance_km": 4.6,
"bearing_deg": 231
},
"... 1 weitere"
]
}
Example response GET /api/v1/solar
{
"quellenangabe": { … },
"generated": "2026-10-07T11:00:00Z",
"source": {
"name": "afu.tools Funkwetter (NOAA SWPC, GFZ Potsdam, GIRO)",
"url": "https://afu.tools/funkwetter"
},
"data": {
"source": "afu.tools",
"updated": "07 Oct 2026 1100 GMT",
"solarflux": "113",
"aindex": "6",
"kindex": "0",
"kindexnt": "",
"xray": "B8.6",
"sunspots": "77",
"aurora": "30",
"solarwind": "357.0",
"magneticfield": "0.6",
"geomagfield": "sehr ruhig",
"signalnoise": "S0-S1",
"fof2": "7.075",
"muffactor": "",
"muf": "25.4"
},
"hf": [
{
"band": "80m-40m",
"time": "day",
"condition": "Fair"
},
{
"band": "30m-20m",
"time": "day",
"condition": "Good"
},
{
"band": "17m-15m",
"time": "day",
"condition": "Fair"
},
{
"band": "12m-10m",
"time": "day",
"condition": "Poor"
},
{
"band": "80m-40m",
"time": "night",
"condition": "Good"
},
{
"band": "30m-20m",
"time": "night",
"condition": "Poor"
},
{
"band": "17m-15m",
"time": "night",
"condition": "Poor"
},
{
"band": "12m-10m",
"time": "night",
"condition": "Poor"
}
],
"vhf": [
{
"name": "vhf-aurora",
"location": "northern_hemi",
"value": "High LAT AUR"
},
{
"name": "E-Skip",
"location": "europe",
"value": "Band Closed"
},
{
"name": "E-Skip",
"location": "north_america",
"value": "Band Closed"
},
{
"name": "E-Skip",
"location": "europe_6m",
"value": "Band Closed"
},
{
"name": "E-Skip",
"location": "europe_4m",
"value": "Band Closed"
}
]
}
Calling frequencies
/api/v1/anlaufstellen/api/v1/anlaufstellen?band=20m/api/v1/anlaufstellen?art=digitalThe established meeting points per mode: FT8, FT4, JS8, WSPR, PSK31, RTTY, SSTV, the calling frequencies, APRS, DAPNET, the emergency communication frequencies and the IBP beacons. Given is the dial frequency in upper sideband. With band you get the view of one band, sorted by frequency. Only what is also inside the band in Germany is included.
Example response GET /api/v1/anlaufstellen?band=20m
{
"quellenangabe": { … },
"generated": "2026-09-01T04:07:01Z",
"band": "20m",
"hinweis": "Einstellfrequenz (Dial) in oberem Seitenband. Eingebürgerte Treffpunkte, keine Vorschrift, verbindlich ist der Bandplan.",
"quellen": [
{
"feld": "FT8, FT4, WSPR",
"name": "Vorgabefrequenzen von WSJT-X",
"url": "https://wsjt.sourceforge.io/"
},
{
"feld": "JS8",
"name": "Vorgabefrequenzen von JS8Call",
"url": "http://js8call.com/"
},
"... 3 weitere"
],
"anlaufstellen": [
{
"key": "cw",
"name": "CW-QRP",
"art": "telegrafie",
"wert": 14.06
},
{
"key": "psk",
"name": "PSK31",
"art": "digital",
"wert": 14.07
},
{
"key": "ft8",
"name": "FT8",
"art": "digital",
"wert": 14.074
},
"... 7 weitere"
]
}
Prefix and DXCC
/api/v1/dxcc/VK6/api/v1/dxcc/9M6%2FLA6VM/api/v1/dxcc?cont=OC/api/v1/dxcc?q=islandEntity, continent, CQ and ITU zone and the centre point for a callsign or prefix. rule says how it was mapped: ausnahme for an entry in the exception list, praefix for the prefix rule. It is based on the BIG CTY country file (MIT licence), the same one the DX calendar and cluster use.
Example response GET /api/v1/dxcc/VK6
{
"quellenangabe": { … },
"query": "VK6",
"match": "VK6",
"rule": "praefix",
"entity": {
"name": "Australia",
"praefix": "VK",
"kontinent": "OC",
"cq": 30,
"itu": 59,
"lat": -23.7,
"lon": 132.33
},
"continent": "Ozeanien",
"prefixes": [
"AX",
"AX4",
"AX6",
"AX8",
"... 16 weitere"
],
"source": {
"name": "BIG CTY (AD1C, Jim Reisert)",
"url": "https://www.country-files.com/big-cty/",
"lizenz": "MIT"
}
}
Satellites
/api/v1/tle/api/v1/tle?funk=trueOrbital data of the amateur radio satellites as CelesTrak lists them, plus frequencies and modes for the known satellites. epoche gives the time of the orbital elements, which determines the accuracy of every prediction. The passes themselves are calculated by the satellite page in the browser; your location doesn't go over the wire for that.
Example response GET /api/v1/tle?funk=true
{
"quellenangabe": { … },
"generated": "2026-09-01T02:15:02Z",
"quelle": {
"name": "CelesTrak",
"url": "https://celestrak.org/",
"lizenz": "frei nutzbar, Nennung erbeten"
},
"status_quelle": {
"name": "AMSAT-NA, Satellitenstatus",
"url": "https://www.amsat.org/status/"
},
"hinweis": "Bahndaten altern: nach einer Woche liegt die Vorhersage schon Minuten daneben. Betriebszustand der Satelliten steht bei AMSAT.",
"count": 8,
"satelliten": [
{
"norad": 7530,
"name": "OSCAR 7",
"kuerzel": "AO-7",
"epoche": "2026-08-31T13:34:27Z",
"tle1": "1 07530U 74089B 26243.56559926 -.00000046 00000+0 60356-6 0 9993",
"tle2": "2 07530 101.9921 257.6005 0012190 349.2633 134.3126 12.53699388369965",
"funk": [
{
"art": "Mode A, linear",
"up_von": 145.85,
"up_bis": 145.95,
"down_von": 29.4,
"down_bis": 29.5
},
{
"art": "Mode B, linear invertierend",
"up_von": 432.125,
"up_bis": 432.175,
"down_von": 145.925,
"down_bis": 145.975
}
],
"hinweis": "Ältester noch benutzter Amateurfunksatellit. Er läuft ohne Akku allein am Sonnenlicht und wechselt die Betriebsart selbsttätig.",
"geostationaer": false
},
"... 7 weitere"
]
}
Line of sight
/api/v1/sichtlinie?von=JO50HB&nach=JO50WB/api/v1/sichtlinie?von=50.07,10.67&nach=JO60&hoehe_von=12&hoehe_nach=40&mhz=439Terrain profile between two points with a verdict: frei (clear), knapp (marginal) or verdeckt (blocked). It uses the German federal elevation model (DGM200, 200 m grid), the effective earth radius (factor 4/3) and the first Fresnel zone; anteil_fresnel gives how much of it stays clear, zusaetzliche_hoehe_m how much height is missing at the starting point. Covers Germany, at most 400 km.
Example response GET /api/v1/sichtlinie?von=JO50HB&nach=JO50WB&hoehe_von=10&hoehe_nach=30
{
"quellenangabe": { … },
"von": {
"lat": 50.0625,
"lon": 10.625,
"locator": "JO50hb"
},
"nach": {
"lat": 50.0625,
"lon": 11.875,
"locator": "JO50wb"
},
"moeglich": true,
"urteil": "verdeckt",
"text": "Das Gelände steht in der Sichtlinie. Ohne Umweg über ein Relais oder mehr Höhe geht da nichts.",
"strecke_km": 89.23,
"anteil_fresnel": -1.0,
"engster_punkt": {
"km": 88.529,
"hoehe": 890.6,
"sicht": 782.1,
"luft": -108.5,
"fresnel": 37.8
},
"hoehe_start_m": 412.2,
"hoehe_ziel_m": 758.6,
"antenne_start_m": 10.0,
"antenne_ziel_m": 30.0,
"mhz": 145.0,
"zusaetzliche_hoehe_m": 13181.4,
"ohne_daten_punkte": 0,
"k_faktor": 1.3333333333333333,
"profil": [
{
"km": 0.0,
"hoehe": 412.2,
"sicht": 422.2,
"luft": 10.0,
"fresnel": 0.0
},
{
"km": 0.349,
"hoehe": 395.1,
"sicht": 421.8,
"luft": 26.7,
"fresnel": 26.8
},
"... 255 weitere"
],
"quelle": {
"name": "DGM200, Bundesamt für Kartographie und Geodäsie",
"url": "https://gdz.bkg.bund.de/index.php/default/digitale-geodaten/digitale-gelandemodelle/digitales-gelandemodell-gitterweite-200-m-dgm200.html",
"lizenz": "GeoNutzV, Quellenvermerk © GeoBasis-DE / BKG",
"vermerk": "© GeoBasis-DE / BKG",
"stand": "Stand 31.12.2019"
}
}
Callsigns
/api/v1/callsign/DL1XXX/api/v1/callsigns?prefix=DL1/api/v1/callsign/frei?muster=DL1A??/api/v1/callsign/frei/plan?suffix=MH&zweck=PZ&klasse=E/api/v1/rufzeichenplan/api/v1/rufzeichenplan/einordnen?call=DO0ABC/api/v1/qth?rufe=DL1ABC,K1ABCReturned are callsign, holder, class, the place named in the official list and the sources. The API doesn't give out addresses, coordinates or locators from the callsign list. There is no search by name and no full dump.
qth gives, for up to 100 callsigns, the locator the station itself reported to PSK Reporter or is listed with in the RBN skimmer list, with source (psk, rbn) and age in days; when signed in, also the one from your last QSO with it (log, wavelog). The FT8, FT4 and JS8 pages use it for distance and the “New Grid” colour.
callsign/frei answers the question before applying for a vanity callsign: which ones matching a pattern are not in the list? ? stands for a letter or digit, # for a digit only. Only German callsigns are checked (DA to DR, one digit, one to three letters): D??MH gives DA0MH to DR9MH. The beginning must be fixed, at most 1296 possibilities. Only the unlisted callsigns and a few numbers come back, who holds what is not listed. And unlisted doesn't mean available: returned callsigns stay blocked for a while, and allocation is on application.
rufzeichenplan returns the callsign plan of the Bundesnetzagentur (BNetzA, German regulator; extract from Vfg. 15/2025, valid from 1 Apr 2025) as JSON: per series (DA0 to DR9 without DE and DI) and suffix type (lang: 2 or 3 letters, ein: 1 letter, sonder: 4 to 7 characters) the purposes (PZ, KS, RL, FB, SZ, AB, KSB, KSO), the purposes being phased out, the class and whether the series is still newly issued today (neu), plus occasions, time limits, additions, invalid suffixes and under bestand the number of callsigns per series, suffix length and list from the latest callsign list. rufzeichenplan/einordnen classifies a callsign, without holder: series, purpose, class, notes, errors (not in the plan, invalid suffix, wrong order of additions such as /pT), also short-term licences (DL/PA3XYZ) and direction-finding beacon identifiers.
callsign/frei/plan checks a desired suffix in all series matching zweck (PZ, KS, SONDER, RL, SZ, KSB, KSO), klasse (A, E, N) and optionally laenge (1, 2, 3, 4-7); with auslaufend=true and exterritorial=true those series too. As with callsign/frei, only the unlisted callsigns and numbers come back; suffixes containing distress or Q groups (no. 7 of the plan) aren't checked at all.
Example response GET /api/v1/callsign/DL1XXX
{
"quellenangabe": { … },
"callsign": "DL1XXX",
"scope": "public",
"operator": {
"callsign": "DL1XXX",
"personalCallSign": null,
"license": "A",
"owner": "Vorname Nachname",
"residence": "Musterstadt",
"sources": [
"bnetza-pdf"
],
"lastFetched": "2026-08-27T04:00:46",
"bnetzaListNumber": 12345
},
"sdok": null,
"source": {
"name": "Bundesnetzagentur, Amateurfunk-Rufzeichenliste",
"note": "Anschrift, Koordinaten und Locator sind nicht oeffentlich."
}
}
Example response GET /api/v1/callsign/frei?muster=D??MH
{
"quellenangabe": { … },
"muster": "D??MH",
"geprueft": 180,
"vergeben": 93,
"frueher_vergeben": 14,
"frei": [
"DA0MH",
"DA2MH",
"DA3MH",
"DA4MH",
"... 69 weitere"
],
"count": 73,
"hinweis": "Nicht gelistet heißt nicht zu haben: Zurückgegebene Rufzeichen bleiben eine Zeit lang gesperrt, und über die Zuteilung entscheidet allein die Bundesnetzagentur.",
"source": {
"name": "Amateurfunk-Rufzeichenliste der Bundesnetzagentur",
"url": "https://www.bundesnetzagentur.de/DE/Fachthemen/Telekommunikation/Frequenzen/SpezielleAnwendungen/Amateurfunk/start.html"
}
}
Places and local clubs
/api/v1/ort?q=Haßfurt/api/v1/ort?q=97437/api/v1/ort?q=DM/BM-002/api/v1/ort?q=B/DL-0001/api/v1/ov?near=JO50hbort turns a place name or postcode into coordinates and locator, always exactly one result. If the name exists more than once, the bigger place wins, and the response says which one via label. A reference of a programme that means a point in the terrain returns that point: SOTA summits (DM/BM-002), bunkers (BOTA, B/DL-0001) and castles (WCA DL-00001 or COTA BBN-001), with programm and referenz in normal form. The server asks SOTA for summits outside the German-speaking area and neighbouring countries; bunkers and castles only as far as the xOTA map lists them. Parks (POTA, WWFF) are areas and therefore not a location. The same applies wherever a parameter takes a location (near and co.).
ov names the nearest local club to a location. near takes a locator, coordinates or a place name. That is no official jurisdiction: local clubs have no borders, a DOK is an identifier and not an area.
Example response GET /api/v1/ort?q=Haßfurt
{
"quellenangabe": { … },
"name": "Haßfurt",
"land": "Bayern",
"label": "Haßfurt (Bayern)",
"lat": 50.0352,
"lon": 10.5156,
"locator": "JO50ga",
"einwohner": 13562,
"quelle": {
"name": "GeoNames, Ortsverzeichnis und Postleitzahlen Deutschland",
"url": "https://www.geonames.org/",
"lizenz": "CC BY 4.0"
}
}
Example response GET /api/v1/ov?near=JO50hb
{
"quellenangabe": { … },
"dok": "B37",
"name": "Hassberge",
"ort": "Hassberge",
"plz": "96126",
"distanz_km": 15.0,
"distrikt": "B",
"link": "https://www.darc.de/der-club/distrikte/b/ortsverbaende/37/",
"hinweis": "Der nächstgelegene Ortsverband, keine amtliche Zuständigkeit. Ortsverbände haben keine Grenzen.",
"quelle": {
"name": "DARC, Ortsverbandssuche auf darc.de",
"url": "https://www.darc.de/home/",
"hinweis": "Postleitzahl je Ortsverband aus der Suche, Koordinaten daraus über GeoNames"
}
}
Calculations and status
/api/v1/locator?lat=50.07&lon=10.67/api/v1/locator?locator=JO50HB/api/v1/distance?from=JO50HB&to=JN47/api/v1/health/api/v1/statsExample response GET /api/v1/locator?lat=50.07&lon=10.67
{
"quellenangabe": { … },
"lat": 50.07,
"lon": 10.67,
"locator": "JO50ib",
"locator4": "JO50"
}
Example response GET /api/v1/distance?from=JO50HB&to=JN47
{
"quellenangabe": { … },
"from": {
"lat": 50.0625,
"lon": 10.625,
"locator": "JO50hb"
},
"to": {
"lat": 47.5,
"lon": 9.0,
"locator": "JN47mm"
},
"distance_km": 308.8,
"bearing_deg": 203.3,
"bearing_back_deg": 22.1
}
Example response GET /api/v1/health
{
"quellenangabe": { … },
"ok": true,
"snapshots": "2026-09-01T08:01:15Z",
"last_run": [
"quellen"
],
"tasks": {
"bands": "2026-09-01T04:07:01Z",
"repeaters": "2026-09-01T04:07:01Z",
"stats": "2026-09-01T04:07:01Z",
"...": "18 weitere"
}
}
Example response GET /api/v1/stats
{
"quellenangabe": { … },
"generated": "2026-09-01T04:07:01Z",
"counts": {
"operators": 70098,
"ovs": 1019,
"sdok": 6243,
"exams_upcoming": 49,
"exams_free": 26,
"repeaters": 2626
},
"licences": {
"A": 58684,
"E": 10219,
"N": 1130
},
"sync": [
{
"key": "bnetza-pdf:lastImportedAt",
"value": "2026-08-27T04:00:53.987Z",
"updatedAt": "2026-08-27 04:00:53.989532"
},
{
"key": "bnetza-pdf:lastModified",
"value": "Wed, 26 Aug 2026 13:56:09 GMT",
"updatedAt": "2026-08-27 04:00:53.977718"
},
"... 6 weitere"
]
}
Example
$ curl -s 'https://afu.tools/api/v1/frequency/145.500' | jq '.band, .allocation.classes'
"2m"
{
"A": { "value": 750, "unit": "PEP" },
"E": { "value": 75, "unit": "PEP" },
"N": { "value": 6.1, "unit": "ERP" }
}
Where the data comes from
The full version, with terms of use and the time of the last fetch, is on the Sources page. Here is the short version.
| Area | Source | Refreshed |
|---|---|---|
| Frequencies and power | Annex 1 of the Amateurfunkverordnung | on change |
| Band segments | IARU Region 1 | rarely |
| Repeaters | fm-funknetz.de, repeatermap.de | every six hours |
| Callsign plan | Bundesnetzagentur, Vfg. 15/2025 (official work) | by hand, checked weekly for changes |
| Callsigns | Callsign list of the Bundesnetzagentur, supplemented by QRZ.com | nightly |
| DOK and local clubs | DARC | nightly |
| Exam dates | Bundesnetzagentur | nightly |
| POTA and SOTA | POTA, SOTA, areas from OSM, BfN and EEA | daily |
| Space weather and propagation | NOAA SWPC (public domain), GFZ Potsdam (Kp, CC BY 4.0), ionosondes via GIRO (CC BY-NC-SA 4.0), rating by afu.tools | every 15 minutes |
| Calling frequencies | Defaults of WSJT-X and JS8Call, band plan of IARU Region 1 | on change |
| DXCC mapping | BIG CTY (AD1C), MIT licence | monthly |
| Satellite orbital data | CelesTrak | twice a day |
| Elevation model | DGM200, © GeoBasis-DE / BKG | checked quarterly |
| Places, postcodes, locators | GeoNames (CC BY 4.0) | by hand |
| Map tiles | © OpenStreetMap contributors (ODbL), loaded via this site's server | continuously |
| Contest calendar | Rules published by the organisers | calculated |
| DX announcements | ADXO (NG3K), DX Calendar (VA3RJ), 425 DX News. Only the dates are taken over, the texts stay with the source. | twice a day |
| DX archive since 1996 | ADXO yearly archives (NG3K). Dates only; 2022 is missing at the source. | imported once |
| Evidence of whether an activity took place | Club Log and ARRL LoTW (public user lists), Reverse Beacon Network (daily archives since 2009, CW and RTTY only) | nightly |
| Rarity of an entity | Most Wanted of the German DX Foundation, from the DARC DXCC scoreboard (first 150 entities). Below that, our own estimate. | nightly |
| DXCC entity, continent, zones | BIG CTY (AD1C, Jim Reisert), MIT licence | monthly |
The API is a by-product of this site and not a guaranteed service. If you build it into something that has to keep running, cache responses and expect outages. Questions, or a data source missing: Contact.