Im Gegensatz zu car2go bietet drive-now momentan leider (und unverständlicherweise) keine offene API für seine Fahrzeugdaten an. Nach meinem ersten Wurf für eine car2go Java Library wollte ich mich davon aber nicht stoppen lassen und habe mir einmal genauer angesehen, woher denn die Webseite ihre Daten bezieht. Erfreulicherweise findet sich dort recht schöne JSON-API, so dass dem Datenabruf (für mich war ohnehin nur der lesende Zugriff interessant) kein Problem zu sein schien.
Die Städte-Liste lädt die Webseite z.b. über https://api2.drive-now.com/cities?expand=cities – Doch ein GET auf diesen URI bringt erstmal Ernüchterung:
{"code":403,"message":"Permission denied."}
Doch nach etwas scharfem Hinsehen wird schnell klar was die Website anders macht. Das Javascript dort sendet zusätzlich einen „X-Api-Key“-Header im Request. Schickt man diesen mit, dann sieht das Ergebnis schon anders aus:
{ "count": 8, "items": [ { "businessAreaUrl": "https:\/\/api2.drive-now.com\/geodata\/6099\/6099.kml", "callCenterPhoneNumber": "+49 \/ 800 \/ 7234070", "carTypes": { "count": 0, "items": [] }, "cars": { "count": 0, "items": [] }, "chargingStations": { "count": 0, "items": [] }, "cityImageBaseUrl": "https:\/\/prod.drive-now-content.com\/fileadmin\/user_upload_global\/assets\/city\/{city}\/{color}\/{density}\/city.png", "countryLabel": "Germany", "fuelTypes": { "count": 0, "items": [] }, "id": "6099", "isoCountryCode": "DE", "latitude": 52.506629, "longitude": 13.381492, "mobileBusinessAreaUrl": "https:\/\/api2.drive-now.com\/geodata\/6099\/6099_mobile.kml", "name": "Berlin", "parkingSpaces": { "count": 0, "items": [] }, "petrolStations": { "count": 0, "items": [] }, "prolongAvailable": true, "registrationStations": { "count": 0, "items": [] }, "routingCityName": "berlin", "routingCountryName": "germany", "showBusinessAreaByDefault": false, "showChargingStationVisible": true, "showPetrolStationVisible": true, "showRegistrationStationVisible": true, "transmissionTypes": { "count": 0, "items": [] } }, ... }
Die Struktur sieht auf den ersten Blick etwas merkwürdig aus, aber auf jeden Fall erhält man Infos über alle aktiven Städte. Die Attribute sind dabei recht selbsterklärend, so dass nicht im Detail darauf eingehen werde. Lediglich die numerische „id“ (= CityId) ist von hervorgehobener Bedeutung, die wird später nämlich noch benötigt. Auffällig sind auch die diversen leeren Arrays „mit“ fehlenden Infos: „carTypes“, „cars“, „fuelTypes“, „parkingSpaces“, …
Also die URL nochmal genauer betrachtet und am „expand=cities“ hängen geblieben. Was wenn ich „carTypes“ sehen möchte?
https://api2.drive-now.com/cities?expand=carTypes liefert die Antwort:
{ "count": 8, "items": [ { "businessAreaUrl": "https:\/\/dev.service.drive-now.com\/geodata\/6099\/6099.kml", "callCenterPhoneNumber": "+49 \/ 800 \/ 7234070", "carTypes": { "count": 6, "items": [ { "carImageUrl": "https:\/\/de.drive-now.com\/static\/drivenow\/img\/cars\/mini.png", "group": "MINI", "make": "BMW", "modelIdentifier": "mini", "modelName": "MINI", "series": "MINI", "variant": "" }, { "carImageUrl": "https:\/\/de.drive-now.com\/static\/drivenow\/img\/cars\/mini_clubman.png", "group": "MINI", "make": "BMW", "modelIdentifier": "mini_clubman", "modelName": "MINI Clubman", "series": "MINI", "variant": "Clubman" }, { "carImageUrl": "https:\/\/de.drive-now.com\/static\/drivenow\/img\/cars\/mini_countryman.png", "group": "MINI", "make": "BMW", "modelIdentifier": "mini_countryman", "modelName": "MINI Countryman", "series": "MINI", "variant": "Countryman" }, { "carImageUrl": "https:\/\/de.drive-now.com\/static\/drivenow\/img\/cars\/bmw_1er.png", "group": "BMW", "make": "BMW", "modelIdentifier": "bmw_1er", "modelName": "BMW 1er", "series": "1er", "variant": "" }, { "carImageUrl": "https:\/\/de.drive-now.com\/static\/drivenow\/img\/cars\/bmw_activee.png", "group": "BMW", "make": "BMW", "modelIdentifier": "bmw_activee", "modelName": "BMW ActiveE", "series": "ActiveE", "variant": "" }, { "carImageUrl": "https:\/\/de.drive-now.com\/static\/drivenow\/img\/cars\/bmw_active_e.png", "group": "BMW", "make": "BMW", "modelIdentifier": "bmw_active_e", "modelName": "BMW ACTIVE E", "series": "ACTIVE E", "variant": "" } ] }, "cars": { "count": 0, "items": [] }, "chargingStations": { "count": 0, "items": [] }, ...
Siehe da: Fahrzeugtypen! Und auch für die anderen Arrays funktioniert das wunderbar. Auch ein „expand=full“ ist verfügbar und liefert die Inhalte aller Arrays, wobei die Ladezeiten hier vermuten lassen, dass man sich damit bei den Sys-Admins von Drive-Now keine Freunde macht.
Etwas fokussierter wird das ganze aber mit folgender URI: https://api2.drive-now.com/cities/4604?expand=full Das Ergebnis sind alle Daten für die CityId 4604 (München). Auch die anderen expand-Werte funktionieren hier wieder.
Aber es geht noch spezifischer: https://api2.drive-now.com/cities/4604/cars liefert ausschließlich die Autos für München, ohne die City Informationen als Wrapper-Objekt.
Im Ergebnis des „expand=cities“-Aufrufes kann man außerdem sehen, dass unter https://api2.drive-now.com/geodata/4604/4604.kml bzw. https://api2.drive-now.com/geodata/4604/4604_mobile.kml ein KML des jeweiligen Geschäftsgebietes zu finden ist (wobei ich noch keine Muse hatte den Unterschied der _mobile Version näher zu betrachten. Infos dazu gerne in die Kommentare). Im Gegensatz zu den anderen URIs, ist für die KMLs kein API-Key notwendig.
Wirklich erheiternd wird das ganze allerdings, wenn man sich das Javascript der Webseite etwas genauer ansieht, weil man z.B. auf der Suche nach einem funktionierenden API-Key zum testen ist. Dort finden sich nämlich solche Schmankerl (URLs leicht verfremdet):
getNApiUrl: function() { return this.napiUrl = "entw" === this.getEnv() || "dev" === this.getEnv() ? "https://xxx.service.drive-now.com/" : "stage" === this.getEnv() ? "https://other-xxx.service.drive-now.com/" : "https://api2.drive-now.com/", this.napiUrl
Nicht weiter schlimm, schließlich fehlt der API-Key? Nunja:
return r.getEnv() === "entw" || r.getEnv() === "dev" ? t = "ichBinDerDevAPIKey" : r.getEnv() === "stage" ? t = "ichBinDerStageAPIKey" : t = "ichBinDerDevAPIKey", $("html").hasClass("phmode") ? $.extend(e, {
Aber Entwicklungssystem sind doch bestimmt nicht von extern erreichbar! Nunja²:
{ "businessAreaUrl": "https:\/\/dev.service.drive-now.com\/geodata\/1774\/1774.kml", "callCenterPhoneNumber": "+49 \/ 800 \/ 7234070", "carTypes": { "count": 4, "items": [ { "carImageUrl": "https:\/\/de.drive-now.com\/static\/drivenow\/img\/cars\/mini.png", "group": "MINI", "make": "BMW", "modelIdentifier": "mini", "modelName": "MINI", "series": "MINI", "variant": "" }, { "carImageUrl": "https:\/\/de.drive-now.com\/static\/drivenow\/img\/cars\/bmw_1er.png", "group": "BMW", "make": "BMW", "modelIdentifier": "bmw_1er", "modelName": "BMW 1er", "series": "1er", "variant": "" }, { "carImageUrl": "https:\/\/de.drive-now.com\/static\/drivenow\/img\/cars\/for_transit_100_d.png", "group": "FOR", "make": "FOR", "modelIdentifier": "for_transit_100_d", "modelName": "FOR TRANSIT 100 D", "series": "TRANSIT 100", "variant": "D" }, { "carImageUrl": "https:\/\/de.drive-now.com\/static\/drivenow\/img\/cars\/for_transit_80_d.png", "group": "FOR", "make": "FOR", "modelIdentifier": "for_transit_80_d", "modelName": "FOR TRANSIT 80 D", "series": "TRANSIT 80", "variant": "D" ...
Doch, ist es! Und es ist spannend, denn die letzten beiden Fahrzeugtypen kommen doch eher überraschend. Ob das als Ankündigung zu verstehen ist oder die Entwickler eine merkwürdige Auswahl an Test-Daten getroffen haben bleibt aber natürlich offen.
Der Fairness halber habe ich Drive-Now vor > 2 Wochen auf ihr eigenes „Überangebot“ an APIs hingewiesen. Trotz Versprechen das an die Technik weiterzuleiten, ist (trotz zwischenzeitlichem Javascript-Code-Update auf der Seite) aber bisher alles weiterhin frei zugänglich.
Meine Anfrage nach einem eigenen API-Key wurde außerdem leider ohne weitere Begründung abgelehnt.
Hey. Wie sende ich den x-api-key mit? Bin grade etwas am rumspielen 🙂
Hast du es geschafft? Ich weiß garnicht wie ich anfangen soll, würde aber auch gerne bisschen was probieren/lesen 😀
würde mich sehr über Hilfe freuen 🙂
Was genau geschafft?
Kommt natürlich darauf an mit was du darauf zugreifen willst. Mit PHP geht das z.B. so:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url );
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Accept: application/json;v=1.2',
'X-Api-Key: '. $api_key,
'Accept-Language: en_EN'
));
$content = curl_exec( $ch );
Wenn ich bespielsweise einfach die JSON im Browser anzeigen lassen will … kann ich in der URL den xapi mit anhängen?
Danke 🙂
Nicht dass ich wüsste. Ich habe es nur im Header getestet.
Schade, dass es keine offizielle Dive-Now API gibt und nachfragen auch nichts hilft 🙁
Halte ich auch für wenig klug, aber das hat bestimmt gaaaaanz sinnvolle Gründe!
Hallo Claus,
toller Beitrag, sehr interessant.
Habe gerade versucht, dein PHP Request-Code zum laufen zu bekommen, und bestimmt 2 Stunden daran verzweifelt, dass ich ein „Permission denied.“ bekomme… Stellt sich heraus, dass ich meine Variable $apikey nannte, bei deinem Codeschnipsel heißt sie „$api_key“ (Hat schon ein Grund, warum ich mit Skriptsprachen nicht so klar komme *gg*)
Für alle, die es gerne im Browser testen wollen, es gibt das Firefox Add-On TamperData, womit man die Http-Requests vor dem Absenden manipulieren kann, da könnt ihr dann den X-Api-Key hinzufügen.
Grüße, Eugen
Hi Claus!
Thank you so much for the informative review.
I have a question though, I can’t find anywhere online how to get an api key from drive now!
How did you get one?
Regards
Unfortunately they have not yet understood the benefits of an open API, so they did not provide me with my own key (even though I asked). Nevertheless their own API key is easly extracted from the their website 😉
Hi ,
gibt es einen Weg die Fahrgestellnummer (VIN) über solche Abfragen herauszufinden ?
Gab es, inzwischen wurden die APIs aber alle mit viel (unsinnigem) Aufwand versteckt. Allerdings haben DN und car2go bei ihrem Merge die Auflage bekommen wieder offene Schnittstellen anzubieten, d.h. evtl. ist das bald wieder möglich.
Das ist ja spannnend. Weißt du ob es da ein Update gibt? Wann ist der Merge denn vollzogen?
Nope, keine Infos.