Dieser Artikel richtet sich an Entwickler, die Aufträge programmatisch an einen Lieferpartner senden möchten, der MotionTools verwendet.
Überblick
Um eine Bestellung an einen MotionTools-betriebenen Lieferpartner zu senden, nutzt du die MotionTools REST API. Weitere Ressourcen und Anleitungen findest du in unserem Help Center.
MotionTools ist eine Multi-Tenant-Plattform, bei der jeder Lieferpartner seinen eigenen Tenant hat. Du sendest Bestellungen an deinen Lieferpartner über ein Konto mit der customer
Rolle.
Wenn du die URL zum Tenant deines Lieferpartners kennst, kannst du selbst ein Kundenkonto erstellen.
Alternativ kannst du deinen Lieferpartner kontaktieren, um ein Kundenkonto zu erhalten.
Du kannst Bestellungen senden, indem du entweder Buchungen oder Pakete über die API erstellst. Wenn du eine Buchung oder ein Paket erstellst, erhältst du als Antwort ein Buchungen/Pakete-Objekt, das deine Bestellung in MotionTools repräsentiert. Erfahre mehr in unseren ausführlichen Artikeln:
Dieses Dokument beschreibt die Integration von Buchungen.
Im Hintergrund werden dann entweder automatisch oder manuell eine oder mehrere Bestellungen (Buchungen oder Pakete) zu optimierten Touren zusammengefasst. Sobald sie sich in einer Tour befinden, können die Mitarbeiter des Lieferpartners mit der Ausführung deiner Bestellung beginnen.
Du kannst den Fortschritt deiner Bestellung auf zwei Arten verfolgen. Du kannst:
regelmäßig die Buchung oder das Paket, das dich interessiert, über die MotionTools API abrufen
Wie bereits erwähnt, interagierst du mit der MotionTools API über ein Konto mit der customer
Rolle. Bestimmte API-Endpunkte oder Aktionen erfordern die admin
Rolle. Solche Aktionen sind in diesem Artikel entsprechend gekennzeichnet. Bitte kontaktiere deinen Lieferpartner oder den MotionTools Support, um dabei Unterstützung zu erhalten. Mehr über Rollen in MotionTools findest du hier
Um eine Verbindung zwischen der Buchung oder dem Paket in MotionTools und der Bestellung in deinem System herzustellen, solltest du unsere Metadaten-Funktion verwenden.
Zu beachtende Aspekte
Modellierung deiner Aufträge: Buchungen vs. Pakete
Bestimmte Betreiber arbeiten ausschließlich mit Buchungen, andere nur mit Paketen. Stelle sicher, dass dein gewünschter Workflow vom Lieferpartner unterstützt wird.
🚴♂️ Buchungen:
Eine Buchung ist eine Anfrage von einem Kunden zur Durchführung eines Service. [...] Sie kann einen oder mehrere Stopps beinhalten. Ein Stop ist eine Aufgabe, die an einem bestimmten Ort ausgeführt werden muss.
📦 Pakete:
Ein Paket ist ein individuell verfolgbarer Gegenstand, der typischerweise eigene Eigenschaften wie Größe oder Gewicht hat, mit einem scannbaren Etikett versehen ist und als Abholungs- oder Zustellungsaufgabe einem Stop hinzugefügt werden kann.
Um Pakete nutzen zu können, muss dein Lieferpartner die Paketerweiterung in seinem Tenant aktiviert haben.
Obwohl es einige Überschneidungen zwischen den beiden Konzepten gibt, werden Buchungen in der Regel gewählt, wenn es darum geht, Aufgaben oder kurze Lieferungen zu verfolgen. Pakete eignen sich dagegen besser für die Verfolgung von Gegenständen oder für große Lieferungen mit Dutzenden oder Hunderten von Paketen innerhalb einer Route.
Was den Integrationsaufwand betrifft, ist der Einstieg mit Buchungen einfacher, da sie im Vergleich zu Paketen relativ unkompliziert sind. Pakete bringen, wie bereits erwähnt, zusätzliche Eigenschaften (Größe, Gewicht), Konzepte (scannbares Etikett), Interaktions- und Tracking-Abläufe, Preisgestaltung, Lebenszyklus usw. mit sich. All dies ist zwar nützlich für große Paketlieferungen, wird aber nicht immer für kurze Lieferungen benötigt.
Auch wenn es möglich ist, eine einfache Restaurant → Kunden-Lieferung mit Paketen zu modellieren, bei der die Essenstasche als Paket in MotionTools dargestellt wird, empfehlen wir für diesen speziellen Fall generell Buchungen, da der Fokus auf der Durchführung der Lieferung liegt und nicht auf der Essenstasche selbst.
Der Rest dieses Artikels konzentriert sich auf Buchungen.
Ausführungsmodi: Sofort vs. Geplant
Bei der Erstellung einer Buchung kannst du eine Verzögerung oder Vorlaufzeit zwischen dem Moment der Erstellung und dem Zeitpunkt, an dem der Lieferpartner mit der Ausführung beginnen soll, festlegen.
Aktuell stehen zwei Optionen zur Verfügung: instant
& scheduled
Buchungen:
Sofortige Buchungen: zeigen an, dass die Buchung sofort ohne Vorlaufzeit ausgeführt werden soll
Geplante Buchungen: zeigen an, dass sie zu einem späteren Zeitpunkt ausgeführt werden sollen, bekannt als
scheduled_at
Zeit.
Weitere Details hier.
Zeitfenster
MotionTools ermöglicht es dir, genau festzulegen, wann ein Fahrer an jedem einzelnen Stopp der Buchung ankommen soll (earliest_arrival_at
, latest_arrival_at
). Zusätzlich kannst du die erwartete Dauer eines Stopps angeben (custom_expected_duration_seconds
). Details findest du in der Payload-Beschreibung des Create Booking Endpunkts im Modell booking.stops
.
Buchungsverlauf
Es ist wichtig, die 3 Hauptkomponenten zu unterscheiden, die eine Bestellung und ihren Fortschritt in MotionTools abbilden: Buchung, Stopp, Tour.
Der Gesamtablauf ist wie folgt:
Über die API erstellst du eine Buchung mit einem Konto, das die Rolle
customer
hat. Abhängig vom Planungsmodus und der Dispositions-Konfiguration werden die Stopps deiner Buchung dann in eine oder mehrere optimierte Touren eingeplant, entweder sofort oder zu einem bestimmten Zeitpunkt in der Zukunft. Die Dispositions-Entscheidung wird entweder manuell vom Betreiber oder automatisch vom System basierend auf den Regeln des Betreibers getroffen.
Hinweis: Normalerweise werden die Stopps einer Buchung in dieselbe Tour eingeplant, aber das ist nicht immer der Fall. In bestimmten Fällen und Optimierungsstrategien kann es vorkommen, dass verschiedene Stopps derselben Buchung auf verschiedene Touren aufgeteilt werden. Deshalb speichert der Stopp die ID der Tour, in die er eingeplant wurde, nicht die Buchung selbst. Mehr dazu weiter unten.
Als Konto mit der Rolle
customer
hast du keinen Zugriff auf die resultierenden Touren. Nur Konten mit den Rollenadmin
,organization manager
&driver
haben Zugriff auf Touren.Jeder Stopp in deiner Buchung enthält Informationen über die Tour, in die er eingeplant wurde, über die folgenden Eigenschaften:
dispatched_hailing_booking_id
-> die ID der Tour, in die dieser Stopp eingeplant wurde. Hinweis: Der Name dieses Feldes könnte in Zukunft geändert werden, um besser zu verdeutlichen, dass es sich um eine Tour und nicht um eine Buchung handelt.child_id
-> die ID des entsprechenden Stopps innerhalb der Tour. Die ID des Tour-Stopps unterscheidet sich von der ID des Stopps in der ursprünglichen Buchung, da es sich im Wesentlichen um ein anderes Objekt handelt, das das Original spiegelt.
Um den Fortschritt deiner Buchung zu verfolgen, musst du Folgendes im Auge behalten:
Die Buchung, die du erstellt hast, hauptsächlich über Webhooks, die über Aktualisierungen des Buchungsstatus informieren.
Um mehr über das Statusmodell von Buchungen und dessen Beziehung zum Statusmodell einer Tour zu erfahren, lies bitte: Statusmodell von Buchungen
Die Touren und äquivalenten Tour-Stopps, in die deine ursprünglichen Stopps eingeplant wurden.
Tour-Lebenszyklus-Ereignisse sind insbesondere detaillierter im Vergleich zu Buchungs-Lebenszyklus-Ereignissen und helfen dir, bestimmte Schlüsselpunkte zu identifizieren, die nicht transparent sind, wenn du nur auf Buchungsstatus-Updates achtest. Ein Beispiel dafür wäre der Moment, in dem ein Fahrer zugewiesen wurde und mit der Ausführung einer bestimmten Tour begonnen hat.
Tour- und Tour-Stopp-Lebenszyklus-Ereignisse werden über spezielle Webhooks mitgeteilt. Du musst dann die in diesen Webhooks erwähnten Tour- und Tour-Stopp-IDs mit den in deinen Buchungs-Stopps referenzierten IDs abgleichen, im vorgenannten
child_id
für Lebenszyklus-Ereignisse eines bestimmten Tour-Stopps unddispatched_hailing_booking_id
für Lebenszyklus-Ereignisse der Tour selbst.
Die relevanten Webhooks und ihre Payloads werden im Abschnitt Updates über Webhooks empfangen ausführlicher beschrieben.
Füge deine Bestellungs-ID als externe ID zu einer Buchung hinzu
Um eine Verbindung zwischen verschiedenen Eigenschaften deines internen Bestellungsmodells (z.B. Bestellungs-id
) und der resultierenden Buchung in MotionTools herzustellen, kannst du diese Eigenschaften als Metadaten zur Buchung, zum Stopp oder zu beidem hinzufügen.
Derzeit unterstützen wir das direkte Hinzufügen von Buchungs-/Stopp-Metadaten bei der Erstellung der Buchung nicht. Um Metadaten zu Buchungen und Stopps hinzuzufügen, musst du zusätzliche Aufrufe an unsere dedizierten Endpunkte senden:
Buchung: Metadaten ändern
Buchung: Metadaten teilweise ändern
Stopp: Metadaten ändern
Stopp: Metadaten teilweise ändern
Buchungs- vs. Stopp-Metadaten
Wenn eine Buchung in eine optimierte Tour zur Ausführung durch den Lieferpartner übertragen wird, werden die Metadaten der Buchung nicht in die Tour-Metadaten kopiert. Dies geschieht, weil eine Tour aus mehreren verschiedenen Buchungen erstellt werden kann.
Die Stopp-Metadaten sind jedoch im entsprechenden Stopp innerhalb der Tour vorhanden, da die Buchungs-Stopps selbst im Wesentlichen in die Tour kopiert werden.
Praktisch bedeutet dies, dass es am besten ist, relevante Metadaten sowohl bei der Buchung als auch bei den enthaltenen Stopps zu platzieren:
Buchungs-Metadaten: helfen dir, die interne Bestellung anhand der Metadaten in der MotionTools-Buchung zu identifizieren
Stopp-Metadaten (bei jedem einzelnen Stopp der Buchung): hilft dem Lieferpartner zu erkennen, welcher Stopp in einer Tour zu einer bestimmten Bestellung aus deinem internen System gehört
Neben der internen Bestellungs-ID können Metadaten verwendet werden, um beliebige nützliche Werte aus deiner ursprünglichen Bestellung in Buchungen/Stopps (und mehr) zu speichern. Beispiele könnten die Kunden-ID, Kundenbewertung, interner Preis, interne Lieferprognose usw. sein.
Voraussetzungen für die Integration
Um dich mit deinem durch MotionTools gestützten Lieferpartner zu integrieren, benötigst du Folgendes:
Kundenkonto: im MotionTools Tenant deines Lieferpartners
Kunden-API-Token: Sobald du Zugang zu deinem Konto hast, musst du einen API-Token erstellen.
service_id
: Diese wird dir vom Lieferpartner zur Verfügung gestellt und muss beim Erstellen einer Buchung angegeben werden. Wenn der Lieferpartner nur den "Standard-Service" nutzt, kann dieservice_id
beim Erstellen der Buchung weggelassen werden. Mehr über Services findest du hier.
Eine Bestellung per API senden
Bitte lies dir Kunde: Eine Buchung über die API erstellen durch
API-Endpunkt Dokumentation: CreateHailingBooking
Beispiel-Payload für eine Abholung, angepasst für Essenslieferungen (zum Anzeigen ausklappen)
Beispiel-Payload für eine Abholung, angepasst für Essenslieferungen (zum Anzeigen ausklappen)
{ "booking": { "stops": [ { "type": "pickup", "earliest_arrival_at": null, "latest_arrival_at": null, "place_id": "7d6991cb-d669-40ae-acb7-6a2b964e212b", // add a valid place id for the pickup location "additional_information": "info for pickup, e.g. order id or name", "metadata": { "public_order_id": "value", "external_order_id": "value" }, }, { "type": "dropoff", "earliest_arrival_at": null, "latest_arrival_at": null, "lat": 53.54439, // optional, MotionTools will geocode if n/a "lng": 9.940334, "street": "Große Elbstraße", "number": "123", "zip_code": "20097", "city": "Hamburg", "country": "Deutschland", "location_name": "Große Elbstraße 123", "first_name": "Vorname", "last_name": "Nachname", "phone_number": "+491601234123", "additional_information": "Please don't ring the bell", "metadata": { "public_order_id": "value", "external_order_id": "value" }, } ], "scheduled_at": "now" // if you only push bookings for now, you can leave this out, otherwise you can add a timestamp, please note that only timestamps in the future are allowed and they have to be within the opening hours of the operator. Scheduled_at is typically the time when you want a driver to pickup the order from the restaurant. } }
Gib die Kontaktdaten des Endempfängers der Bestellung als Stopp-Kontaktdaten beim Auslieferungsstopp an, damit Fahrer/Kuriere deines Lieferpartners den Endempfänger kontaktieren können, wenn sie die Buchung bearbeiten.
Updates über Webhooks empfangen
Das Einrichten von Webhooks kann nur von admin
Nutzern vorgenommen werden.
Um einen Webhook zu erstellen, musst du die URL, an die du Webhooks empfangen möchtest, entweder mit einem Manager deines Lieferpartners (der admin
Zugriff haben sollte) oder mit dem MotionTools Support teilen. Außerdem musst du angeben, welche Events du empfangen möchtest und welche Filter gegebenenfalls angewendet werden sollen.
Allgemeine Informationen
MotionTools kann Statusaktualisierungen über Webhooks für fast jedes Ereignis senden, das in MotionTools stattfindet
Die Webhooks sind schlank gehalten und enthalten nur die wichtigsten Informationen, wie zum Beispiel das aufgetretene Ereignis und die Buchungs-ID
Wenn du detailliertere Informationen benötigst, musst du diese über den entsprechenden Endpunkt abrufen, nachdem du einen Webhook erhalten hast. Nutze dafür zum Beispiel den "Buchung anzeigen" Endpunkt
Die API-Dokumentation für Webhooks findest du hier: https://docs.motiontools.io/#tag/Webhooks
Um sicherzustellen, dass dein Webhook-Consumer-Endpunkt nur von authentischen MotionTools-Anfragen aufgerufen wird, haben wir eine Webhook-Verifizierung implementiert. Siehe: Webhook-Verifizierung
Relevante Webhooks
Buchungs- & Stopp-Statusaktualisierungen
Fahrer zugewiesen + auf dem Weg zur Abholung:
Zu verwendender Webhook:
tour.transition
Ordne
webhook.data.tour_id
dembooking.stop[].dispatched_hailing_booking_id
des Abholungsstopps zuRelevantes Ereignis:
start
Fahrer bei der Abholung angekommen:
Zu verwendender Webhook:
tour.stop_transition
Ordne
webhook.data.tour_id
derdispatched_hailing_booking_id
Eigenschaft des Abholungsstopps zuOrdne
webhook.data.stop_id
derbooking.stop[].child_id
des Abholungsstopps zuRelevantes Ereignis:
arrive
Fahrer hat die Abholung abgeschlossen:
Zu verwendender Webhook:
tour.stop_transition
Ordne
webhook.data.tour_id
derdispatched_hailing_booking_id
Eigenschaft des Abholungsstopps zuOrdne
webhook.data.stop_id
derbooking.stop[].child_id
des Abholungsstopps zuRelevantes Ereignis:
complete
Fahrer auf dem Weg zur Auslieferung:
Zu verwendender Webhook:
tour.stop_transition
Ordne
webhook.data.tour_id
derdispatched_hailing_booking_id
Eigenschaft des Auslieferungsstopps zuOrdne
webhook.data.stop_id
derbooking.stop[].child_id
des Auslieferungsstopps zuRelevantes Ereignis:
start
Fahrer bei der Auslieferung angekommen:
Zu verwendender Webhook:
tour.stop_transition
Ordne
webhook.data.tour_id
derdispatched_hailing_booking_id
Eigenschaft des Auslieferungsstopps zuOrdne
webhook.data.stop_id
derbooking.stop[].child_id
des Auslieferungsstopps zuRelevantes Ereignis:
arrive
Fahrer hat die Auslieferung abgeschlossen (sollte gleich dem Buchungsabschluss sein, du kannst entweder dies oder die nächste Option mit "Buchung abgeschlossen" implementieren):
Zu verwendender Webhook:
tour.stop_transition
Ordne
webhook.data.tour_id
derdispatched_hailing_booking_id
Eigenschaft des Auslieferungsstopps zuOrdne
webhook.data.stop_id
derbooking.stop[].child_id
des Auslieferungsstopps zuRelevantes Ereignis:
complete
Buchung abgeschlossen:
Zu verwendender Webhook:
booking.transition
Zuordnung über Buchungs-ID
Relevante Ereignisse:
complete_stops
oderforce_end
Buchungsstatus nach Ereignis:
paid
Buchung storniert:
Zu verwendender Webhook:
booking.transition
Zuordnung über Buchungs-ID
Relevante Ereignisse:
cancel
Buchungsstatus nach Ereignis:
cancelled
Fahrer-Standort-Updates
Rufe Fahrerdetails über den ShowBookingStopsDriverContactDetails Endpunkt ab
Aktuelle Ankunftszeiten
Aktion: Rufe Details über den EstimateBookingStopsArrivals Endpunkt ab
Zugehöriger Hilfe-Center Artikel: ETA Service über API integrieren
Buchungszyklus
Bitte lies dir den Statusmodell von Buchungen Artikel durch
Stopp-Zyklus
scheduled
→ Stopp noch nicht begonnenapproaching
→ Fahrer nähert sich dem Stopparrived
→ Fahrer ist am Stopp angekommendone
→ Fahrer hat den Stopp abgeschlossenfailed
→ Disponent hat den Stopp als fehlgeschlagen markiert (bei bestimmten Konfigurationen dürfen auch Fahrer einen Stopp als fehlgeschlagen markieren)
Webhook-Verifizierung
Um zu überprüfen, ob ein eingehender Webhook-Request nicht böswillig gefälscht oder modifiziert wurde, fügen wir eine Signatur als Teil der Request-Header hinzu. Du musst die Signatur auf deiner Seite gegen den öffentlichen Schlüssel validieren, den du von deinem Lieferpartner erhalten hast, als dieser den Webhook konfiguriert hat.
Als Verschlüsselungsalgorithmus wird Ed25519
verwendet, und die Signatur wird Base64-kodiert im X-Mtools-Signature
Request-Header übermittelt.
TypeScript-Beispiel eines Cloudflare Workers zur Überprüfung der Webhook-Authentizität
TypeScript-Beispiel eines Cloudflare Workers zur Überprüfung der Webhook-Authentizität
Das folgende Beispiel ist für die Cloudflare Workers/Deno-Laufzeitumgebung geeignet. Wenn du eine andere JavaScript-Laufzeitumgebung wie NodeJs oder Bun verwendest, wird das Beispiel nicht ohne Anpassungen funktionieren. In NodeJs verwendest du zum Beispiel Ed25519
statt NODE-ED25519
als Algorithmus-Bezeichner. Auch bei der Interaktion mit der crypto
-Bibliothek kann es Unterschiede geben. Das folgende Beispiel dient nur zur Veranschaulichung. Bitte passe es entsprechend an die Anforderungen deiner Laufzeitumgebung an.
// Replace this with your actual public key (Base64-encoded)const PUBLIC_KEY_BASE64 = 'YOUR_PUBLIC_KEY_HERE';export default { async fetch(request: Request): Promise<Response> { // Read body as ArrayBuffer (Uint8Array required for crypto.subtle) const body = new Uint8Array(await request.arrayBuffer()); // Get signature from header (Base64-encoded) const signatureBase64 = request.headers.get('X-Mtools-Signature'); if (!signatureBase64) { return new Response('Missing signature header', { status: 400 }); } const signature = Uint8Array.from(atob(signatureBase64), c => c.charCodeAt(0)); // Decode public key const publicKey = Uint8Array.from(atob(PUBLIC_KEY_BASE64), c => c.charCodeAt(0)); // Import public key for Ed25519 verify const cryptoKey = await crypto.subtle.importKey( 'raw', publicKey, { name: 'NODE-ED25519', namedCurve: 'NODE-ED25519' }, // For Deno/Cloudflare false, ['verify'] ); // Verify signature const isValid = await crypto.subtle.verify( 'NODE-ED25519', cryptoKey, signature, body ); if (!isValid) { return new Response('Invalid signature', { status: 401 }); } // Signature valid, process webhook try { await procesWebhook(body) return new Response('Webhook verified!', { status: 200 }); } catch (e) { return new Response('Internal server error: error processing webhook.', { status: 500 }); } }};
Richtlinien zur Nutzung von Webhooks
Um die Leistungsstabilität unserer Plattform zu gewährleisten, gelten folgende Einschränkungen für Webhook-Empfänger:
Wir erwarten einen gültigen
2xx
Antwort-Code, um die Zustellung eines Webhook-Events als erfolgreich zu betrachten.15 Sekunden Timeout: Wenn keine
2xx
Antwort innerhalb von 15 Sekunden erfolgt, betrachten wir die Zustellung als fehlgeschlagen.3 Wiederholungsversuche: Jedes Webhook-Event wird 3 Mal wiederholt. Nach 3 Versuchen wird das Webhook-Event nicht mehr erneut gesendet und ist damit verloren.
250 aufeinanderfolgende fehlgeschlagene Zustellungen an dieselbe URL führen zur Blockierung/Deaktivierung des Webhooks und lösen eine E-Mail-Benachrichtigung an den Tenant-Besitzer aus (in diesem Fall dein Lieferpartner). Sollte dies passieren, wird entweder dein Lieferpartner oder der MotionTools-Support dich kontaktieren.
Webhook-Filterung
Wenn du Webhook-Events für Buchungen erhältst, die nicht zu dir gehören, hat dein Lieferpartner möglicherweise die Webhook-Filter nicht korrekt eingerichtet, als er den Webhook für dich konfiguriert hat.
Bitte kontaktiere deinen Lieferpartner, um dies anzupassen. Relevanter Artikel in unserem Help Center: Webhooks an deine Kunden für Buchungsstatus-Updates weiterleiten.
Technische Überlegungen & Empfehlungen
Webhook-Überlegungen
Datenvalidierung
Unsere API & Payload-Strukturen & Status-Modelle entwickeln sich ständig weiter.
Daher empfehlen wir dir:
keine strikte Validierung der Payload-Struktur vorzunehmen → deine Integration sollte nicht abstürzen, wenn neue Eigenschaften in einem MotionTools-Payload auftauchen, das du nutzt
keine strikte Validierung bekannter Schlüsselwerte als Enums (z.B. Status, Übergänge, andere Schlüsselwerte wie
now
für diebooking.scheduled_at
Eigenschaft) → deine Integration sollte fehlerfrei und ohne Abstürze mit neuen, unbekannten Status, Übergängen usw. umgehen können
Integration testen
Für Testzwecke bekommst du Zugriff auf deinen eigenen MotionTools-Mandanten, der dem Mandanten deines Lieferpartners sehr ähnlich sein wird. Dieser Mandant dient als deine Sandbox-Umgebung, in der du während der Entwicklung deiner Integration testen, iterieren und experimentieren kannst.
Beachte jedoch, dass du in dieser Entwicklungs-Sandbox-Umgebung Zugriff auf den Mandanten-admin
-Benutzer haben wirst, während du in der Produktionsumgebung nur Zugriff auf einen customer
-Benutzer im Produktionsmandanten deines Lieferpartners haben wirst.
Stelle daher sicher, dass du in deiner Sandbox-Umgebung auch einen customer
-Account anlegst und dessen API-Schlüssel (d.h. Schlüssel mit der customer
-Rolle) während der Entwicklung deiner Integration auf deinem Sandbox-Mandanten verwendest.