Entwickler
Drive Analytics API
Eine HTTP/JSON-REST-API für den programmatischen Zugriff auf deine eigenen Fahrzeug-, Fahrten-, Tank-, Wartungs-, Geofence- und Benachrichtigungsdaten. Authentifizierung über einen persönlichen API-Key. Jeder Aufruf ist strikt auf deinen Account beschränkt; geteilte Fahrzeuge siehst du lesend. Diese Seite ist die vollständige Referenz mit Beispiel-Requests, Beispiel-Antworten und einer Feld-Referenz.
Schnellstart
- In Einstellungen → API-Zugriff einen Key erstellen. Der Klartext wird einmalig angezeigt, kopiere ihn sofort.
- Den Key bei jeder Anfrage im
Authorization-Header mitschicken. - Loslegen, z. B. deine Fahrzeuge abrufen:
curl -H "Authorization: Bearer da_DEIN_KEY" \
https://driveanalytics.uk/api/v1/cars
Antwort:
{
"data": [
{
"id": 6,
"license_plate": "M-AB-1234",
"make": "Mercedes-Benz",
"model": "C 220 d",
"is_registered": true,
"access": "owner",
"current_mileage": 84210,
"position": { "lat": 52.5163, "lon": 13.3777, "fuel_percent": 64,
"voltage_v": 12.7, "seen_at": "2026-06-25T09:12:00+00:00" }
}
],
"meta": { "count": 1 }
}
Authentifizierung
Jede Anfrage braucht deinen API-Key als Bearer-Token im
Authorization-Header (alternativ der Header X-API-Key).
Keys beginnen mit da_. Auf dem Server wird nur ein Hash gespeichert,
der Klartext ist nach dem Erstellen nicht mehr abrufbar. Du kannst beliebig viele
Keys mit eigenen Namen anlegen (max. 20 aktiv) und einzeln widerrufen, ein
widerrufener Key wird sofort mit 401 abgelehnt.
Authorization: Bearer da_QMQvA2zPe8x1k... # empfohlen
X-API-Key: da_QMQvA2zPe8x1k... # Alternative
Basis-URL & Version
Alle Endpunkte liegen unter https://driveanalytics.uk/api/v1.
Die Versionsnummer im Pfad bleibt stabil; abwärtskompatible Ergänzungen (neue Felder/Endpunkte)
kommen ohne Versionswechsel dazu. Alle Anfragen laufen ausschließlich über HTTPS.
Antwort-Format
Erfolg, Einzelobjekt:
{ "data": { "id": 6, ... } }
Erfolg, Liste (mit meta):
{ "data": [ { ... }, { ... } ], "meta": { "count": 2, "limit": 50, "offset": 0 } }
- Zeitstempel: ISO 8601 mit Zeitzone (UTC), z. B.
2026-06-25T09:12:00+00:00. - Geldbeträge und Liter: Strings (volle Dezimal-Präzision), z. B.
"46.43". - Distanzen (m/km), Koordinaten, Geschwindigkeiten, Zähler und Scores: Zahlen.
nullbedeutet „nicht vorhanden / unbekannt".
Fehler
Fehler kommen als JSON mit passendem HTTP-Status:
{ "error": { "code": "forbidden", "message": "Nur der Besitzer kann Fahrten löschen." } }
| Status | code | Bedeutung |
|---|---|---|
| 400 | invalid | Ungültige Eingabe (z. B. fehlendes Feld) |
| 401 | unauthorized | Kein / ungültiger / widerrufener Key |
| 403 | forbidden | Kein Schreibrecht (z. B. geteiltes Fahrzeug) |
| 404 | not_found | Nicht gefunden oder kein Zugriff |
| 409 | uncategorized_trips | Export bei unkategorisierten Fahrten |
| 429 | rate_limited | Zu viele Anfragen |
Rate-Limits
120 Anfragen pro Minute je API-Key. Bei Überschreitung kommt
429 mit code: "rate_limited", warte dann kurz und wiederhole.
Paginierung & Filter
Listen unterstützen ?limit= (Standard 50, max. 200) und ?offset=.
Fahrten und der Export akzeptieren zusätzlich einen Zeitraum über
?from=YYYY-MM-DD und ?to=YYYY-MM-DD.
# Zweite Seite à 25, nur Juni 2026
curl -H "Authorization: Bearer da_DEIN_KEY" \
"https://driveanalytics.uk/api/v1/cars/6/trips?limit=25&offset=25&from=2026-06-01&to=2026-06-30"
Code-Beispiele
Dieselbe Anfrage (Fahrten eines Autos) in drei Sprachen:
cURL
curl -H "Authorization: Bearer $DA_KEY" \
"https://driveanalytics.uk/api/v1/cars/6/trips?limit=10"
JavaScript (fetch)
const res = await fetch(
"https://driveanalytics.uk/api/v1/cars/6/trips?limit=10",
{ headers: { Authorization: `Bearer ${process.env.DA_KEY}` } }
);
const { data, meta } = await res.json();
console.log(meta.count, data[0].distance_km);
Python (requests)
import os, requests
r = requests.get(
"https://driveanalytics.uk/api/v1/cars/6/trips",
params={"limit": 10},
headers={"Authorization": f"Bearer {os.environ['DA_KEY']}"},
)
r.raise_for_status()
for trip in r.json()["data"]:
print(trip["started_at"], trip["distance_km"], "km")
Objekt: Fahrzeug
Felder eines car-Objekts.
{
"id": 6, // int, eindeutige Fahrzeug-ID
"vin": "WVWZZZ1KZAW000000", // string|null, Fahrgestellnummer
"license_plate": "M-AB-1234", // string|null
"license_country": "D", // string|null
"make": "Mercedes-Benz", // string|null, Marke
"model": "C 220 d", // string|null
"first_registration": "2019-03-01", // date|null, Erstzulassung
"body_class": "Limousine", // string|null
"is_registered": true, // bool, aktiver Tracker?
"access": "owner", // "owner" | "manager" (Flotten-Verwalter) | "shared"
"current_mileage": 84210, // int|null, km
"odometer_auto": true, // bool, km automatisch via OBD?
"mileage_updated_at": "2026-06-25T09:12:00+00:00",
"manual_avg_fuel_l_per_100km": 7.5, // float|null, manueller Ø-Verbrauch
"learned_avg_fuel_l_per_100km": 6.8, // float|null, gelernt aus Tankbelegen
"estimated_avg_fuel_l_per_100km": 6.5, // float|null, typischer Modellwert
// Leiter für estimated_cost_eur:
// manuell > gelernt > typisch (gemessener
// Trip-Verbrauch gewinnt immer)
"position": { // object|null, letzte bekannte Position
"lat": 52.5163, "lon": 13.3777,
"fuel_percent": 64, // int|null, Tankfüllstand in %. Aus fuel_liters
// und tank_capacity_l, wo beides vorliegt,
// sonst der Sensorwert des Fahrzeugs
"fuel_liters": null, // int|null, gemessener Resttank in L
"tank_capacity_l": null, // int|null, eingetragene Tankgröße in L
"range_km": 540, // int|null
"voltage_v": 12.7, // float|null, Bordspannung
"dtc_codes": [], // string[], Fehlercodes
"seen_at": "2026-06-25T09:12:00+00:00",
// Zeitstempel des jüngsten Datensatzes,
// also wie aktuell die Position ist
"moved_at": "2026-06-25T08:55:00+00:00",
"packet_at": "2026-06-25T09:12:03+00:00",
// datetime|null, wann das Paket bei uns
// ankam. Puffert der Tracker im Funkloch und
// liefert später nach, ist seen_at deutlich
// älter als packet_at. Für „sendet das
// Gerät?" ist packet_at maßgeblich.
"moving": false, // bool, fährt das Auto gerade?
"speed_kmh": null // int|null, aktuelle Geschwindigkeit
// (nur während der Fahrt, sonst null)
},
"created_at": "2026-06-19T06:58:08+00:00"
}
Objekt: Fahrt
Die Übersicht (trip_summary); das Detail enthält zusätzlich route, speed_series, events, score_breakdown.
{
"id": 42, "car_id": 6,
"started_at": "2026-06-24T08:00:00+00:00",
"ended_at": "2026-06-24T08:30:00+00:00",
"duration_min": 30,
"distance_m": 18230,
"distance_km": 18.23,
"top_speed_kmh": 121,
"avg_fuel_l_per_100km": "6.4", // string|null
"estimated_cost_eur": "2.14", // string|null, geschätzte Kraftstoffkosten
"fuel_price_source": "Beleg 12.06.", // string|null, Basis der Schätzung; endet
// auf "· Ø-Verbrauch" (manueller Wert),
// "· Ø aus Tankbelegen" (gelernt) oder
// "· typischer Verbrauch" (Modellwert),
// wenn kein gemessener Trip-Verbrauch vorlag
"category": "business", // "private"|"business"|"commute"|null
"purpose": "Kundentermin Müller", // string|null (nur bei business)
"driver_id": 3, // int|null, Fahrer-Override (Geschäftskonto).
// Abgeleiteter Fahrer aus einer Zuordnung
// ist hier null; über /fleet/assignments
// rekonstruierbar.
"driving_score": 88, // int|null, 0–100
"event_count": 1, // Anzahl Ereignisse (harsh_brake, ...)
"shared": false,
"share_url": null // string|null, öffentlicher Link
}
Objekt: Tankrechnung
{
"id": 3, "car_id": 6,
"fueled_at": "2026-06-13T18:08:00+00:00",
"liters": "46.43", // string
"price_per_liter": "1.899", // string
"total_amount": "88.17", // string, in Originalwährung
"discount_amount": null, // string|null
"currency": "EUR",
"total_amount_eur": "88.17", // string, in EUR umgerechnet
"fx_rate": null, "fx_rate_date": null,
"fuel_type": "diesel", // e5|e10|super_plus|diesel|...
"station_name": "Shell Berlin",
"station_address": "...",
"status": "confirmed",
"owned": true, // false = geteiltes Fahrzeug (nur lesen)
"image_url": "/api/v1/fuel-receipts/3/image"
}
Objekte: Wartung, Geofence, Mitteilung, Batterie
Wartungsposition
{ "id": 12, "kind": "oil_change", "name": "Motoröl",
"interval_km": 10000, "interval_months": 12,
"last_service_date": "2025-11-02", "last_service_mileage": 71200,
"due_date": "2026-11-02", "due_km": 81200,
"severity": "ok", // "ok"|"warn"|"danger"
"notify_lead_times": ["1_month","1000_km"] }
Geofence-Zone
{ "id": 1, "name": "Zuhause", "lat": 52.5, "lon": 13.4,
"radius_m": 150, "notify_enter": true, "notify_leave": true, "enabled": true }
Mitteilung
{ "id": 87, "type": "theft", "priority": "critical",
"title": "Manipulationsversuch", "body": "...", "car_id": 6,
"deeplink_url": "/cars/6", "read": false, "read_at": null,
"created_at": "2026-06-24T18:30:00+00:00" }
Batterie-Gesundheit
{ "status": "good", // good|watch|critical|no_data
"label": "Gut", "resting_v": 12.7, "crank_min_v": 11.1,
"charge_max_v": 14.9, "charging_ok": true,
"trend": "stable", "days": 14, "note": "Batterie in gutem Zustand.",
"spark": [12.6, 12.7, 12.7] }
Endpunkte · Konto
Discovery-Index der Sammlungen.
Eigenes Konto-Profil (Name, E-Mail, Sprache, Zeitzone).
Endpunkte · Fahrzeuge
Liste aller zugänglichen Fahrzeuge (eigene + geteilte).
Einzelnes Fahrzeug inkl. Live-Position.
Batterie-Gesundheit (siehe Objekt oben).
Fahrten des Fahrzeugs. Query: limit, offset, from, to, q (Textsuche im Fahrt-Zweck).
Tankrechnungen des Fahrzeugs.
Aggregierte Tank-Kennzahlen (Ø/Monat, YTD, Ø Preis/Liter).
Wartungspositionen mit Fälligkeit (siehe Objekt).
Wartung quittieren. Besitzer oder Flotten-Verwalter. Mit „cost“ entsteht zugleich eine Kostenposition.
Request-Body (JSON)
{ "date": "2026-06-25", "mileage": 84210, "cost": "189,90", "currency": "EUR" } // alle optional
Endpunkte · Fahrten
Fahrt-Detail inkl. Route, Speed-Profil, Ereignissen.
Fahrt als GPX herunterladen (auch .kml). Route wird als Track exportiert.
Kategorie/Zweck und/oder Fahrer-Override setzen. driver_id nur im Geschäftskonto; null löscht den Override.
Request-Body (JSON)
{ "category": "business", "purpose": "Kundentermin Müller", "driver_id": 3 }
Sammel-Kategorisierung mehrerer Fahrten in einem Schritt (bis 200). Alles-oder-nichts: eine fremde Kennung lässt die ganze Anfrage scheitern (404).
Request-Body (JSON)
{ "ids": [12, 15, 18], "category": "business" }
Fahrt löschen. Nur Besitzer.
Öffentlichen, widerrufbaren Link erzeugen.
Beispiel-Antwort
{ "data": { "share_url": "https://driveanalytics.uk/t/AbC123", "token": "AbC123" } }
Teilen wieder aufheben.
Endpunkte · Tankrechnungen
Alle Tankrechnungen über deine Fahrzeuge.
Einzelne Tankrechnung.
Belegfoto als JPEG (kein JSON).
Tankrechnung löschen. Nur Besitzer.
Endpunkte · Suche
Globale Suche über Fahrzeuge, Fahrten (nach Zweck), Tankrechnungen (nach Tankstelle), Zonen und App-Seiten. Query: q (Pflicht). Liefert Gruppen mit Treffern (type, title, subtitle, url).
Endpunkte · Kosten
Kraftstoff kommt aus den Tankrechnungen und wird nicht über diese Endpunkte erfasst. Laufende Kosten (Versicherung, Steuer) werden anteilig auf den Zeitraum umgelegt, nicht als Einmalzahlung gezählt. km_source sagt, worauf die Kilometer beruhen: odometer (Tachostand) oder trips (nur aufgezeichnete Fahrten, Wert je Kilometer fällt dann eher zu hoch aus).
Kontoweite Kosten-Übersicht: alle Kostenarten (Monatsverlauf über 12 Monate, by_kind, Fahrzeug-Vergleich, cost_per_km_eur) plus geschätzte Aufteilung nach Fahrtzweck (category_split_estimated). Beträge als String, Währung EUR.
Kosten eines Fahrzeugs: Summe, Aufteilung nach Kostenart, Kosten je Kilometer, Einzelposten und laufende Positionen. Query: from, to (Standard letzte 12 Monate).
Einmalkosten erfassen. Nur Besitzer. kind: maintenance, repair, tires, inspection, insurance, tax, purchase, other. occurred_on nicht in der Zukunft, Standard heute.
Request-Body (JSON)
{ "kind": "repair", "amount": "249,90", "currency": "EUR",
"occurred_on": "2026-07-14", "mileage": 84210, "note": "Bremsen vorne" }
Kostenposition löschen. Nur Besitzer. Aus einer Wartung erzeugte Positionen verlieren dabei auch den Betrag an der Wartung.
Laufende Kosten anlegen. Nur Besitzer. kind: insurance, tax, parking, leasing, other. period: monthly, quarterly, yearly. ends_on leer = läuft weiter.
Request-Body (JSON)
{ "kind": "insurance", "amount": "480,00", "period": "yearly",
"starts_on": "2026-01-01", "note": "Haftpflicht plus Teilkasko" }
Laufende Kosten löschen. Nur Besitzer.
Endpunkte · Flotte
Nur für Geschäftskonten. Andere Konten erhalten 403.
Fahrer-Stammliste.
Fahrer ändern (name, email, active).
Request-Body (JSON)
{ "active": false }
Fahrer löschen. Zuordnungen entfallen, Fahrt-Overrides werden auf leer gesetzt.
Fahrer-Fahrzeug-Zuordnungen.
Zuordnung anlegen (überlappungsfrei je Fahrzeug). ends_on optional.
Request-Body (JSON)
{ "driver_id": 3, "car_id": 7, "starts_on": "2026-07-01", "ends_on": "2026-07-31" }
Zuordnung entfernen.
Monatsbericht je Fahrer und Fahrzeug (km, Fahrten, geschätzte Kosten) plus vehicle_costs: fahrzeuggebundene Kosten des Monats, die bewusst NICHT auf Fahrer verteilt werden. Query: year, month (Standard voriger Monat).
Endpunkte · Wartung
Siehe Fahrzeuge: GET /cars/{id}/maintenance und POST /cars/{id}/maintenance/{item_id}/done.
Endpunkte · Geofence-Zonen
Alle eigenen Zonen. Jede Zone trägt active_start_min/active_end_min (Minuten seit lokaler Mitternacht, null = ganztägig) und car_ids (leer = alle Fahrzeuge).
Zone anlegen. radius_m optional (Standard 200). active_start_min/active_end_min setzen ein Zeitfenster (z. B. 1320/360 = 22:00 bis 06:00), car_ids beschränkt auf Fahrzeuge.
Request-Body (JSON)
{ "name": "Zuhause", "lat": 52.5, "lon": 13.4, "radius_m": 150,
"notify_enter": true, "notify_leave": true,
"active_start_min": 1320, "active_end_min": 360, "car_ids": [7] }
Zone ändern. active_start_min/active_end_min auf gleich oder ungültig setzen = wieder ganztägig; car_ids: [] = wieder alle Fahrzeuge.
Request-Body (JSON)
{ "enabled": false, "active_start_min": 1320, "active_end_min": 360 }
Zone löschen. Entfernt auch den gesamten Verlauf dieser Zone.
Verlauf der Ein- und Austritte, neueste zuerst. direction ist "enter" oder "leave". notified sagt, ob eine Benachrichtigung entstanden ist: außerhalb des Zeitfensters einer Zone wird der Übergang aufgezeichnet, aber nicht gemeldet. limit (Standard 50, max. 200) und offset blättern, meta.total nennt die Gesamtzahl.
Alle eigenen Webhook-Ziele. Das Geheimnis steht NICHT in der Liste, es wird nur beim Anlegen einmal ausgegeben.
Ziel anlegen. Die Adresse muss https sein und oeffentlich aufloesen; interne Adressen werden abgelehnt. Moegliche Ereignisse: trip.completed, zone.entered, zone.left, alert.raised. Die Antwort enthaelt das Geheimnis genau einmal.
Request-Body (JSON)
{ "label": "Mein System", "url": "https://example.com/hook",
"events": ["zone.entered", "zone.left"] }
Ziel widerrufen. Bereits eingereihte Zustellungen werden nicht mehr versucht.
Verlauf eines Fahrzeugs über alle eigenen Zonen hinweg. Nur für eigene Fahrzeuge: die Zone ist eine Einstellung ihres Besitzers, ihr Verlauf gibt dessen Orte preis. Für ein lediglich freigegebenes Fahrzeug antwortet der Endpunkt mit 404.
Endpunkte · Benachrichtigungen
Mitteilungen (paginiert). Query: ?unread=1 für nur ungelesene. meta.unread enthält die Gesamtzahl.
Anzahl ungelesener Mitteilungen.
Eine Mitteilung als gelesen markieren.
Alle als gelesen markieren.
Endpunkte · Fahrtenbuch-Export
Fahrtenbuch als Datei. Query: format=pdf|csv|xlsx, from, to, car_id (optional). Liefert die Datei direkt (kein JSON).
Gibt es im Zeitraum unkategorisierte Fahrten, kommt 409 uncategorized_trips —
setze zuerst überall eine Kategorie via PATCH /api/v1/trips/{id}.
curl -L -H "Authorization: Bearer $DA_KEY" \
"https://driveanalytics.uk/api/v1/logbook/export?format=pdf&from=2026-01-01&to=2026-03-31" \
-o fahrtenbuch.pdf
API v1 · Diese Referenz wächst mit dem Produkt mit. Fehlt dir eine Funktion? Schreib uns.