Grundlagen
OpenAPI-Spezifikation
- Im Browser ansehen: /openapi
- Herunterladen: OpenAPI-YAML
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:00fü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. verweistbrand_idauf 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