Skip to content

Latest commit

 

History

History
994 lines (795 loc) · 40.6 KB

API_DOCUMENTATION.md

File metadata and controls

994 lines (795 loc) · 40.6 KB

VeloHub API Documentation

Base URL: http://localhost:8080
Content-Type: application/json (außer bei GPX-Upload: multipart/form-data)
Swagger UI: http://localhost:8080/swagger-ui.html
OpenAPI JSON: http://localhost:8080/api-docs


Inhaltsverzeichnis

  1. Datenmodelle (Schemas)
  2. Fehlerbehandlung
  3. Trips
  4. BaseCamps
  5. Accommodations
  6. Cycling Routes
  7. Transfers
  8. Itinerary

Datenmodelle (Schemas)

PointDto

Repräsentiert einen geografischen Punkt (WGS84).

{
  "longitude": 11.5820,
  "latitude": 48.1351
}
Feld Typ Beschreibung
longitude Double Längengrad (WGS84)
latitude Double Breitengrad (WGS84)

CoordinateDto

Einzelne Koordinate innerhalb einer Linie.

{
  "longitude": 11.5820,
  "latitude": 48.1351
}

LineStringDto

Repräsentiert einen Linienzug (GPS-Track) als geordnete Liste von Koordinaten.

{
  "coordinates": [
    { "longitude": 11.5820, "latitude": 48.1351 },
    { "longitude": 11.5900, "latitude": 48.1400 },
    { "longitude": 11.6000, "latitude": 48.1500 }
  ]
}

ErrorResponse

Wird bei allen Fehlern zurückgegeben.

{
  "timestamp": "2026-04-03T12:00:00Z",
  "status": 404,
  "error": "Not Found",
  "message": "Trip mit ID abc123 nicht gefunden",
  "path": "/api/trips/abc123"
}

Fehlerbehandlung

HTTP-Status Fehlertyp Auslöser
400 Bad Request Validierungsfehler (z. B. fehlendes Pflichtfeld)
404 Not Found Ressource existiert nicht
422 Unprocessable Entity Ungültige Operation (z. B. Datumsüberschneidung)
500 Internal Server Error Unerwarteter Serverfehler

Alle Fehlermeldungen folgen dem ErrorResponse-Schema (siehe oben).


Trips

Ein Trip ist das übergeordnete Reiseobjekt. Er enthält mehrere BaseCamps, Transfers und Statistiken.

Endpoints

Methode Pfad Beschreibung
GET /api/trips Alle Trips abrufen
GET /api/trips/{id} Einzelnen Trip abrufen
GET /api/trips/{id}/stats Aggregierte Statistiken eines Trips
POST /api/trips Neuen Trip erstellen
PUT /api/trips/{id} Trip aktualisieren
DELETE /api/trips/{id} Trip löschen

GET /api/trips

Gibt alle Trips als Liste zurück.

Response 200 OK:

[
  {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Südtirol 2026",
    "description": "Radreise durch die Dolomiten",
    "createdAt": "2026-01-15T10:30:00Z"
  }
]

GET /api/trips/{id}

Gibt einen einzelnen Trip zurück.

Path Parameter:

Parameter Typ Beschreibung
id UUID Trip-ID

Response 200 OK:

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "name": "Südtirol 2026",
  "description": "Radreise durch die Dolomiten",
  "createdAt": "2026-01-15T10:30:00Z"
}

Response 404 Not Found: Trip nicht gefunden.


GET /api/trips/{id}/stats

Gibt aggregierte Statistiken eines Trips zurück (read-only, wird on-the-fly berechnet).

Path Parameter:

Parameter Typ Beschreibung
id UUID Trip-ID

Response 200 OK:

{
  "tripId": "550e8400-e29b-41d4-a716-446655440000",
  "tripName": "Südtirol 2026",
  "startDate": "2026-07-01",
  "endDate": "2026-07-14",
  "totalDays": 14,
  "cyclingDays": 8,
  "restDays": 3,
  "transferDays": 3,
  "totalCyclingRoutes": 10,
  "totalCyclingDistanceMeters": 650000.0,
  "totalCyclingElevationGain": 12500.0,
  "avgCyclingDistancePerDayMeters": 81250.0,
  "longestRouteMeters": 95000.0,
  "maxElevationGainRoute": 2100.0,
  "totalTransfers": 3,
  "totalCarDistanceKm": 185.5,
  "totalCarDurationMinutes": 180,
  "totalBaseCamps": 4
}
Feld Typ Beschreibung
tripId UUID ID des Trips
tripName String Name des Trips
startDate LocalDate? Erster Tag (Ankunft am ersten BaseCamp), null wenn leer
endDate LocalDate? Letzter Tag (Abreise aus dem letzten BaseCamp)
totalDays Int Gesamtdauer in Tagen (inkl. An-/Abreisetag)
cyclingDays Int Tage mit mindestens einer geplanten Tour
restDays Int Tage ohne geplante Aktivität
transferDays Int Tage mit einem Auto-Transfer
totalCyclingRoutes Int Anzahl aller Sternfahrten
totalCyclingDistanceMeters Double Gesamtdistanz aller Touren in Metern
totalCyclingElevationGain Double Gesamthöhenmeter (positiv) aller Touren
avgCyclingDistancePerDayMeters Double? Ø km pro Radtag, null wenn keine Radtage
longestRouteMeters Double? Längste Einzeltour in Metern, null wenn keine Touren
maxElevationGainRoute Double? Höchste Höhenmeter einer Einzeltour, null wenn keine Touren
totalTransfers Int Anzahl der Transfers
totalCarDistanceKm Double Gesamtdistanz aller Auto-Transfers in km
totalCarDurationMinutes Int Gesamtfahrzeit aller Auto-Transfers in Minuten
totalBaseCamps Int Anzahl der BaseCamps

POST /api/trips

Erstellt einen neuen Trip.

Request Body:

{
  "name": "Südtirol 2026",
  "description": "Radreise durch die Dolomiten"
}
Feld Typ Pflicht Validierung Beschreibung
name String ✅ max. 255 Zeichen Name des Trips
description String? ❌ – Optionale Beschreibung

Response 201 Created: TripResponse (wie bei GET)

Response 400 Bad Request: Validierungsfehler.


PUT /api/trips/{id}

Aktualisiert einen bestehenden Trip.

Path Parameter: id (UUID)

Request Body: Identisch mit POST /api/trips

Response 200 OK: TripResponse

Response 404 Not Found: Trip nicht gefunden.


DELETE /api/trips/{id}

Löscht einen Trip samt aller zugehörigen Daten.

Path Parameter: id (UUID)

Response 204 No Content

Response 404 Not Found: Trip nicht gefunden.


BaseCamps

Ein BaseCamp ist ein Aufenthaltsort innerhalb eines Trips (z. B. ein Hotel-Standort für mehrere Tage). Von einem BaseCamp aus werden Sternfahrten (CyclingRoutes) unternommen.

Endpoints

Methode Pfad Beschreibung
GET /api/trips/{tripId}/basecamps Alle BaseCamps eines Trips
GET /api/trips/{tripId}/basecamps/{baseCampId} Einzelnes BaseCamp
GET /api/trips/{tripId}/basecamps/{baseCampId}/stats Aggregierte Statistiken des BaseCamps
POST /api/trips/{tripId}/basecamps Neues BaseCamp erstellen
PUT /api/trips/{tripId}/basecamps/{baseCampId} BaseCamp aktualisieren
DELETE /api/trips/{tripId}/basecamps/{baseCampId} BaseCamp löschen

GET /api/trips/{tripId}/basecamps

Gibt alle BaseCamps eines Trips zurück.

Path Parameter:

Parameter Typ Beschreibung
tripId UUID Trip-ID

Response 200 OK:

[
  {
    "id": "660e8400-e29b-41d4-a716-446655440001",
    "tripId": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Bozen",
    "location": {
      "longitude": 11.3548,
      "latitude": 46.4983
    },
    "arrivalDate": "2026-07-01",
    "departureDate": "2026-07-05",
    "orderIndex": 0
  }
]

GET /api/trips/{tripId}/basecamps/{baseCampId}

Gibt ein einzelnes BaseCamp zurück.

Response 200 OK: BaseCampResponse (wie oben)

Response 404 Not Found: BaseCamp nicht gefunden.


GET /api/trips/{tripId}/basecamps/{baseCampId}/stats

Gibt aggregierte Statistiken aller Sternfahrten eines BaseCamps zurück.

Response 200 OK:

{
  "baseCampId": "660e8400-e29b-41d4-a716-446655440001",
  "baseCampName": "Bozen",
  "routeCount": 4,
  "totalDistanceMeters": 210000.0,
  "totalElevationGain": 4800.0,
  "longestRouteMeters": 75000.0,
  "maxElevationGain": 1800.0
}
Feld Typ Beschreibung
baseCampId UUID ID des BaseCamps
baseCampName String Name des BaseCamps
routeCount Int Anzahl der Sternfahrten
totalDistanceMeters Double Gesamtdistanz in Metern
totalElevationGain Double Gesamthöhenmeter
longestRouteMeters Double? Längste Einzeltour in Metern, null wenn keine Touren
maxElevationGain Double? Höchste Höhenmeter einer Einzeltour, null wenn keine

POST /api/trips/{tripId}/basecamps

Erstellt ein neues BaseCamp.

Request Body:

{
  "name": "Bozen",
  "location": {
    "longitude": 11.3548,
    "latitude": 46.4983
  },
  "arrivalDate": "2026-07-01",
  "departureDate": "2026-07-05",
  "orderIndex": 0
}
Feld Typ Pflicht Validierung Beschreibung
name String ✅ max. 255 Zeichen Name des BaseCamps
location PointDto ✅ – Geografische Position
arrivalDate LocalDate ✅ – Ankunftsdatum (yyyy-MM-dd)
departureDate LocalDate ✅ – Abreisedatum (yyyy-MM-dd)
orderIndex Int? ❌ – Reihenfolge im Trip (wird automatisch gesetzt wenn leer)

Response 201 Created: BaseCampResponse

Response 400 Bad Request: Validierungsfehler.


PUT /api/trips/{tripId}/basecamps/{baseCampId}

Aktualisiert ein bestehendes BaseCamp.

Request Body:

{
  "name": "Bozen",
  "location": {
    "longitude": 11.3548,
    "latitude": 46.4983
  },
  "arrivalDate": "2026-07-01",
  "departureDate": "2026-07-05",
  "orderIndex": 0
}
Feld Typ Pflicht Beschreibung
name String ✅ max. 255 Zeichen
location PointDto ✅ Geografische Position
arrivalDate LocalDate ✅ Ankunftsdatum (yyyy-MM-dd)
departureDate LocalDate ✅ Abreisedatum (yyyy-MM-dd)
orderIndex Int ✅ Reihenfolge im Trip

Response 200 OK: BaseCampResponse

Response 404 Not Found


DELETE /api/trips/{tripId}/basecamps/{baseCampId}

Löscht ein BaseCamp.

Response 204 No Content


Accommodations

Eine Accommodation ist eine konkrete Unterkunft innerhalb eines BaseCamps (z. B. ein Hotel für bestimmte Nächte).

Endpoints

Methode Pfad Beschreibung
GET /api/trips/{tripId}/basecamps/{baseCampId}/accommodation Alle Unterkünfte des BaseCamps
GET /api/trips/{tripId}/basecamps/{baseCampId}/accommodation/{accommodationId} Einzelne Unterkunft
POST /api/trips/{tripId}/basecamps/{baseCampId}/accommodation Unterkunft erstellen
PUT /api/trips/{tripId}/basecamps/{baseCampId}/accommodation/{accommodationId} Unterkunft aktualisieren
DELETE /api/trips/{tripId}/basecamps/{baseCampId}/accommodation/{accommodationId} Unterkunft löschen

GET /api/trips/{tripId}/basecamps/{baseCampId}/accommodation

Gibt alle Unterkünfte eines BaseCamps zurück, sortiert nach Check-in-Datum.

Response 200 OK:

[
  {
    "id": "770e8400-e29b-41d4-a716-446655440002",
    "baseCampId": "660e8400-e29b-41d4-a716-446655440001",
    "name": "Hotel Therme Meran",
    "location": {
      "longitude": 11.1714,
      "latitude": 46.6725
    },
    "bookingUrl": "https://booking.com/hotel/therme-meran",
    "checkInDate": "2026-07-01",
    "checkOutDate": "2026-07-05"
  }
]

POST /api/trips/{tripId}/basecamps/{baseCampId}/accommodation

Erstellt eine neue Unterkunft.

Request Body:

{
  "name": "Hotel Therme Meran",
  "location": {
    "longitude": 11.1714,
    "latitude": 46.6725
  },
  "bookingUrl": "https://booking.com/hotel/therme-meran",
  "checkInDate": "2026-07-01",
  "checkOutDate": "2026-07-05"
}
Feld Typ Pflicht Validierung Beschreibung
name String ✅ max. 255 Zeichen Name der Unterkunft
location PointDto ✅ – Geografische Position
bookingUrl String? ❌ – Link zur Buchungsseite
checkInDate LocalDate ✅ – Check-in-Datum (yyyy-MM-dd)
checkOutDate LocalDate ✅ – Check-out-Datum (yyyy-MM-dd)

Response 201 Created: AccommodationResponse

Response 400 Bad Request: Validierungsfehler.


PUT /api/trips/{tripId}/basecamps/{baseCampId}/accommodation/{accommodationId}

Aktualisiert eine bestehende Unterkunft. Request Body identisch mit POST.

Response 200 OK: AccommodationResponse

Response 404 Not Found


DELETE /api/trips/{tripId}/basecamps/{baseCampId}/accommodation/{accommodationId}

Löscht eine Unterkunft.

Response 204 No Content


Cycling Routes

Eine CyclingRoute ist eine Sternfahrt vom BaseCamp aus (Ausfahrt und Rückfahrt zum selben Ausgangspunkt). Routen können manuell erstellt oder per GPX-Import angelegt werden.

Endpoints

Methode Pfad Beschreibung
GET /api/trips/{tripId}/basecamps/{baseCampId}/routes Alle Routen eines BaseCamps
GET /api/trips/{tripId}/basecamps/{baseCampId}/routes/{routeId} Einzelne Route
GET /api/trips/{tripId}/basecamps/{baseCampId}/routes/{routeId}/elevation-profile Höhenprofil der Route
POST /api/trips/{tripId}/basecamps/{baseCampId}/routes Route manuell erstellen
POST /api/trips/{tripId}/basecamps/{baseCampId}/routes/gpx Route per GPX-Datei importieren
PUT /api/trips/{tripId}/basecamps/{baseCampId}/routes/{routeId} Route aktualisieren
DELETE /api/trips/{tripId}/basecamps/{baseCampId}/routes/{routeId} Route löschen

GET /api/trips/{tripId}/basecamps/{baseCampId}/routes

Gibt alle Sternfahrten eines BaseCamps zurück.

Response 200 OK:

[
  {
    "id": "880e8400-e29b-41d4-a716-446655440003",
    "baseCampId": "660e8400-e29b-41d4-a716-446655440001",
    "name": "Passo dello Stelvio",
    "distanceMeters": 95000.0,
    "elevationGain": 2100.0,
    "trackGeom": {
      "coordinates": [
        { "longitude": 11.3548, "latitude": 46.4983 },
        { "longitude": 10.4530, "latitude": 46.5393 }
      ]
    },
    "orderIndex": 0,
    "scheduledDate": "2026-07-02",
    "gpxImportInfo": null
  }
]

GET /api/trips/{tripId}/basecamps/{baseCampId}/routes/{routeId}/elevation-profile

Gibt das Höhenprofil einer Route zurück (für Chart-Darstellung und Karten-Hover).

Response 200 OK:

{
  "routeId": "880e8400-e29b-41d4-a716-446655440003",
  "routeName": "Passo dello Stelvio",
  "totalDistanceMeters": 95000.0,
  "hasElevationData": true,
  "points": [
    {
      "distanceMeters": 0.0,
      "elevation": 260.0,
      "longitude": 11.3548,
      "latitude": 46.4983,
      "gradePct": 2.1
    },
    {
      "distanceMeters": 500.0,
      "elevation": 270.5,
      "longitude": 11.3560,
      "latitude": 46.4990,
      "gradePct": null
    }
  ]
}
Feld Typ Beschreibung
routeId UUID ID der Route
routeName String Name der Route
totalDistanceMeters Double Gesamtdistanz in Metern
hasElevationData Boolean true wenn GPX-Track Höhendaten enthielt
points Array Geordnete Liste von ElevationPoint-Objekten

ElevationPoint:

Feld Typ Beschreibung
distanceMeters Double Kumulative Distanz vom Startpunkt (X-Achse im Chart)
elevation Double? Höhe über NN in Metern (null wenn GPX keine <ele>-Daten enthielt)
longitude Double Längengrad (für Mapbox-Marker beim Hover)
latitude Double Breitengrad (für Mapbox-Marker beim Hover)
gradePct Double? Steigung zum nächsten Punkt in % (positiv = Anstieg), null beim letzten Punkt

POST /api/trips/{tripId}/basecamps/{baseCampId}/routes

Erstellt eine neue Sternfahrt manuell.

Request Body:

{
  "name": "Passo dello Stelvio",
  "distanceMeters": 95000.0,
  "elevationGain": 2100.0,
  "trackGeom": {
    "coordinates": [
      { "longitude": 11.3548, "latitude": 46.4983 },
      { "longitude": 10.4530, "latitude": 46.5393 }
    ]
  },
  "orderIndex": 0,
  "scheduledDate": "2026-07-02"
}
Feld Typ Pflicht Validierung Beschreibung
name String ✅ max. 255 Zeichen Name der Route
distanceMeters Double ✅ positiv Streckenlänge in Metern
elevationGain Double ✅ positiv Positive Höhenmeter
trackGeom LineStringDto ✅ – GPS-Track als Linienzug
orderIndex Int? ❌ – Reihenfolge im BaseCamp (automatisch ans Ende wenn leer)
scheduledDate LocalDate? ❌ – Geplantes Datum (yyyy-MM-dd, muss im Camp-Zeitraum liegen)

Response 201 Created: CyclingRouteResponse


POST /api/trips/{tripId}/basecamps/{baseCampId}/routes/gpx

Importiert eine Route aus einer GPX-Datei.

Die Route wird automatisch mit dem Douglas-Peucker-Algorithmus vereinfacht.
Distanz und Höhenmeter werden automatisch aus den GPS-Daten berechnet.

Content-Type: multipart/form-data

Parameter Typ Pflicht Beschreibung
file File (GPX) ✅ GPX-Datei (max. 50 MB)
name String ❌ Optionaler Name (überschreibt den GPX-internen Namen)
scheduledDate LocalDate ❌ Geplantes Datum (yyyy-MM-dd)

Response 201 Created:

{
  "id": "880e8400-e29b-41d4-a716-446655440003",
  "baseCampId": "660e8400-e29b-41d4-a716-446655440001",
  "name": "Passo dello Stelvio",
  "distanceMeters": 95482.3,
  "elevationGain": 2148.7,
  "trackGeom": { "coordinates": [ ... ] },
  "orderIndex": 1,
  "scheduledDate": "2026-07-02",
  "gpxImportInfo": {
    "originalPointCount": 4823,
    "simplifiedPointCount": 312
  }
}

gpxImportInfo-Felder (nur bei GPX-Import befüllt):

Feld Typ Beschreibung
originalPointCount Int Anzahl der GPS-Punkte im Original-GPX
simplifiedPointCount Int Anzahl der Punkte nach Douglas-Peucker-Vereinfachung

PUT /api/trips/{tripId}/basecamps/{baseCampId}/routes/{routeId}

Aktualisiert eine bestehende Route.

Request Body:

{
  "name": "Passo dello Stelvio (angepasst)",
  "distanceMeters": 95000.0,
  "elevationGain": 2100.0,
  "trackGeom": {
    "coordinates": [
      { "longitude": 11.3548, "latitude": 46.4983 }
    ]
  },
  "orderIndex": 0,
  "scheduledDate": "2026-07-03"
}
Feld Typ Pflicht Validierung
name String ✅ max. 255 Zeichen
distanceMeters Double ✅ positiv
elevationGain Double ✅ positiv
trackGeom LineStringDto ✅ –
orderIndex Int ✅ –
scheduledDate LocalDate? ❌ –

Response 200 OK: CyclingRouteResponse


DELETE /api/trips/{tripId}/basecamps/{baseCampId}/routes/{routeId}

Löscht eine Route.

Response 204 No Content


Transfers

Ein Transfer ist eine Auto-Fahrt zwischen zwei BaseCamps. Die Route wird automatisch über den OpenRouteService berechnet, kann aber manuell überschrieben werden.

Endpoints

Methode Pfad Beschreibung
GET /api/trips/{tripId}/transfers Alle Transfers eines Trips
GET /api/trips/{tripId}/transfers/{transferId} Einzelnen Transfer abrufen
POST /api/trips/{tripId}/transfers Transfer erstellen
POST /api/trips/{tripId}/transfers/{transferId}/recalculate Route neu berechnen (via OpenRouteService)
PUT /api/trips/{tripId}/transfers/{transferId} Transfer aktualisieren
DELETE /api/trips/{tripId}/transfers/{transferId} Transfer löschen

GET /api/trips/{tripId}/transfers

Gibt alle Transfers eines Trips zurück.

Response 200 OK:

[
  {
    "id": "990e8400-e29b-41d4-a716-446655440004",
    "tripId": "550e8400-e29b-41d4-a716-446655440000",
    "fromCampId": "660e8400-e29b-41d4-a716-446655440001",
    "toCampId": "661e8400-e29b-41d4-a716-446655440005",
    "distanceKm": 85.5,
    "durationMinutes": 95,
    "routeGeom": {
      "coordinates": [
        { "longitude": 11.3548, "latitude": 46.4983 },
        { "longitude": 10.9027, "latitude": 46.0664 }
      ]
    },
    "scheduledDate": "2026-07-05"
  }
]

POST /api/trips/{tripId}/transfers

Erstellt einen neuen Transfer. Distanz, Dauer und Routengeometrie werden automatisch via OpenRouteService berechnet, wenn nicht manuell angegeben.

Request Body:

{
  "fromCampId": "660e8400-e29b-41d4-a716-446655440001",
  "toCampId": "661e8400-e29b-41d4-a716-446655440005",
  "distanceKm": null,
  "durationMinutes": null,
  "routeGeom": null,
  "scheduledDate": "2026-07-05"
}
Feld Typ Pflicht Validierung Beschreibung
fromCampId UUID ✅ – ID des Abfahrts-BaseCamps
toCampId UUID ✅ – ID des Ziel-BaseCamps
distanceKm Double? ❌ positiv Manuelle Überschreibung der Distanz in km
durationMinutes Int? ❌ positiv Manuelle Überschreibung der Fahrtdauer in Minuten
routeGeom LineStringDto? ❌ – Manuelle Routengeometrie (wird sonst via Routing-API berechnet)
scheduledDate LocalDate? ❌ – Geplantes Datum (yyyy-MM-dd); automatisch = letzter Camp-Tag

Response 201 Created: TransferResponse


POST /api/trips/{tripId}/transfers/{transferId}/recalculate

Berechnet die Route eines bestehenden Transfers neu (z. B. nach einer Positionsänderung eines BaseCamps). Nutzt den OpenRouteService.

Response 200 OK: Aktualisierter TransferResponse


PUT /api/trips/{tripId}/transfers/{transferId}

Aktualisiert einen bestehenden Transfer manuell.

Request Body:

{
  "distanceKm": 90.0,
  "durationMinutes": 110,
  "routeGeom": null,
  "scheduledDate": "2026-07-05"
}
Feld Typ Pflicht Validierung Beschreibung
distanceKm Double ✅ positiv Distanz in km
durationMinutes Int ✅ positiv Fahrtdauer in Minuten
routeGeom LineStringDto? ❌ – Optionale Routengeometrie
scheduledDate LocalDate? ❌ – Geplantes Datum (yyyy-MM-dd)

Response 200 OK: TransferResponse


DELETE /api/trips/{tripId}/transfers/{transferId}

Löscht einen Transfer.

Response 204 No Content


Itinerary

Der Itinerary ist der vollständige Tag-für-Tag-Reiseplan eines Trips. Er wird on-the-fly aus allen vorhandenen Daten berechnet (kein eigener Datensatz in der Datenbank).

Endpoints

Methode Pfad Beschreibung
GET /api/trips/{tripId}/itinerary Vollständigen Reiseplan abrufen

GET /api/trips/{tripId}/itinerary

Generiert den vollständigen Tag-für-Tag-Reiseplan eines Trips.

Der Plan aggregiert BaseCamps, CyclingRoutes (scheduledDate), Transfers (scheduledDate) und Accommodations (checkIn/checkOut) zu einer chronologischen Übersicht.

Tagestypen:

Typ Beschreibung
CYCLING Mindestens eine Tour ist an diesem Tag geplant
TRANSFER_DEPARTURE Abfahrt mit dem Auto zum nächsten BaseCamp
TRANSFER_ARRIVAL Ankunft mit dem Auto vom vorherigen BaseCamp
REST_DAY Keine Aktivität geplant

Response 200 OK:

{
  "tripId": "550e8400-e29b-41d4-a716-446655440000",
  "tripName": "Südtirol 2026",
  "startDate": "2026-07-01",
  "endDate": "2026-07-14",
  "totalDays": 14,
  "days": [
    {
      "date": "2026-07-01",
      "dayNumber": 1,
      "baseCampId": "660e8400-e29b-41d4-a716-446655440001",
      "baseCampName": "Bozen",
      "accommodation": {
        "accommodationId": "770e8400-e29b-41d4-a716-446655440002",
        "name": "Hotel Therme Meran",
        "location": {
          "longitude": 11.1714,
          "latitude": 46.6725
        },
        "bookingUrl": "https://booking.com/hotel/therme-meran"
      },
      "entries": [
        {
          "type": "TRANSFER_ARRIVAL",
          "orderIndex": 0,
          "cycling": null,
          "transfer": {
            "transferId": "990e8400-e29b-41d4-a716-446655440004",
            "fromCampName": "München",
            "toCampName": "Bozen",
            "distanceKm": 185.5,
            "durationMinutes": 180
          }
        }
      ]
    },
    {
      "date": "2026-07-02",
      "dayNumber": 2,
      "baseCampId": "660e8400-e29b-41d4-a716-446655440001",
      "baseCampName": "Bozen",
      "accommodation": { ... },
      "entries": [
        {
          "type": "CYCLING",
          "orderIndex": 0,
          "cycling": {
            "routeId": "880e8400-e29b-41d4-a716-446655440003",
            "name": "Passo dello Stelvio",
            "distanceMeters": 95000.0,
            "elevationGain": 2100.0
          },
          "transfer": null
        }
      ]
    }
  ]
}

Response-Felder:

Feld Typ Beschreibung
tripId UUID ID des Trips
tripName String Name des Trips
startDate LocalDate Erster Tag des Trips
endDate LocalDate Letzter Tag des Trips
totalDays Int Gesamtanzahl der Tage
days Array Liste von ItineraryDayResponse

ItineraryDayResponse:

Feld Typ Beschreibung
date LocalDate Datum des Tages
dayNumber Int Laufender Tag (1-basiert)
baseCampId UUID Zugehöriges BaseCamp
baseCampName String Name des BaseCamps
accommodation AccommodationSummary? Unterkunft dieser Nacht (null wenn nicht hinterlegt)
entries Array Geordnete Liste von ItineraryEntryResponse

ItineraryEntryResponse:

Feld Typ Beschreibung
type ItineraryEntryType (Enum) Art der Aktivität (CYCLING, TRANSFER_DEPARTURE, TRANSFER_ARRIVAL, REST_DAY)
orderIndex Int Sortierreihenfolge innerhalb des Tages
cycling CyclingRouteSummary? Nur bei CYCLING befüllt
transfer TransferSummary? Nur bei TRANSFER_DEPARTURE/TRANSFER_ARRIVAL befüllt

CyclingRouteSummary:

Feld Typ Beschreibung
routeId UUID ID der Route
name String Name der Route
distanceMeters Double Streckenlänge in Metern
elevationGain Double Positive Höhenmeter

TransferSummary:

Feld Typ Beschreibung
transferId UUID ID des Transfers
fromCampName String Name des Abfahrts-BaseCamps
toCampName String Name des Ziel-BaseCamps
distanceKm Double Fahrtstrecke in km
durationMinutes Int Fahrtdauer in Minuten

AccommodationSummary:

Feld Typ Beschreibung
accommodationId UUID ID der Unterkunft
name String Name der Unterkunft
location PointDto Geografische Position
bookingUrl String? Link zur Buchungsseite (optional)

Vollständige Endpoint-Übersicht

Methode Pfad Beschreibung
GET /api/trips Alle Trips
POST /api/trips Trip erstellen
GET /api/trips/{tripId} Trip abrufen
PUT /api/trips/{tripId} Trip aktualisieren
DELETE /api/trips/{tripId} Trip löschen
GET /api/trips/{tripId}/stats Trip-Statistiken
GET /api/trips/{tripId}/itinerary Reiseplan (Itinerary)
GET /api/trips/{tripId}/basecamps Alle BaseCamps eines Trips
POST /api/trips/{tripId}/basecamps BaseCamp erstellen
GET /api/trips/{tripId}/basecamps/{baseCampId} BaseCamp abrufen
PUT /api/trips/{tripId}/basecamps/{baseCampId} BaseCamp aktualisieren
DELETE /api/trips/{tripId}/basecamps/{baseCampId} BaseCamp löschen
GET /api/trips/{tripId}/basecamps/{baseCampId}/stats BaseCamp-Statistiken
GET /api/trips/{tripId}/basecamps/{baseCampId}/accommodation Alle Unterkünfte eines BaseCamps
POST /api/trips/{tripId}/basecamps/{baseCampId}/accommodation Unterkunft erstellen
GET /api/trips/{tripId}/basecamps/{baseCampId}/accommodation/{accommodationId} Unterkunft abrufen
PUT /api/trips/{tripId}/basecamps/{baseCampId}/accommodation/{accommodationId} Unterkunft aktualisieren
DELETE /api/trips/{tripId}/basecamps/{baseCampId}/accommodation/{accommodationId} Unterkunft löschen
GET /api/trips/{tripId}/basecamps/{baseCampId}/routes Alle Routen eines BaseCamps
POST /api/trips/{tripId}/basecamps/{baseCampId}/routes Route erstellen
POST /api/trips/{tripId}/basecamps/{baseCampId}/routes/gpx Route per GPX importieren
GET /api/trips/{tripId}/basecamps/{baseCampId}/routes/{routeId} Route abrufen
PUT /api/trips/{tripId}/basecamps/{baseCampId}/routes/{routeId} Route aktualisieren
DELETE /api/trips/{tripId}/basecamps/{baseCampId}/routes/{routeId} Route löschen
GET /api/trips/{tripId}/basecamps/{baseCampId}/routes/{routeId}/elevation-profile Höhenprofil einer Route
GET /api/trips/{tripId}/transfers Alle Transfers eines Trips
POST /api/trips/{tripId}/transfers Transfer erstellen
GET /api/trips/{tripId}/transfers/{transferId} Transfer abrufen
PUT /api/trips/{tripId}/transfers/{transferId} Transfer aktualisieren
DELETE /api/trips/{tripId}/transfers/{transferId} Transfer löschen
POST /api/trips/{tripId}/transfers/{transferId}/recalculate Transfer-Route neu berechnen