Die go~mus-API ist offen, mit ihr lässt sich fast alles bauen. Damit du nicht in den gleichen Fallen landet wie andere vor dir, hier eine kompakte Liste an Praktiken, die sich bewährt haben.
Caching ist Pflicht, nicht Empfehlung
Stammdaten täglich pollen und cachen. Verfügbarkeiten live, aber nicht pro Endkunden-Request. Direkt-Live-Traffic auf Stammdaten wird abgelehnt und kommt nicht in Produktion. Mehr Details unter Datenaktualität: Pull statt Push.
Konkrete Cache-Layer, die sich bewährt haben:
- HTTP-Cache mit korrekten
max-age-Headern auf Reverse-Proxy-Ebene (Varnish, Cloudflare, nginx) - Application-Cache (Redis, Memcached) mit expliziter Invalidierung beim täglichen Sync-Job
- ETag- oder Last-Modified-basiert, wenn du conditional GETs nutzen willst
Fehler graziös behandeln
Order-Erstellung kann jederzeit fehlschlagen, auch nach erfolgreicher Reservation: Kapazität wurde reduziert, anderer Kanal hat schneller verkauft, Preisberechnung weicht ab. Du musst vorbereitet sein.
- 4xx von go~mus: Body lesen, Fehler dem Endkunden klar machen, ggf. Schritt zurück gehen
- 5xx von go~mus: retry mit exponential backoff, max 3 Versuche, dann freundliche Fehlermeldung
- Reservation läuft ab: redirect zur Auswahl, neue Verfügbarkeit prüfen
Eine Order kann nicht nachträglich bestätigt werden, wenn sie nie erstellt wurde. Niemals.
Pagination
Jeder Index-Endpoint paginiert. Default 25, kann pro Instanz variieren. Lest meta.total_count, meta.page, meta.per_page aus und blättert konsequent durch.
async function fetchAllTickets(token) {
const all = [];
let page = 1;
while (true) {
const res = await fetch(`https://demo.gomus.de/api/v4/tickets?page=${page}`, {
headers: { Authorization: `Bearer ${token}` }
});
const data = await res.json();
all.push(...data.tickets);
if (page >= Math.ceil(data.meta.total_count / data.meta.per_page)) break;
page++;
}
return all;
}
Multi-Locale in einem Roundtrip
Wenn DE und EN gebraucht werden, hängst du nicht zwei Calls hintereinander. Ein Call mit ?locale=de liefert beide.
Tokens server-seitig halten
Niemals Tokens im Browser-Bundle, nicht in Mobile-Apps, nicht in Frontend-JS. Tokens auf eurem Server, API-Calls proxen.
Total selbst berechnen, Server validiert
Bei der Order-Erstellung wird total als Summe aller Item-Preise mitgeschickt. go~mus rechnet selbst gegen, und nur wenn dein total zur Server-Berechnung passt, wird die Order angelegt. Diese Doppelberechnung schützt vor Preismanipulation und falsch konfigurierten Discounts.
Heißt: du berechnst den Preis client-/server-seitig auf deiner Seite, aus den Preisinformationen, die go~mus in den jeweiligen Stammdaten-Endpunkten liefert.
Wo die Preise pro Produkttyp herkommen:
- Tickets:
price_cents,discount,vat_pct,tax_includeddirekt aus dem Ticket-Objekt -GET /api/v4/ticketsoderGET /api/v4/tickets/:id. Der/capacity-Endpoint liefert nur Verfügbarkeiten, keine Preise. - Events (Termine):
prices-Array im Termin-Detail unterGET /api/v4/events/:event_id/dates/:id. Zwei Typen: Default-Price und Scale-Price (z.B. „regulär", „ermäßigt", mitscale_price_idundtitle). Pro Termin können mehrere Optionen vorliegen. - Tours: dedizierter Preis-Endpunkt
GET /api/v4/tours/:id/prices. Default-, Scale- und Entgelttabellen-basierte Preise plus Zuschläge (Fremdsprache, Sonntag etc.). Pro Preis-Objekt gebengroup(Pauschal vs. pro Teilnehmer) undoptional(Pflicht vs. Wahl) das Verhalten an. Preise hängen ab von Datum, Uhrzeit, Teilnehmerzahl, Kunden-Kategorie und Sprache.
Wenn der Server deinen total ablehnt: Stammdaten frisch holen (Cache-Invalidierung), neu berechnen, neuer Versuch. Häufig veränderte Preise oder Discount-Konfigurationen sind die Ursache.
foreign_id für Customer-Mapping
Wenn du ein eigenes CRM haben, hängt eine foreign_id an Customer-Records. Beim nächsten Update referenzierst du via foreign_id statt go~mus-ID. Spart Mapping-Tabelle. Mehr in foreign_id-Pattern.
Logging
Logge jeden API-Call: Timestamp, Endpoint, HTTP-Status, Response-Time, Token-Identifier (nicht Token selbst). Bei Support-Tickets brauchst du das, um die Fehlerursache rückwärts nachzuvollziehen.
Was nicht loggen: Tokens, Customer-PII, Bestellungen mit Klartext-Daten. Logs sind Audit-Material, kein Datenarchiv.
Idempotenz und Wiederholungen
Bei Netzwerkfehlern weißt du nicht, ob die Order durch ist. Was du weißt musst:
- Reservation: nicht idempotent. Gleicher Aufruf erzeugt eine zweite Reservation. Reservations können nicht via API abgefragt werden. Bei Timeout nicht versuchen, die alte wiederzufinden, sondern sie nach 5 Minuten von selbst auslaufen lassen und einen neuen Capacity-Check + Reservation starten.
- Order anlegen: nicht idempotent, aber go~mus storniert nicht-finalisierte Orders nach kurzer Zeit automatisch (Auto-Cancel). Bei Timeout also einfach den Vorgang neu starten, doppelte halb-erstellte Orders verschwinden von selbst.
- Finalize: idempotent, kannst du wiederholen.
Beispielcode-Repos
- gomus-public-iframe-example: Iframe-Embedding mit Resize-Handling
Was kaputt gehen wird
Pläne, die in der Praxis schiefgehen:
- „Wir cachen die Verfügbarkeiten 5 Minuten, das wird reichen." → Ausverkaufte Termine werden weiterverkauft, Kunden sind sauer.
- „Wir berechnen den Preis selbst aus Listenpreisen." → Bei Discounts, Sonderaktionen, Dynamic Pricing greift die Server-Validierung und du hast einen Bug auf eurer Seite.
- „Wir holen die Tokens über AJAX im Browser." → Token im Browser = Token public. Sofortige Rotation nötig.
Wenn du nicht weiterkommt
Schreibe mit dem konkreten API-Call, Timestamp, erwartetem vs. tatsächlichem Verhalten an support@giantmonkey.de. Häufige Ursache von Fehlern: ein alter oder falscher Token. Hilfreich daher: die letzten vier Zeichen des verwendeten Tokens mitschicken, oder gleich den vollen Token - wir rotieren ihn danach. Je präziser die Frage, desto schneller die Antwort.