Zum Hauptinhalt springen

GraphQL-Überblick

Tourfold stellt neben der REST-API auch eine GraphQL-API bereit. Sie existiert für genau eine Aufgabe, die die REST-Oberfläche nur unzureichend erfüllt: das Lesen von Custom-Object-Datensätzen mit Filtern, Sortierung, Paginierung und Relationsnavigation in einer einzigen Anfrage — gegen ein Schema, das aus Ihren eigenen Objektdefinitionen erzeugt wird.

Was sie abdeckt und was nicht​

QueriesCustom-Object-Datensätze und die Relationen zwischen ihnen.
MutationsKeine. GraphQL ist ausschließlich lesend. Anlegen, Ändern und Löschen laufen über die REST-Endpoints für Custom Objects.
SubscriptionsKeine. Für Änderungsbenachrichtigungen nutzen Sie Webhooks.
KernressourcenNicht verfügbar. Touren, Jobs, Gebiete, Benutzer, Fahrzeuge und Dokumente gibt es nur über REST.

Das Schema ist spezifisch für Ihren Workspace. Es wird aus Ihren Custom-Object-Definitionen abgeleitet: Zwei Workspaces haben also unterschiedliche Typen, und Ihres ändert sich, sobald Sie ein Feld oder eine Relation hinzufügen. Deshalb wird kein statisches Schemadokument veröffentlicht — Sie laden das aktuelle Schema von der API herunter (siehe Schema und Benennung).

Endpoints​

AbfragePOST https://api.tourfold.com/api/v2/graphql
Schema (SDL)GET https://api.tourfold.com/api/v2/graphql/schema

Beide benötigen Authorization: Bearer <token> und beide benötigen ein Schreibrecht auf Custom Objects — siehe Authentifizierung und Berechtigungen, wo erklärt wird, warum Lesen derzeit ein Schreibrecht erfordert.

Anfrageformat​

POST /api/v2/graphql erwartet den üblichen JSON-Envelope von GraphQL over HTTP:

FeldTypHinweise
queryStringPflichtfeld. Das auszuführende Dokument. Maximal 10.000 Zeichen.
variablesObjectOptional. Werte für die Variablendefinitionen des Dokuments.
operationNameStringOptional. Nur erforderlich, wenn query mehr als eine Operation enthält.

operationName behält die GraphQL-eigene camelCase-Schreibweise und folgt nicht der snake_case-Konvention des Tourfold-REST-JSON: Dieser Envelope gehört zum GraphQL-Protokoll, nicht zum REST-Vertrag.

Schnellstart​

Jedes Wurzelfeld ist eine Relay-Connection; Sie selektieren also über edges { node { … } } statt eine einfache Liste zu lesen. Es gibt kein limit-Argument — die Seitengröße wird über first (oder last) gesteuert, siehe Paginierung.

Die Beispiele in diesem Abschnitt verwenden zwei Custom Objects eines fiktiven Workspace, Alpine Facility Services: equipment (Gebäudetechnik, z. B. ein Kälteaggregat) und maintenance_request, verknüpft so, dass jedes Gerät viele Wartungsanfragen hat. Passen Sie die Feldnamen an Ihr eigenes Schema an.

quickstart-first-page.graphql
query FirstEquipmentPage {
equipment(first: 2, order_by: [{ name: asc }]) {
totalCount
pageInfo {
hasNextPage
endCursor
}
edges {
cursor
node {
id
name
asset_tag
operational
}
}
}
}
curl -X POST "https://api.tourfold.com/api/v2/graphql" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"query": "query FirstEquipmentPage { equipment(first: 2, order_by: [{ name: asc }]) { totalCount pageInfo { hasNextPage endCursor } edges { cursor node { id name asset_tag operational } } } }",
"operationName": "FirstEquipmentPage"
}'
{
"data": {
"equipment": {
"totalCount": 3,
"pageInfo": { "hasNextPage": true, "endCursor": "Y3Vyc29yOjE=" },
"edges": [
{
"cursor": "Y3Vyc29yOjA=",
"node": {
"id": "6f3d2a10-0000-4000-8000-000000000101",
"name": "Basement Chiller CH-02",
"asset_tag": "AFS-CH-02",
"operational": true
}
},
{
"cursor": "Y3Vyc29yOjE=",
"node": {
"id": "6f3d2a10-0000-4000-8000-000000000102",
"name": "Passenger Lift LIFT-01",
"asset_tag": "AFS-LIFT-01",
"operational": true
}
}
]
}
},
"extensions": {
"cost": { "estimated_rows": 23, "limit": 100000 }
}
}

Antworten melden ihre Kosten​

Eine Antwort enthält extensions.cost, sofern die Anfrage die Kostenanalyse erreicht hat: estimated_rows ist der vom Server berechnete Umfang, auf den die Antwort anwachsen kann, und limit das Budget, an dem er gemessen wird. Der Wert wird auch bei Erfolg gemeldet, nicht nur bei Ablehnungen — so können Sie ein Dokument anpassen, bevor es zurückgewiesen wird.

Er fehlt, wenn die Anfrage vor der Analyse gescheitert ist — bei einem Syntax- oder Validierungsfehler. Behandeln Sie ihn daher als optional. Siehe Fehler und Limits.

Fehler​

Es gibt zwei grundlegend verschiedene Fehlerarten, und sie sehen nicht gleich aus:

  • Transportfehler — fehlendes oder abgelaufenes Token, fehlerhafter JSON-Body, ein query über der Grenze von 10.000 Zeichen — kommen als HTTP 4xx mit einem Problemdokument nach RFC 9457.
  • Abfragefehler — alles, was die GraphQL-Engine oder Tourfold am Dokument selbst ablehnt — kommen mit HTTP 200 und einem errors-Array im Body. data kann dabei teilweise gefüllt sein.

Schließen Sie niemals allein vom Statuscode auf Erfolg: Prüfen Sie auf errors. Alle Details, samt dem Katalog der stabilen extensions.code-Werte, finden Sie unter Fehler und Limits.

Typischer Ablauf​

  1. Besorgen Sie sich ein Bearer-Token genau wie für REST, mit einem Schreibrecht auf Custom Objects (Authentifizierung und Berechtigungen).
  2. Laden Sie das Schema Ihres Workspace von GET /api/v2/graphql/schema herunter und richten Sie Ihren GraphQL-Client oder Ihre IDE darauf aus (Schema und Benennung).
  3. Bauen Sie Abfragen mit where und order_by (Filtern und Sortieren).
  4. Paginieren Sie mit first/after (Paginierung).
  5. Beobachten Sie extensions.cost und bleiben Sie innerhalb der dokumentierten Limits (Fehler und Limits).