Tours (Führungen)

Geführte Touren - listen, Verfügbarkeit prüfen, Preise berechnen, und über Anfrage oder Direktbuchung anstoßen.

Eine Tour in go~mus ist eine geführte Veranstaltung, die nicht zu festen Terminen stattfindet, sondern auf Anfrage oder Buchung angesetzt wird - klassische Führungen, Schulworkshops, Privatführungen, Kindergeburtstage. Anders als bei Events gibt es kein vorbelegtes Date pro Termin; stattdessen fragst du ab, wann eine Tour grundsätzlich verfügbar wäre, und der konkrete Termin entsteht erst mit der Anfrage oder Buchung.

Die zwei häufigsten Use-Cases dieser Resource sind:

1. Tour-Übersicht auf der Webseite mit Filterung nach Sprache, Zielgruppe, Sonderausstellung

2. Anfrage- oder Buchungsformular auf der Webseite, das in go~mus landet (Pattern Museumsdienst Berlin, Hamburg, viele andere)

Vollständige Endpoint- und Schema-Referenz: Swagger.

Tour vs Event - der Unterschied

TourEvent
Termineflexibel, vom/von der Kund:in vorgeschlagenim Backoffice vordefiniert (Dates)
Buchungs-Primitivdie Tour selbst plus Wunsch-Datum/Zeitdas Date
HauptflowAnfrage oder DirektbuchungDirektbuchung
Verfügbarkeits-Endpointstart_timesdates / calendar

Ein Date pro Tour gibt es technisch trotzdem - sobald eine Tour gebucht ist, entsteht intern ein Booking mit konkretem Termin. Für die API-Sicht von außen ist die Resource aber die Tour, nicht das Date.

Anatomie eines Tour-Objekts

Im Index- und Show-Response findest du je Tour:

  • id - stabil, nutzt das in Items von Anfragen und Bestellungen
  • title, sub_title, description - übersetzbar via ?locale=de
  • museum_id, exhibition_id - Zuordnung
  • category - eingebettete Kategorie (Führung, Workshop, Vortrag, Kindergeburtstag, ...)
  • bookable, registerable - kontextabhängige Flags für deine Auth-Stufe
  • featured - Boolean, Highlight-Flag
  • min_persons, max_persons, max_participants - Bestellgrenzen und Gruppenobergrenze
  • duration - Dauer in Minuten
  • equipment - Liste benötigter Hilfsmittel (z.B. Kopfhörer, Beamer)
  • entry_fee - Modus für Eintrittsgebühr-Anzeige

Im Show-Response zusätzlich: tickets, quotas, limitations, validities, content (Langtexte), documents (Anhänge), sellabilities.

Komplette Feldliste: Swagger.

Endpoints im Überblick

EndpointWofürWann nutzen
GET /api/v4/toursTour-ListeÜbersichtsseite mit Filtern
GET /api/v4/tours/:idTour-DetailVolle Beschreibung, Konfiguration
GET /api/v4/tours/:id/start_timesVerfügbare Startzeiten"Wann kann ich diese Tour buchen?"
GET /api/v4/tours/:id/pricesPreisermittlungWas kostet die Tour mit X Personen am Datum Y
GET /api/v4/tours/:id/categoriesKategorien einer Tourfür Filter-UI
GET /api/v4/tours/:id/languagesVerfügbare Sprachenfür Filter-UI
GET /api/v4/tours/:id/audiencesZielgruppenfür Filter-UI
GET /api/v4/tours/:id/age_groupsAltersgruppenfür Filter-UI
POST /api/v4/requestsAnfrage anlegenKund:in fragt Termin an, Museum bestätigt manuell
POST /api/v4/ordersDirektbuchung anlegenKund:in bucht sofort verbindlich

Häufige Aufgaben

Tours auflisten

curl "https://demo.gomus.de/api/v4/tours?by_museum_ids[]=20&by_audience_ids[]=4&locale=de"

Die Filter sind dieselben wie bei Events - alle optional, alle kombinierbar:

  • by_museum_ids[]=20 - nur Touren eines Hauses
  • by_exhibition_ids[]=2057 - nur Touren zu einer Sonderausstellung (-1 für "ohne Ausstellungsbezug")
  • by_category_ids[]=12 oder by_categories[]=fuehrung - Kategorie-Filter
  • by_audience_ids[]=4 - z.B. nur Touren für Familien
  • by_age_group_ids[]=2 - z.B. nur Touren für Erwachsene
  • by_grade_ids[]=8 - Schulklassen-Stufe
  • by_language_ids[]=1 - nur deutschsprachige Touren
  • by_catch_word_ids[], by_disablement_ids[], by_proposal_category_ids[] - weitere Klassifikationen
  • by_featured=true - nur Highlights

Filter-UI mit den verfügbaren Werten füllen

Wie bei Events liefern Sub-Resource-Endpoints die in der Instance tatsächlich genutzten Werte:

curl "https://demo.gomus.de/api/v4/tours/categories?locale=de"
curl "https://demo.gomus.de/api/v4/tours/audiences?locale=de"
curl "https://demo.gomus.de/api/v4/tours/languages?locale=de"

Verfügbare Startzeiten ermitteln

curl "https://demo.gomus.de/api/v4/tours/512/start_times?start_at=2026-05-01&end_at=2026-05-31&participants=15&language_ids[]=1"

Parameter:

  • start_at, end_at - Zeitfenster (Default: heute bis Ende des Monats). Maximaler Range: 60 Tage - größere Spannen gibt der Server mit einem Validierungsfehler zurück. Für ein 12-Monats-Datepicker machst du also mehrere Calls in 60-Tage-Buckets.
  • participants - Teilnehmerzahl, beeinflusst Verfügbarkeit (Default: 1 oder das min_persons der Tour)
  • language_ids[], age_group_ids[] - Filter, die in die Verfügbarkeitsberechnung einfließen
  • depth - any (mindestens ein Slot pro Tag, Boolean-Antwort) oder all (alle buchbaren Slots, Liste); Default any

depth=any ist der typische Datepicker-Use-Case ("welche Tage sind buchbar"). depth=all ist der Slot-Picker-Use-Case ("welche Uhrzeiten am gewählten Tag").

Preis ermitteln

Tour-Preise sind kontextabhängig - sie hängen ab von Datum, Uhrzeit, Personenzahl, Sprache und der Preisgruppe (PriceTargetAudience, z.B. "Privatkunde", "Schulklasse", "Reseller"). Der Endpoint berechnet das in einem Call:

curl "https://demo.gomus.de/api/v4/tours/512/prices?date=2026-05-15&time=14:00&participants=15&language_id=1"

Parameter:

  • date (Default: heute)
  • time als HH:MM (Default: 12:00)
  • participants (Default: 1)
  • language_id (Default: erste für die Tour hinterlegte Sprache)
  • price_target_audience_id (Default: aus dem Auth-Kontext, sonst die instance-weite Default-PTA)

Die Antwort enthält die Einzelpositionen und den Gesamtpreis - genau das, was im Buchungsformular angezeigt wird.

Tour-Detail

curl "https://demo.gomus.de/api/v4/tours/512?locale=de"

Show-Response liefert die Beschreibung, eingebundene Tickets/Quotas, Validity-Regeln und Anhänge - genug für eine vollständige Detailseite.

Vom Wunsch zur Buchung - die zwei Wege

Weg 1: Anfrage (POST /api/v4/requests)

Die typische Lösung für Schul-Anfragen, Gruppenführungen und alles, was das Museum vor Bestätigung redaktionell prüfen will (Disposition, Guide-Auswahl, Sondervereinbarungen). Die Anfrage landet in go~mus mit Status registered, geht durchs Anfragen-Postfach, das Backoffice antwortet manuell.

curl -X POST "https://demo.gomus.de/api/v4/requests" \
  -H "Authorization: Bearer YOUR_API_USER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "request": {
      "participants": 25,
      "companions": 2,
      "date": "2026-06-15",
      "notes": "Klasse 7a, Geschichts-LK, Schwerpunkt 19. Jahrhundert",
      "language": "Deutsch",
      "age_group": "Schulklasse",
      "grade": "Sekundarstufe II",
      "items": [
        { "tour_id": 512, "time": "10:00" },
        { "tour_id": 519, "time": "13:00" }
      ],
      "customer": {
        "name": "Müller", "surname": "Anna",
        "email": "lehrer@beispielschule.de",
        "phone": "+49 30 12345",
        "street": "Schulweg 1", "zip": "10115", "city": "Berlin"
      }
    }
  }'

Wichtig:

  • Authentifizierung über einen API-User-Token mit Permission. Public-Token reicht hier nicht.
  • items ist Pflicht und muss mindestens eine tour_id plus gewünschte time enthalten. Mehrere Items in einer Anfrage = Mehrfachführung am selben Tag.
  • payment_mode, language, age_group, grade, proposal_category, category lassen sich entweder als ID oder als übersetzter Name angeben.
  • skip_confirmation_email: true unterdrückt die automatische Bestätigungsmail (z.B. wenn dein System die Bestätigung selbst versendet).

Die Response liefert id, created_at, updated_at. Validierungsfehler kommen als 422 mit Feld-Details.

Weg 2: Direktbuchung (POST /api/v4/orders)

Wenn die Tour direkt verkauft werden soll - Privatführung, Workshop mit Festpreis, Tickets-on-Demand - geht das wie bei Events über Order plus Finalize.

Order anlegen mit der Tour als Item:

curl -X POST "https://demo.gomus.de/api/v4/orders" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "order": {
      "items": [
        {
          "tour_id": 512,
          "date": "2026-06-15",
          "start_time": "14:00",
          "participants": 8,
          "language_id": 1
        }
      ],
      "customer": { "email": "kund@example.com", "..." : "..." }
    }
  }'

Dann finalisieren:

curl -X POST "https://demo.gomus.de/api/v4/orders/ORDER_TOKEN/finalize" \
  -H "Authorization: Bearer YOUR_TOKEN"

Genaue Payload-Strukturen, Validierungen und Payment-Optionen: Swagger und Best Practices.

Anfrage vs Direktbuchung - wann was

KriteriumAnfrageDirektbuchung
Sofort verbindlich?Nein, Bestätigung manuellJa
Preis bei Submit fix?Optional (Group-Prices kommen automatisch)Ja
Bezahlung sofort?NeinJa, im Finalize-Schritt
Typische NutzungSchulklassen, Gruppenführungen, SonderwünschePrivatführungen, Workshop-Tickets
AuthAPI-User-Token mit PermissionPublic-Token, Reseller-Token oder API-User

Wenn du beides anbietet, ist das Pattern: Formular auf der Webseite mit "Anfragen"-Button für Schulen/Gruppen und "Direkt buchen"-Button für Privatpersonen.

Beziehungen

Tour
 ├── Category ............ z.B. Führung, Workshop, Vortrag
 ├── Museum .............. Haus
 ├── Exhibition (0..1) ... Sonderausstellung
 ├── Audience (0..n) ..... z.B. Familien, Schulklassen
 ├── AgeGroup (0..n) ..... z.B. Kinder, Erwachsene
 ├── Language (0..n) ..... welche Sprachen werden angeboten
 ├── Guide (0..n) ........ welche Guides sind qualifiziert
 ├── Equipment (0..n) .... benötigte Hilfsmittel
 ├── Request (über items) wenn als Anfrage eingegangen
 └── OrderItem .......... wenn direkt gebucht

Stolperdrahte

  • Anfragen brauchen API-User-Token. Anders als Tour-Listing oder Preisberechnung (Public-Token reicht) erfordert POST /requests einen authentifizierten API-User mit Permission. Token im Frontend nicht offenlegen - die Anfrage muss serverseitig durchgereicht werden.
  • start_times mit participants aufrufen. Wer die Teilnehmerzahl weglässt, bekommt Verfügbarkeit für die min_persons der Tour. Das ist nicht falsch, aber bei großen Gruppen oft optimistisch - am Tag der Buchung kann die Gruppe nicht mehr passen.
  • prices ist kontextabhängig. Ohne price_target_audience_id fällt der Endpoint auf die Default-PTA (z.B. "Privatkunde") zurück. Für Reseller, Schulklassen oder Mitglieder unbedingt explizit angeben, sonst rechnest du mit den falschen Tarifen.
  • depth bei start_times macht den Unterschied. any ist deutlich günstiger und ausreichend für Datepicker-Logik. all lohnt sich erst, wenn Slots auf einem Tag angezeigt werden.
  • start_times hat ein 60-Tage-Limit. Für längere Vorschau-Zeiträume mehrere Calls. In der Praxis selten ein Problem, weil Datepicker ohnehin meist nur den aktuellen oder kommenden Monat zeigen.
  • Translated names statt IDs. Die Anfrage akzeptiert language: "Deutsch" zusätzlich zur ID. Praktisch für Formulare ohne ID-Lookup, aber dann muss der Wert exakt mit der hinterlegten Übersetzung übereinstimmen.

Verwandte Seiten