Zum Hauptinhalt springen

Grundlagen

OpenAPI-Spezifikation​

API-Endpoints​

  • Produktion: https://api.tourfold.com/api/v2/

Namenskonventionen​

Die REST-API verwendet einheitliche Benennungen in Payloads und URLs.

JSON-Schlüssel​

Alle JSON-Schlüssel verwenden snake_case:

{
"id": "a1b2c3d4-e5f6-4a1b-8c9d-123456789abc",
"created_at": "2024-01-15T10:30:00Z",
"phone_number": "+43 1 2345678",
"location_coordinates": {
"latitude": 48.2038,
"longitude": 16.3698
}
}

URL-Pfade​

URL-Pfadsegmente verwenden kebab-case. Pfadparameter-Platzhalter erhalten aussagekräftige Namen in snake_case. Eine undurchsichtige Ressourcen-ID wird als {resource_id} bezeichnet; andere Bezeichner benennen ihre tatsächliche Bedeutung, etwa {resource_slug}, {resource_key} oder {resource_number}. Allgemeine Platzhalter wie {id}, {slug} und {type} werden nicht verwendet:

# Ressourcen-Endpoints
GET /api/v2/brands
GET /api/v2/brands/{brand_id}
GET /api/v2/brands/{brand_id}/custom-domains/{custom_domain_id}

# Verschachtelte Ressourcen
GET /api/v2/users/{user_id}/skills
GET /api/v2/users/{user_id}/tags

# Aktions-Endpoints
POST /api/v2/devices/{device_id}/activate
POST /api/v2/devices/{device_id}/deactivate
POST /api/v2/users/{user_id}/deactivate

# Ein Slug wird nicht als ID bezeichnet
GET /api/v2/custom-objects/definitions/{definition_slug}

Query-Parameter​

Alle Query-Parameter verwenden aussagekräftige Namen in snake_case; Query-Namen in camelCase werden nicht verwendet:

# Paginierung
GET /api/v2/areas?page=0&size=20

# Filterung
GET /api/v2/users?status=ACTIVE&role_ids=b2c3d4e5-f6a1-4b2c-9d0e-234567890bcd

# Freitextsuche und ein begrenztes, nicht paginiertes Ergebnis
GET /api/v2/comments/mention-suggestions?search=ali&target_type=user&limit=10

# Mehrere Werte wiederholen denselben pluralischen Schlüssel
GET /api/v2/comments/counts?target_type=tour&target_ids=a1b2c3d4-e5f6-4a1b-8c9d-123456789abc&target_ids=b2c3d4e5-f6a1-4b2c-9d0e-234567890bcd

# Sortierung
GET /api/v2/areas?sort=created_at:asc&sort=updated_at:desc

Query-Parameter mit Array-Werten verwenden in OpenAPI style: form mit explode: true. Senden Sie jeden Wert als eigenes Vorkommen desselben pluralischen Parameternamens, wie im target_ids-Beispiel oben. Senden Sie weder einen kommagetrennten Wert (target_ids=a,b) noch einen wiederholten Schlüssel im Singular (target_id=a&target_id=b). Generierte Clients nehmen ein Array entgegen und serialisieren es in dieser Form mit wiederholtem Schlüssel. Etablierte Query-Steuerparameter wie sort und include behalten auch bei Wiederholung ihre semantischen Namen.

Kommas haben in Query-Parametern der Tourfold-eigenen REST-APIs keine strukturelle Bedeutung. Sortierkriterien verwenden feld:richtung; unterstützt eine Operation mehrere Sortierfelder, wird sort wiederholt. Strukturierte skalare Werte verwenden getrennte benannte Parameter statt positioneller Tupel, zum Beispiel target_lat=48.2082&target_lon=16.3738. Enthält ein einzelner Stringwert eines Arrays ein Komma, muss es als %2C percent-kodiert werden; ein wörtliches Komma in einem Array-Parameter wird mit 422 abgelehnt. Kommas sind in sort niemals Nutzdaten, daher werden dort sowohl wörtliche als auch percent-kodierte Kommaformen mit 422 abgelehnt.

Die extern kompatible BW-EBA-API ist die einzige Ausnahme und behält ihr separat dokumentiertes Wire-Format.

Lebenszyklus-Aktionen​

Aktionen für den Lebenszyklus öffentlicher Ressourcen verwenden activate und deactivate. unblock bleibt der Wiederherstellung nach einer Sicherheitssperre vorbehalten, etwa dem Aufheben einer Benutzersperre nach fehlgeschlagenen Anmeldeversuchen. enable und disable bezeichnen Fähigkeiten, Konfigurationsschalter und Provider-Interna, nicht den öffentlichen Lebenszyklus einer Ressource.

Request-Body (JSON)​

Verwenden Sie beim Senden von Daten in Request-Bodies snake_case für alle Feldnamen:

{
"name": "Vienna Central",
"description": "Innerstädtische Zustellzone für die Bezirke 1–9",
"color": "#3B82F6",
"zip_ranges": [
{
"from": "1010",
"to": "1090"
}
]
}

Content-Type: Verwenden Sie application/json für POST/PUT-Bodies. Für PATCH verwenden Sie application/merge-patch+json (RFC 7386); application/json wird als Alias mit derselben Weglassen/null-Semantik akzeptiert. Siehe Ressourcen erstellen & aktualisieren.

curl -X POST "https://api.tourfold.com/api/v2/areas" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{
"name": "Vienna Central",
"description": "Innerstädtische Zustellzone",
"color": "#3B82F6"
}'

Das Schreibmodell — partielle Aktualisierungen mit PATCH, das Leeren von Feldern mit null, das Ersetzen ganzer Mengen mit PUT sowie optimistische Nebenläufigkeit über lock_version — finden Sie unter Ressourcen erstellen & aktualisieren.

OpenAPI-Schemanamen​

OpenAPI-Komponentennamen beschreiben das öffentliche Konzept und keine Implementierungsklasse. Ressourcenschemas verwenden ein Substantiv im Singular (Area), Schreib-Requests spiegeln das Verb der Operation wider (CreateArea, UpdateArea) und Listenhüllen verwenden die Form <Ressource>List im Singular (AreaList, DeletedEventList). Öffentliche Schemanamen enthalten keine Implementierungssuffixe wie Request, Response, DTO oder Dto.

Abgeschlossene Wertemengen​

Endliche, von Tourfold definierte Auswahlmengen werden als OpenAPI-Enums veröffentlicht und nicht als uneingeschränkte Strings, deren gültige Werte nur im Beschreibungstext stehen. Generierte Clients stellen dadurch einen passenden Enum- oder String-Union-Typ bereit:

GET /api/v2/users?status=ACTIVE

Der Benutzerstatusfilter akzeptiert zum Beispiel ausschließlich ACTIVE, BLOCKED, INACTIVE oder ALL. Nicht unterstützte Werte liefern eine feldbezogene 422-Antwort; sie werden niemals stillschweigend als Standardwert interpretiert.

Bewusst erweiterbare Werte bleiben Strings. Dazu gehören registrierte Ressourcen-/Typ-Slugs, MIME-Typen und von externen Anbietern definierte Statuswerte, die sich unabhängig weiterentwickeln können. Eine deploymentspezifische Auswahl wird nur dann als abgeschlossene Menge veröffentlicht, wenn die API zusätzlich einen von Clients nutzbaren Discovery-Vertrag bereitstellt.

Telefonnummern​

Tourfold-eigene Telefonnummernfelder erfordern eine internationale Nummer mit einer expliziten Ländervorwahl nach +. Übliche Schreibweisen werden akzeptiert und vor Suche oder Speicherung normalisiert:

+43 (664) 123-45-67 → +436641234567

Antworten enthalten immer kanonisches E.164. Nationale Werte wie 06641234567 und internationale Verkehrsausscheidungsziffern wie 00436641234567 werden mit einem feldbezogenen 422 abgelehnt; die API nimmt niemals Österreich oder ein anderes Land als Standard an. Der separat dokumentierte BW-EBA-Vertrag und BW-eigene Kontaktdaten fallen nicht unter diese Regel.

Datums- und Zeitformate​

Die REST-API verwendet standardisierte Datums- und Zeitformate gemäß den RFC-Spezifikationen.

DateTime-Felder​

Alle Datums-/Zeit-Felder verwenden das RFC-3339-Format (eine Teilmenge von ISO 8601):

{
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T11:45:30.123Z",
"scheduled_start": "2024-01-15T14:00:00+01:00",
"completed_at": "2024-01-15T16:30:00Z"
}

Format: YYYY-MM-DDTHH:mm:ss.sssZ oder YYYY-MM-DDTHH:mm:ss.sss±HH:mm

  • Z: UTC-Zeitzone (z. B. 2024-01-15T10:30:00Z)
  • ±HH:mm: Zeitzonen-Offset (z. B. 2024-01-15T10:30:00+01:00 für Mitteleuropäische Zeit)

Standard-Zeitzone: Die Tourfold-API verwendet UTC (Z) als Standard-Zeitzone für alle Datums-/Zeit-Felder. Wird keine Zeitzone angegeben, werden Zeiten als UTC interpretiert.

Datumsfelder​

Reine Datumsfelder verwenden das RFC-3339-Datumsformat:

{
"valid_from": "2024-01-01",
"valid_until": "2024-12-31"
}

Format: YYYY-MM-DD

Zeitfelder​

Reine Zeitfelder verwenden das RFC-3339-Zeitformat:

{
"departure_time": "14:30:00",
"arrival_time": "16:45:00",
"break_duration": "00:30:00"
}

Format: HH:mm:ss oder HH:mm:ss.sss

Dauer-Felder​

Dauer-Felder verwenden das ISO-8601-Dauerformat:

{
"estimated_duration": "PT2H30M",
"processing_time": "PT45M",
"break_time": "PT15M"
}

Format: PTnHnMnS (Period of Time: Stunden, Minuten, Sekunden)

Beispiele​

# Anfrage mit Datums-/Zeit-Parametern
curl "https://api.tourfold.com/api/v2/audit-logs?created_from=2024-01-15T00:00:00Z&created_to=2024-01-16T23:59:59Z" \
-H "Authorization: Bearer YOUR_TOKEN"

# Antwort mit Datums-/Zeit-Feldern
{
"id": "a1b2c3d4-e5f6-4a1b-8c9d-123456789abc",
"name": "Vienna Central",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T11:45:30.123Z"
}

Gängige Muster​

ID-Felder​

Alle Ressourcen-IDs sind typischerweise UUIDs (Universally Unique Identifiers) und folgen einheitlichen Namensmustern:

Beispiel – Benutzer-Ressource:

{
"id": "a1b2c3d4-e5f6-4a1b-8c9d-123456789abc",
"brand_id": "b2c3d4e5-f6a1-4b2c-9d0e-234567890bcd",
"role_id": "c3d4e5f6-a1b2-4c3d-0e1f-345678901cde",
"skill_id": "d4e5f6a1-b2c3-4d4e-1f2a-456789012def"
}

Format: UUID-Format (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)

Namenskonvention:

  • Primäre ID: id – der eigene Bezeichner der Ressource (z. B. die ID des Benutzers)
  • Fremdschlüssel: {entity}_id – Verweise auf andere Entitäten (z. B. verweist brand_id auf eine Marke)

Boolean-Felder​

Boolean-Felder verwenden beschreibende Namen:

{
"is_active": true,
"is_default": true,
"requires_confirmation": false,
"can_resend_set_password_email": true
}

Array-Felder​

Array-Felder verwenden Substantive im Plural:

{
"skills": [...],
"roles": [...],
"tags": [...],
"zip_ranges": [...]
}

Optionale Felder und null​

Antworten lassen Eigenschaften ohne Wert weg — die API sendet niemals "field": null über die Leitung. Ein fehlender Schlüssel bedeutet daher „kein Wert", und ein vorhandener Schlüssel trägt stets einen echten Wert. Felder, die immer befüllt sind (Bezeichner, Zeitstempel, Status), werden nie weggelassen.

{
"id": "a1b2c3d4-e5f6-4a1b-8c9d-123456789abc",
"name": "Vienna Depot",
"created_at": "2024-01-15T10:30:00Z"
}

Diese Ressource hat keine Beschreibung, daher fehlt der Schlüssel einfach, statt als "description": null zurückgegeben zu werden. Clients sollten einen fehlenden Schlüssel als „nicht gesetzt" behandeln.

Ein explizites null ist nur in einem PATCH-Request-Body (Merge Patch) von Bedeutung, wo es ein leerbares Feld löscht — siehe Ressourcen erstellen & aktualisieren → Ein optionales Feld leeren.

Antworten für einzelne Ressourcen​

Einzelne Ressourcen werden direkt im Wurzelobjekt zurückgegeben, ohne Ummantelung:

{
"id": "a1b2c3d4-e5f6-4a1b-8c9d-123456789abc",
"name": "Vienna Central",
"color": "#3B82F6",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z"
}

Listenantworten​

Jede Listenantwort kapselt Ressourcen in einem items-Array. Paginierte Antworten enthalten zusätzlich page; bei nicht paginierten Listen entfällt dieses Feld:

{
"items": [
{
"id": "a1b2c3d4-e5f6-4a1b-8c9d-123456789abc",
"name": "Vienna Central",
"color": "#3B82F6",
"created_at": "2024-01-15T10:30:00Z"
},
{
"id": "b2c3d4e5-f6a1-4b2c-9d0e-234567890bcd",
"name": "Salzburg Region",
"color": "#10B981",
"created_at": "2024-01-15T11:00:00Z"
}
],
"page": {
"size": 20,
"total_elements": 150,
"total_pages": 8,
"number": 0
}
}

Hinweis: Einzelne Ressourcen werden direkt zurückgegeben. Listenantworten stellen ihre Sammlung immer unter items bereit, nie unter einem ressourcenspezifischen Schlüssel.

API-Versionierung​

Die REST-API verwendet eine URL-basierte Versionierung, um Stabilität und Abwärtskompatibilität sicherzustellen:

Versionsstrategie​

  • Nie entfernen, nur hinzufügen: Neue Versionen wahren die volle Abwärtskompatibilität
  • Breaking Changes: Nur in neuen Hauptversionen (v2, v3 usw.) eingeführt
  • Aktuelle Version: /api/v2/ – stabil und vollständig unterstützt

Versions-URLs​

# Aktuelle stabile Version
GET https://api.tourfold.com/api/v2/areas

# Zukünftige Versionen (bei Bedarf)
GET https://api.tourfold.com/api/v3/areas
GET https://api.tourfold.com/api/v4/areas