18 KiB
Wegwichtel REST-API
Diese Datei dokumentiert die vollständige HTTP-Schnittstelle des aktuellen Wegwichtel-Servers. Die API wird unter /api bereitgestellt. Aktive GPX-, Bild- und Audiodateien werden zusätzlich unter /media ausgeliefert.
1. Grundlagen
Basisadresse
Lokaler Standard:
http://127.0.0.1:47145
API-Basis:
http://127.0.0.1:47145/api
Bei einer Nginx-Installation bleibt der Pfad gleich, beispielsweise:
https://wegwichtel.example.org/api
Formate
- Lesezugriffe liefern JSON.
- Routen- und POI-Schreibzugriffe mit Dateien verwenden
multipart/form-data. - Fehler werden als JSON ausgegeben.
- Zeitstempel stammen aus SQLite beziehungsweise JavaScript und werden als Text oder ISO-8601-Zeitstempel ausgegeben.
- Die aktuelle API besitzt noch keine Authentifizierung. Schreibzugriffe dürfen deshalb nicht ungeschützt öffentlich erreichbar sein.
Allgemeines Fehlerformat
{
"error": "HttpError",
"message": "Strecke nicht gefunden."
}
Bei Detailinformationen kann zusätzlich details enthalten sein:
{
"error": "HttpError",
"message": "Die GPX-Datei ist kein gültiges XML.",
"details": "Parsermeldung"
}
Typische Statuscodes:
| Status | Bedeutung |
|---|---|
200 |
Anfrage erfolgreich |
201 |
Ressource wurde angelegt |
400 |
Parameter oder Upload unvollständig beziehungsweise ungültig |
404 |
Route, POI oder Datei wurde nicht gefunden |
409 |
Dateisystemzustand verhindert Löschen oder Wiederherstellen |
413 |
Eine hochgeladene Datei überschreitet das konfigurierte Limit |
415 |
Dateityp wird nicht unterstützt |
500 |
Interner Serverfehler |
IDs
Die Pfadparameter :id sind positive, von SQLite erzeugte Ganzzahlen. Beispiele verwenden überwiegend Route 1 und POI 7.
Uploadgrenzen und Dateitypen
Das Dateilimit pro Datei wird durch MAX_UPLOAD_MB festgelegt und beträgt standardmäßig 50 MB. Multer akzeptiert höchstens 25 Dateien pro Request.
Erlaubte Uploadtypen:
- GPX/XML:
.gpx,application/gpx+xml,application/xml,text/xml - Bilder: JPEG, PNG, WebP
- Audio: MP3, MP4/M4A, AAC, Ogg, WAV, WebM
Beim Anlegen oder Aktualisieren eines POIs gelten zusätzlich:
- höchstens eine Datei im Feld
audio - höchstens 20 Dateien im Feld
images
2. Datenmodelle
Kurzfassung einer Route
{
"id": 1,
"slug": "schulwald-runde",
"name": "Schulwald-Runde",
"description": "Naturkundlicher Rundweg",
"schoolName": "Beispielschule",
"status": "active",
"start": { "lat": 52.5208, "lon": 13.4070 },
"center": { "lat": 52.5210, "lon": 13.4080 },
"bounds": {
"minLat": 52.5208,
"minLon": 13.4070,
"maxLat": 52.5212,
"maxLon": 13.4090
},
"distanceM": 842.6,
"elevationGainM": 14.2,
"pointCount": 87,
"gpxUrl": "/media/routes/1/route.gpx",
"createdAt": "2026-06-16 12:00:00",
"updatedAt": "2026-06-16 12:00:00",
"deletedAt": null,
"proximityM": 324.8
}
proximityM ist null, wenn beim Listenaufruf keine gültige Position übergeben wurde. Bei gelöschten Routen ist gpxUrl null, weil Dateien im Papierkorb nicht öffentlich ausgeliefert werden.
Vollständige Route
GET /api/routes/:id ergänzt die Kurzfassung um points und pois:
{
"id": 1,
"name": "Schulwald-Runde",
"points": [
{
"sequence": 0,
"lat": 52.5208,
"lon": 13.4070,
"elevation": 71.4,
"recordedAt": "2026-06-16T09:00:00Z"
}
],
"pois": []
}
POI
{
"id": 7,
"routeId": 1,
"title": "Die alte Eiche",
"description": "Hier wird das Alter der Eiche erklärt.",
"lat": 52.5208,
"lon": 13.4070,
"triggerRadiusM": 60,
"sequence": 2,
"audioUrl": "/media/routes/1/audio/uuid.mp3",
"images": [
{
"id": 15,
"caption": "",
"sequence": 0,
"url": "/media/routes/1/images/uuid.jpg"
}
]
}
3. Systemzustand
GET /api/health
Prüft den Node.js-Prozess und eine SQLite-Abfrage.
Parameter: keine.
curl http://127.0.0.1:47145/api/health
Beispielantwort:
{
"ok": true,
"service": "wegwichtel",
"socket": "127.0.0.1:47145",
"sqliteVersion": "3.46.1",
"timestamp": "2026-06-16T12:00:00.000Z"
}
4. Routen lesen
GET /api/routes
Liefert standardmäßig alle aktiven Routen alphabetisch. Werden lat und lon gemeinsam übergeben, berechnet der Server die Entfernung zum Startpunkt, filtert anhand radiusKm und sortiert nach Entfernung.
Query-Parameter
| Parameter | Typ | Pflicht | Standard | Beschreibung |
|---|---|---|---|---|
lat |
Dezimalzahl | nein | – | Breitengrad der aktuellen Position; nur zusammen mit lon wirksam |
lon |
Dezimalzahl | nein | – | Längengrad der aktuellen Position; nur zusammen mit lat wirksam |
radiusKm |
Dezimalzahl | nein | DEFAULT_ROUTE_RADIUS_KM, standardmäßig 25 |
maximaler Abstand zum Routenstart; nur bei gültigem lat und lon wirksam |
includeDeleted |
Boolean-Text | nein | false |
nur der exakte Wert true schließt gelöschte Routen ein |
Alle aktiven Routen:
curl http://127.0.0.1:47145/api/routes
Alle Parameter in einem Beispiel:
curl --get http://127.0.0.1:47145/api/routes \
--data-urlencode 'lat=52.5208' \
--data-urlencode 'lon=13.4070' \
--data-urlencode 'radiusKm=12.5' \
--data-urlencode 'includeDeleted=true'
Antwort:
{
"routes": [
{
"id": 1,
"name": "Schulwald-Runde",
"status": "active",
"proximityM": 324.8
}
]
}
Hinweise:
- Eine ungültige Zahl wird intern wie ein nicht gesetzter Wert behandelt.
- Der Positionsfilter wird nur aktiv, wenn sowohl
latals auchlongültige Zahlen sind. radiusKmwird derzeit nicht auf einen Mindest- oder Höchstwert begrenzt.
GET /api/routes/:id
Liefert eine Route mit sämtlichen GPX-Punkten und POIs.
Pfadparameter
| Parameter | Typ | Pflicht | Beschreibung |
|---|---|---|---|
id |
Ganzzahl | ja | ID der Route |
Query-Parameter
| Parameter | Typ | Pflicht | Standard | Beschreibung |
|---|---|---|---|---|
includeDeleted |
Boolean-Text | nein | false |
mit true kann auch eine als gelöscht markierte Route gelesen werden |
Aktive Route:
curl http://127.0.0.1:47145/api/routes/1
Gelöschte Route ausdrücklich einschließen:
curl 'http://127.0.0.1:47145/api/routes/1?includeDeleted=true'
Bei einer gelöschten Route sind Medien-URLs null, weil der Papierkorb nicht unter /media veröffentlicht wird.
GET /api/routes/:id/pois
Liefert alle POIs einer aktiven Route in der Reihenfolge sequence, anschließend id.
Pfadparameter
| Parameter | Typ | Pflicht | Beschreibung |
|---|---|---|---|
id |
Ganzzahl | ja | ID der aktiven Route |
Weitere Parameter: keine.
curl http://127.0.0.1:47145/api/routes/1/pois
Antwort:
{
"pois": [
{
"id": 7,
"routeId": 1,
"title": "Die alte Eiche",
"sequence": 2,
"audioUrl": "/media/routes/1/audio/uuid.mp3",
"images": []
}
]
}
5. POIs lesen
GET /api/pois/:id
Liefert einen einzelnen POI einschließlich Bild- und Audio-URLs. Der POI muss zu einer aktiven Route gehören.
Pfadparameter
| Parameter | Typ | Pflicht | Beschreibung |
|---|---|---|---|
id |
Ganzzahl | ja | ID des POIs |
Weitere Parameter: keine.
curl http://127.0.0.1:47145/api/pois/7
6. Route anlegen
POST /api/routes
Legt eine neue Route aus einer GPX-Datei an. Trackpunkte, Streckenlänge, Höhengewinn, Startpunkt, Mittelpunkt und Grenzen werden aus der Datei berechnet.
Content-Type: multipart/form-data
Formular- und Dateiparameter
| Feld | Typ | Pflicht | Standard | Beschreibung |
|---|---|---|---|---|
gpx |
Datei | ja | – | GPX-Datei mit mindestens einem verwertbaren trkpt |
name |
Text | bedingt | GPX-Track- oder Metadatenname | Routenname; erforderlich, falls die GPX-Datei keinen Namen enthält |
slug |
Text | nein | aus name abgeleitet |
URL-freundliche interne Kennung; Kollisionen erhalten automatisch -2, -3 usw. |
description |
Text | nein | leer | Beschreibung der Route |
schoolName |
Text | nein | leer | Name der Schule oder Einrichtung |
Beispiel mit allen Parametern:
curl -X POST http://127.0.0.1:47145/api/routes \
-F 'name=Schulwald-Runde' \
-F 'slug=schulwald-runde-klasse-7a' \
-F 'description=Naturkundlicher Rundweg der Klasse 7a' \
-F 'schoolName=Beispielschule' \
-F 'gpx=@examples/sample-route.gpx;type=application/gpx+xml'
Erfolg:
- Status
201 Created - Header
Location: /api/routes/<id> - Body: vollständige neu angelegte Route
7. Route vollständig aktualisieren
PUT /api/routes/:id
Ändert Metadaten einer aktiven Route. Eine optionale GPX-Datei ersetzt alle bisherigen Trackpunkte und die Datei route.gpx.
Content-Type: multipart/form-data
Pfadparameter
| Parameter | Typ | Pflicht | Beschreibung |
|---|---|---|---|
id |
Ganzzahl | ja | ID der aktiven Route |
Formular- und Dateiparameter
| Feld | Typ | Pflicht | Verhalten bei Auslassung | Beschreibung |
|---|---|---|---|---|
name |
Text | nein | alter Wert bleibt | neuer Routenname |
description |
Text | nein | alter Wert bleibt | neue Beschreibung; leere Zeichenfolge löscht den Inhalt |
schoolName |
Text | nein | alter Wert bleibt | neuer Schulname; leere Zeichenfolge löscht den Inhalt |
gpx |
Datei | nein | Track bleibt unverändert | ersetzt GPX-Datei, Trackpunkte und berechnete Kennzahlen vollständig |
slug kann über diesen Endpunkt derzeit nicht geändert werden.
Beispiel mit allen Parametern:
curl -X PUT http://127.0.0.1:47145/api/routes/1 \
-F 'name=Schulwald-Runde – überarbeitet' \
-F 'description=Neue Wegführung ab dem Schulhof' \
-F 'schoolName=Beispielschule Nord' \
-F 'gpx=@examples/sample-route.gpx;type=application/gpx+xml'
Nur die Beschreibung ändern:
curl -X PUT http://127.0.0.1:47145/api/routes/1 \
-F 'description=Nur dieser Wert wird geändert.'
Antwort: vollständige aktualisierte Route.
8. GPX-Punkte an eine Route anhängen
POST /api/routes/:id/append
Hängt sämtliche verwertbaren Trackpunkte einer GPX-Datei an eine aktive Route an und berechnet die Streckenkennzahlen neu.
Content-Type: multipart/form-data
Pfadparameter
| Parameter | Typ | Pflicht | Beschreibung |
|---|---|---|---|
id |
Ganzzahl | ja | ID der aktiven Route |
Dateiparameter
| Feld | Typ | Pflicht | Beschreibung |
|---|---|---|---|
gpx |
Datei | ja | GPX-Datei mit den anzuhängenden Trackpunkten |
curl -X POST http://127.0.0.1:47145/api/routes/1/append \
-F 'gpx=@weiterer-abschnitt.gpx;type=application/gpx+xml'
Hinweis: Die Punkte werden in SQLite ergänzt. Die gespeicherte Originaldatei route.gpx wird durch diesen Endpunkt derzeit nicht zu einer konsolidierten GPX-Datei erweitert.
9. POI anlegen
POST /api/routes/:id/pois
Legt einen POI für eine aktive Route an und speichert optional eine Audioansage und mehrere Bilder.
Content-Type: multipart/form-data
Pfadparameter
| Parameter | Typ | Pflicht | Beschreibung |
|---|---|---|---|
id |
Ganzzahl | ja | ID der aktiven Route |
Formular- und Dateiparameter
| Feld | Typ | Pflicht | Standard | Beschreibung |
|---|---|---|---|---|
title |
Text | nein | Unbenannter POI |
Titel der Station |
description |
Text | nein | leer | Beschreibung der Station |
lat |
Dezimalzahl | ja | – | Breitengrad des POIs |
lon |
Dezimalzahl | ja | – | Längengrad des POIs |
triggerRadiusM |
Dezimalzahl | nein | DEFAULT_POI_TRIGGER_METERS, standardmäßig 80 |
Entfernung in Metern, ab der die Station automatisch aktiviert und ihre Audiodatei vorgeladen wird; die Wiedergabe startet nicht automatisch |
sequence |
Ganzzahl | nein | 0 |
Sortierreihenfolge innerhalb der Route |
audio |
Datei | nein | keine | eine Audioansage |
images |
Datei, wiederholbar | nein | keine | bis zu 20 Bilder; jedes Bild wird als eigenes Feld images gesendet |
Beispiel mit allen Parametern:
curl -X POST http://127.0.0.1:47145/api/routes/1/pois \
-F 'title=Die alte Eiche' \
-F 'description=Hier wird das Alter der Eiche erklärt.' \
-F 'lat=52.5208' \
-F 'lon=13.4070' \
-F 'triggerRadiusM=60' \
-F 'sequence=2' \
-F 'audio=@ansage.mp3;type=audio/mpeg' \
-F 'images=@eiche-1.jpg;type=image/jpeg' \
-F 'images=@eiche-2.webp;type=image/webp'
Erfolg:
- Status
201 Created - Header
Location: /api/pois/<id> - Body: neu angelegter POI
Bildunterschriften können in der aktuellen API noch nicht per Parameter gesetzt werden und bleiben leer.
10. POI aktualisieren und Medien ergänzen
PUT /api/pois/:id
Ändert einen POI einer aktiven Route. Eine neue Audiodatei ersetzt den in der Datenbank referenzierten Audiopfad. Neue Bilder werden an die vorhandene Bilderliste angehängt.
Content-Type: multipart/form-data
Pfadparameter
| Parameter | Typ | Pflicht | Beschreibung |
|---|---|---|---|
id |
Ganzzahl | ja | ID des POIs |
Formular- und Dateiparameter
| Feld | Typ | Pflicht | Verhalten bei Auslassung | Beschreibung |
|---|---|---|---|---|
title |
Text | nein | alter Wert bleibt | neuer Titel |
description |
Text | nein | alter Wert bleibt | neue Beschreibung |
lat |
Dezimalzahl | nein | alter Wert bleibt | neuer Breitengrad |
lon |
Dezimalzahl | nein | alter Wert bleibt | neuer Längengrad |
triggerRadiusM |
Dezimalzahl | nein | alter Wert bleibt | neuer automatischer Auslöseradius in Metern |
sequence |
Ganzzahl | nein | alter Wert bleibt | neue Sortierreihenfolge |
audio |
Datei | nein | alte Referenz bleibt | neue Audioansage; maximal eine Datei |
images |
Datei, wiederholbar | nein | Bilder bleiben unverändert | bis zu 20 zusätzliche Bilder |
Beispiel mit allen Parametern:
curl -X PUT http://127.0.0.1:47145/api/pois/7 \
-F 'title=Die sehr alte Eiche' \
-F 'description=Überarbeitete Ansage und neue Fotos.' \
-F 'lat=52.5209' \
-F 'lon=13.4072' \
-F 'triggerRadiusM=45' \
-F 'sequence=3' \
-F 'audio=@ansage-neu.ogg;type=audio/ogg' \
-F 'images=@eiche-3.png;type=image/png' \
-F 'images=@eiche-4.jpg;type=image/jpeg'
Wichtige aktuelle Einschränkungen:
- Einzelne Bilder können noch nicht per API gelöscht, umsortiert oder beschriftet werden.
- Neu hochgeladene Bilder werden hinter vorhandenen Bildern einsortiert.
- Beim Ersetzen der Audio-Referenz wird die vorherige Audiodatei derzeit nicht automatisch aus dem aktiven Verzeichnis entfernt.
11. Route zum Löschen markieren
DELETE /api/routes/:id
Markiert eine aktive Route als gelöscht und verschiebt ihr gesamtes Verzeichnis einschließlich GPX, Bildern und Audio nach storage/trash/routes. Die Datenbankzeilen bleiben erhalten; alle gespeicherten Pfade werden auf den Papierkorb umgeschrieben.
Pfadparameter
| Parameter | Typ | Pflicht | Beschreibung |
|---|---|---|---|
id |
Ganzzahl | ja | ID der aktiven Route |
Weitere Parameter: keine.
curl -X DELETE http://127.0.0.1:47145/api/routes/1
Antwort:
{
"route": {
"id": 1,
"status": "deleted",
"gpxUrl": null,
"deletedAt": "2026-06-16 12:30:00"
},
"softDeleted": true
}
Es werden keine Dateien endgültig entfernt.
12. Route wiederherstellen
POST /api/routes/:id/restore
Stellt eine als gelöscht markierte Route wieder her, verschiebt ihr Verzeichnis nach storage/active/routes/<id> zurück und korrigiert alle GPX-, Bild- und Audiopfade.
Pfadparameter
| Parameter | Typ | Pflicht | Beschreibung |
|---|---|---|---|
id |
Ganzzahl | ja | ID der gelöschten Route |
Weitere Parameter: keine. Der Request besitzt keinen Body.
curl -X POST http://127.0.0.1:47145/api/routes/1/restore
Antwort:
{
"route": {
"id": 1,
"status": "active",
"gpxUrl": "/media/routes/1/route.gpx",
"deletedAt": null
},
"restored": true
}
13. Medien abrufen
Aktive Dateien werden nicht unter /api, sondern statisch unter /media ausgeliefert. Die benötigten URLs stehen in gpxUrl, audioUrl und images[].url.
Parameter: keine zusätzlichen Query- oder Formularparameter. Der komplette Pfad stammt aus der jeweiligen API-Antwort.
GPX-Datei:
curl --output route.gpx \
http://127.0.0.1:47145/media/routes/1/route.gpx
Audio:
curl --output ansage.mp3 \
http://127.0.0.1:47145/media/routes/1/audio/DATEINAME.mp3
Bild:
curl --output station.jpg \
http://127.0.0.1:47145/media/routes/1/images/DATEINAME.jpg
Nur storage/active wird veröffentlicht. Dateien gelöschter Routen unter storage/trash sind nicht über HTTP erreichbar.
14. Endpunktübersicht
| Methode | Pfad | Zweck |
|---|---|---|
GET |
/api/health |
Server und SQLite prüfen |
GET |
/api/routes |
Routen auflisten und optional räumlich filtern |
GET |
/api/routes/:id |
vollständige Route lesen |
GET |
/api/routes/:id/pois |
POIs einer Route lesen |
GET |
/api/pois/:id |
einzelnen POI lesen |
POST |
/api/routes |
Route aus GPX anlegen |
PUT |
/api/routes/:id |
Route aktualisieren oder GPX ersetzen |
POST |
/api/routes/:id/append |
GPX-Punkte anhängen |
POST |
/api/routes/:id/pois |
POI und Medien anlegen |
PUT |
/api/pois/:id |
POI aktualisieren und Medien ergänzen |
DELETE |
/api/routes/:id |
Route in den Papierkorb verschieben |
POST |
/api/routes/:id/restore |
Route wiederherstellen |
GET |
/media/routes/... |
aktive GPX-, Bild- und Audiodateien abrufen |